diff options
| author | iamcheeseman <[hidden email]> | 2026-01-12 20:51:28 -0500 |
|---|---|---|
| committer | iamcheeseman <[hidden email]> | 2026-01-12 20:51:28 -0500 |
| commit | 7fb83578b99aa224f7545f4118a46e84b58a9295 (patch) | |
| tree | 515e294ac7de167c4501cc0a8d375b13213faf36 /src | |
| parent | 2b3a3ea9f4bc902b1b357fd149952d4570b25bf3 (diff) | |
NEW ASSET SYSTEM WOOOOOOOOHOOOOOOOOOOOOOOOOOOOOOOOOO
Diffstat (limited to 'src')
| -rw-r--r--[-rwxr-xr-x] | src/assets.odin | 106 | ||||
| -rw-r--r-- | src/draw/sprite.odin | 94 | ||||
| -rw-r--r-- | src/main.odin | 15 | ||||
| -rw-r--r-- | src/platform.odin | 18 | ||||
| -rw-r--r-- | src/player.odin | 50 | ||||
| -rw-r--r-- | src/resources.odin | 61 | ||||
| -rw-r--r-- | src/sprite.odin | 106 | ||||
| -rw-r--r-- | src/tiled/json.odin | 208 | ||||
| -rw-r--r-- | src/tiled/tiled.odin | 628 | ||||
| -rw-r--r-- | src/tiled/world.odin | 88 | ||||
| -rw-r--r-- | src/world.odin | 87 |
11 files changed, 362 insertions, 1099 deletions
diff --git a/src/assets.odin b/src/assets.odin index e74dcf8..b2222bb 100755..100644 --- a/src/assets.odin +++ b/src/assets.odin @@ -15,11 +15,12 @@ Image_Id :: enum { Animation_Id :: enum { PLAYER, + NONE, } -Map_Id :: enum { - ROOM_BEGIN_1, +Room_Id :: enum { ROOM_BEGIN, + ROOM_BEGIN_1, } Tileset_Id :: enum { @@ -29,50 +30,87 @@ Tileset_Id :: enum { Resource_Id :: union { Image_Id, Animation_Id, - Map_Id, + Room_Id, Tileset_Id, } -images: [Image_Id]Image_Resource -animations: [Animation_Id]Animation_Resource -maps: [Map_Id]Map_Resource -tilesets: [Tileset_Id]Tileset_Resource +images: [Image_Id]Image_Resource = { + .TILESETS = {data = #load("../.compiled-res/tilesets.qoi"), anim = .NONE}, + .PLAYER = {data = #load("../.compiled-res/player-sheet.qoi"), anim = .PLAYER}, +} -path_to_id: map[string]Resource_Id +animations: [Animation_Id]Animation_Resource = { + .PLAYER = {frame_count = 23, frame_durations = {100, 100, 100, 100, 100, 100, 75, 75, 75, 75, 75, 75, 75, 75, 100, 100, 100, 100, 100, 100, 100, 100, 100}, tags = {"idle"={from = 0, to = 5}, "jump_trans"={from = 16, to = 16}, "run"={from = 6, to = 13}, "jump_down"={from = 17, to = 18}, "jump_up"={from = 14, to = 15}, "sleep"={from = 19, to = 22}}}, + .NONE = {frame_count=1, frame_durations={100}, tags={}}, +} -load_resources :: proc() { - load_images() - load_anims() - load_maps() - load_tilesets() +rooms: [Room_Id]Room_Resource = { + .ROOM_BEGIN = {width=30, height=20, tile_width=16, tile_height=16, layers={{40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 27, 31, 31, 19, 19, 28, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 21, 31, 31, 31, 11, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 27, 31, 19, 31, 19, 19, 19, 31, 19, 31, 19, 19, 17, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 21, 31, 31, 31, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 40, 40, 21, 19, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 21, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 32, 0, 0, 0, 0, 0, 0, 5, 9, 20, 9, 20, 20, 20, 18, 20, 20, 18, 18, 9, 18, 9, 18, 6, 0, 0, 0, 0, 0, 7, 32, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 8, 0, 0, 0, 0, 0, 7, 11, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 38, 9, 9, 18, 18, 9, 39, 0, 0, 0, 5, 9, 20, 9, 44, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 20, 9, 18, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}}, objects={}, background_image=nil}, + .ROOM_BEGIN_1 = {width=30, height=20, tile_width=16, tile_height=16, layers={{40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 21, 19, 19, 19, 19, 31, 31, 28, 40, 40, 40, 40, 40, 40, 40, 27, 31, 19, 31, 31, 31, 19, 19, 31, 31, 31, 31, 19, 19, 19, 17, 0, 0, 0, 0, 0, 0, 10, 28, 40, 40, 21, 19, 31, 31, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 21, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 27, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 9, 20, 20, 20, 18, 18, 18, 20, 8, 0, 0, 0, 0, 0, 0, 5, 18, 9, 9, 20, 20, 20, 18, 9, 18, 9, 18, 18, 9, 39, 40, 40, 40, 40, 40, 40, 40, 40, 43, 20, 20, 9, 20, 9, 9, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}}, objects={}, background_image=nil}, +} - // Allow conversion from paths to a resource id, since it's a better way to - // reference resources in other resources (JSON is a good example). - path_to_id["res/tileset.tsj"] = Tileset_Id.TILESET - path_to_id["res/img/player.ase"] = Image_Id.PLAYER - path_to_id["res/img/tilesets.png"] = Image_Id.TILESETS - path_to_id["res/room_begin.tmj"] = Map_Id.ROOM_BEGIN - path_to_id["res/room_begin_1.tmj"] = Map_Id.ROOM_BEGIN_1 +tilesets: [Tileset_Id]Tileset_Resource = { + .TILESET = {tiles={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}, image=.TILESETS}, } -@(private="file") -load_images :: proc() { - images[.TILESETS] = {data = #load("/home/xswan/demonchime/.compiled-res/tilesets.qoi")} - images[.PLAYER] = {data = #load("/home/xswan/demonchime/.compiled-res/player-sheet.qoi")} +tiles: []Tile_Resource = { + {tileset=.TILESET, rect=Rect{start = {0, 0}, size = {16, 16}}, id=1, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {16, 0}, size = {16, 16}}, id=2, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {32, 0}, size = {16, 16}}, id=3, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {48, 0}, size = {16, 16}}, id=4, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {64, 0}, size = {16, 16}}, id=5, collisions={Rect{start = {8, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {80, 0}, size = {16, 16}}, id=6, collisions={Rect{start = {0, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {96, 0}, size = {16, 16}}, id=7, collisions={Rect{start = {8, 0}, size = {8, 16}}}}, + {tileset=.TILESET, rect=Rect{start = {112, 0}, size = {16, 16}}, id=8, collisions={Rect{start = {0, 0}, size = {8, 16}}}}, + {tileset=.TILESET, rect=Rect{start = {128, 0}, size = {16, 16}}, id=9, collisions={Rect{start = {0, 8}, size = {16, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {144, 0}, size = {16, 16}}, id=10, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {160, 0}, size = {16, 16}}, id=11, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {0, 16}, size = {16, 16}}, id=12, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {16, 16}, size = {16, 16}}, id=13, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {32, 16}, size = {16, 16}}, id=14, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {48, 16}, size = {16, 16}}, id=15, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {64, 16}, size = {16, 16}}, id=16, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {80, 16}, size = {16, 16}}, id=17, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {96, 16}, size = {16, 16}}, id=18, collisions={Rect{start = {0, 8}, size = {16, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {112, 16}, size = {16, 16}}, id=19, collisions={Rect{start = {0, 0}, size = {16, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {128, 16}, size = {16, 16}}, id=20, collisions={Rect{start = {0, 8}, size = {16, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {144, 16}, size = {16, 16}}, id=21, collisions={Rect{start = {8, 0}, size = {8, 8}}, Rect{start = {0, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {160, 16}, size = {16, 16}}, id=22, collisions={Rect{start = {8, 8}, size = {8, 8}}, Rect{start = {0, 0}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {0, 32}, size = {16, 16}}, id=23, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {16, 32}, size = {16, 16}}, id=24, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {32, 32}, size = {16, 16}}, id=25, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {48, 32}, size = {16, 16}}, id=26, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {64, 32}, size = {16, 16}}, id=27, collisions={Rect{start = {8, 0}, size = {8, 8}}, Rect{start = {0, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {80, 32}, size = {16, 16}}, id=28, collisions={Rect{start = {8, 8}, size = {8, 8}}, Rect{start = {0, 0}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {96, 32}, size = {16, 16}}, id=29, collisions={Rect{start = {0, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {112, 32}, size = {16, 16}}, id=30, collisions={Rect{start = {8, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {128, 32}, size = {16, 16}}, id=31, collisions={Rect{start = {0, 0}, size = {16, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {144, 32}, size = {16, 16}}, id=32, collisions={Rect{start = {0, 0}, size = {8, 16}}}}, + {tileset=.TILESET, rect=Rect{start = {160, 32}, size = {16, 16}}, id=33, collisions={Rect{start = {8, 0}, size = {8, 16}}}}, + {tileset=.TILESET, rect=Rect{start = {0, 48}, size = {16, 16}}, id=34, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {16, 48}, size = {16, 16}}, id=35, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {32, 48}, size = {16, 16}}, id=36, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {48, 48}, size = {16, 16}}, id=37, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {64, 48}, size = {16, 16}}, id=38, collisions={Rect{start = {0, 8}, size = {16, 8}}, Rect{start = {0, 0}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {80, 48}, size = {16, 16}}, id=39, collisions={Rect{start = {0, 8}, size = {16, 8}}, Rect{start = {8, 0}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {96, 48}, size = {16, 16}}, id=40, collisions={}}, + {tileset=.TILESET, rect=Rect{start = {112, 48}, size = {16, 16}}, id=41, collisions={Rect{start = {8, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {128, 48}, size = {16, 16}}, id=42, collisions={Rect{start = {0, 8}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {144, 48}, size = {16, 16}}, id=43, collisions={Rect{start = {0, 8}, size = {16, 8}}, Rect{start = {0, 0}, size = {8, 8}}}}, + {tileset=.TILESET, rect=Rect{start = {160, 48}, size = {16, 16}}, id=44, collisions={Rect{start = {0, 8}, size = {16, 8}}, Rect{start = {8, 0}, size = {8, 8}}}}, } -@(private="file") -load_anims :: proc() { - animations[.PLAYER] = {frame_count = 23, frame_durations = {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}, tags = {"jump_trans"={from = 16, to = 16}, "jump_down"={from = 17, to = 18}, "idle"={from = 0, to = 5}, "sleep"={from = 19, to = 22}, "jump_up"={from = 14, to = 15}, "run"={from = 6, to = 13}}} +world: []Room_Position_Resource = { + {id=.ROOM_BEGIN_1, x=-528, y=-64, width=480, height=320}, + {id=.ROOM_BEGIN, x=-48, y=-64, width=480, height=320}, } -@(private="file") -load_maps :: proc() { - maps[.ROOM_BEGIN_1] = #load("/home/xswan/demonchime/res/room_begin_1.tmj") - maps[.ROOM_BEGIN] = #load("/home/xswan/demonchime/res/room_begin.tmj") +path_to_id: map[string]Resource_Id = { + "res/img/player.ase" = Image_Id.PLAYER, + "res/img/tilesets.png" = Image_Id.TILESETS, + "res/room_begin.tmj" = Room_Id.ROOM_BEGIN, + "res/room_begin_1.tmj" = Room_Id.ROOM_BEGIN_1, } -@(private="file") -load_tilesets :: proc() { - tilesets[.TILESET] = #load("/home/xswan/demonchime/res/tileset.tsj") +load_resources :: proc() { } diff --git a/src/draw/sprite.odin b/src/draw/sprite.odin index ebe2e08..3a90dfe 100644 --- a/src/draw/sprite.odin +++ b/src/draw/sprite.odin @@ -4,97 +4,3 @@ import "core:log" import rl "vendor:raylib" -Sprite :: struct { - image: rl.Texture2D, - anim: Animation, - active_anim: u32, - frame_time: f32, - current_frame: i32, - - width: i32, - height: i32, - - pos: Vec2, - offset: Vec2, - rotation: f32, - scale: Vec2, - - just_finished_loop: bool, -} - -init_sprite :: proc( - sprite: ^Sprite, - path: string, - anim: Animation = {}, -) -> bool { - byte_path := make([]u8, len(path) + 1, context.temp_allocator) - copy(byte_path, path) - byte_path[len(path)] = 0 - - sprite.image = rl.LoadTexture(transmute(cstring)&byte_path[0]) - sprite.anim = anim - - sprite.width = i32(int(sprite.image.width) / len(sprite.anim.frames)) - sprite.height = i32(sprite.image.height) - - sprite.scale = Vec2{1, 1} - - log.debugf( - "loaded sprite '%v' %vx%v (%vx%v)", - path, - sprite.width, sprite.height, - sprite.image.width, sprite.image.height, - ) - - return true -} - -destroy_sprite :: proc(sprite: Sprite) { - rl.UnloadTexture(sprite.image) -} - -set_sprite_active_tag :: proc(sprite: ^Sprite, tag_name: string) { - sprite.active_anim = sprite.anim.frame_tags_indices[tag_name] -} - -update_sprite :: proc(sprite: ^Sprite, dt: f32) { - sprite.just_finished_loop = false - - sprite.frame_time += dt - - tag := sprite.anim.frame_tags[sprite.active_anim] - frame := sprite.anim.frames[sprite.current_frame] - duration := f32(frame.duration) / 1000 - - if sprite.frame_time > duration { - sprite.frame_time -= duration - sprite.current_frame += 1 - } - - if sprite.current_frame < tag.from { - sprite.current_frame = tag.to - sprite.just_finished_loop = true - } - if sprite.current_frame > tag.to { - sprite.current_frame = tag.from - sprite.just_finished_loop = true - } -} - -sprite :: proc( - sprite: Sprite, -) { - frame := sprite.anim.frames[sprite.current_frame] - - texture_quad( - sprite.image, - Rect { - Vec2{f32(frame.rect.x), f32(frame.rect.y)}, - Vec2{f32(frame.rect.w), f32(frame.rect.h)}, - }, - sprite.pos, - sprite.offset, - sprite.rotation, - sprite.scale, - ) -} diff --git a/src/main.odin b/src/main.odin index 508f97c..bed9861 100644 --- a/src/main.odin +++ b/src/main.odin @@ -9,12 +9,13 @@ import "base:runtime" import "core:log" import "core:fmt" import "core:mem" +import os "core:os/os2" import rl "vendor:raylib" import "draw" import "phys" -import "tiled" +// import "tiled" Vec2 :: [2]f32 @@ -55,6 +56,11 @@ logger: log.Logger // } // } +die :: proc(msg: string, args: ..any, #any_int exit_code := 1) { + log.fatalf(msg, args) + os.exit(exit_code) +} + init :: proc() { state.camera.zoom = 1 // state.camera.offset = {draw.SCREEN_WIDTH/2, draw.SCREEN_HEIGHT/2} @@ -71,8 +77,7 @@ init :: proc() { // } // state.room = room - tiled.load_world("res/map.world") - tiled.open_new_room_at({0, 0}) + open_room(.ROOM_BEGIN) setup_map_collisions() } @@ -85,7 +90,7 @@ frame :: proc() { rl.BeginMode2D(state.camera) draw_player() - tiled.draw_map(tiled.current_room.tmap) + draw_room(current_room.id) // draw_platforms() rl.EndMode2D() @@ -102,7 +107,6 @@ frame :: proc() { cleanup :: proc() { delete_player() delete_entity_list(state.platform_list) - tiled.delete_world() phys.destroy_world() } @@ -159,3 +163,4 @@ main :: proc() { cleanup() } + diff --git a/src/platform.odin b/src/platform.odin index bc0e103..a071468 100644 --- a/src/platform.odin +++ b/src/platform.odin @@ -2,7 +2,6 @@ package demonchime import "draw" import "phys" -import "tiled" Platform :: struct { handle: Entity_Handle, @@ -40,20 +39,17 @@ setup_map_collisions :: proc() { make_map_collisions :: proc( x: i32, y: i32, - tile: tiled.Tile, - tile_set: tiled.Tile_Set, + tile_id: u32, ) { - objs, is_object_layer := tile.object_group.layer.(tiled.Object_Layer) - if !is_object_layer { - return - } + tile := tiles[tile_id] - for obj in objs { + for coll in tile.collisions { make_platform({ - Vec2{f32(x), f32(y)} + obj.position, - obj.size, + coll.start + {f32(x), f32(y)}, + coll.size, }) } } - tiled.iterate_map_tiles(tiled.current_room.tmap, make_map_collisions) + + iterate_room_tiles(current_room.id, make_map_collisions) } diff --git a/src/player.odin b/src/player.odin index de5a66b..e7fd214 100644 --- a/src/player.odin +++ b/src/player.odin @@ -5,9 +5,7 @@ import "core:math" import rl "vendor:raylib" -import "draw" import "phys" -import "tiled" PLAYER_SPEED :: 100 PLAYER_ACCEL :: 10 @@ -29,8 +27,7 @@ Player_State :: enum { // there will only ever be one player, so just make it a global :) player: struct { body_handle: phys.Body_Handle, - anim: draw.Animation, - sprite: draw.Sprite, + sprite: Sprite, jump_buffer: f32, coyote_time: f32, @@ -45,13 +42,6 @@ player: struct { } init_player :: proc() { - anim_ok := draw.init_anim_data(&player.anim, "res/player.json") - if !anim_ok { - log.warn("could not load animation") - rl.CloseWindow() - return - } - handle, body := phys.make_body( phys.Rect{{-4, 17}, {8, 16}}, ) @@ -59,7 +49,7 @@ init_player :: proc() { phys.set_body_position(handle, Vec2{50, 100}) - draw.init_sprite(&player.sprite, player.anim.image_path, player.anim) + init_sprite(&player.sprite, .PLAYER) player.sprite.offset = Vec2{ math.floor(f32(player.sprite.width / 2)), @@ -70,8 +60,7 @@ init_player :: proc() { delete_player :: proc() { phys.remove_body(player.body_handle) - draw.destroy_sprite(player.sprite) - draw.delete_anim_data(player.anim) + destroy_sprite(player.sprite) } @(private="file") @@ -93,10 +82,10 @@ default_state :: proc(dt: f32) { input := get_input_dir() if input != 0 { - draw.set_sprite_active_tag(&player.sprite, "run") + set_sprite_active_tag(&player.sprite, "run") player.sprite.scale.x = math.sign(input) } else { - draw.set_sprite_active_tag(&player.sprite, "idle") + set_sprite_active_tag(&player.sprite, "idle") } if is_keybind_just_down(actions.jump) { @@ -116,11 +105,11 @@ default_state :: proc(dt: f32) { } else { switch body.vel.y { case -math.INF_F32..<-50: - draw.set_sprite_active_tag(&player.sprite, "jump_up") + set_sprite_active_tag(&player.sprite, "jump_up") case 50..<math.INF_F32: - draw.set_sprite_active_tag(&player.sprite, "jump_down") + set_sprite_active_tag(&player.sprite, "jump_down") case: - draw.set_sprite_active_tag(&player.sprite, "jump_trans") + set_sprite_active_tag(&player.sprite, "jump_trans") } } @@ -176,6 +165,7 @@ dash_state :: proc(dt: f32) { } } +@(private="file") exit_dash :: proc() { player.state = .DEFAULT @@ -189,21 +179,21 @@ exit_dash :: proc() { change_rooms :: proc() { body := phys.get_body(player.body_handle) - width := f32(tiled.current_room.room.width) - height := f32(tiled.current_room.room.height) + width := f32(current_room.width) + height := f32(current_room.height) if body.pos.x < 0 || body.pos.x > width \ || body.pos.y < 0 || body.pos.y > height { - prev_room_pos := [2]f32{ - f32(tiled.current_room.room.x), - f32(tiled.current_room.room.y), + prev_room_pos := Vec2{ + f32(current_room.x), + f32(current_room.y), } - changed := tiled.open_new_room_at({i32(body.pos.x), i32(body.pos.y)}) + changed := open_room_at({i32(body.pos.x), i32(body.pos.y)}) if changed { - new_room_pos := [2]f32{ - f32(tiled.current_room.room.x), - f32(tiled.current_room.room.y), + new_room_pos := Vec2{ + f32(current_room.x), + f32(current_room.y), } diff := prev_room_pos - new_room_pos @@ -226,7 +216,7 @@ update_player :: proc(dt: f32) { body := phys.get_body(player.body_handle) player.sprite.pos = body.pos - draw.update_sprite(&player.sprite, dt) + update_sprite(&player.sprite, dt) player.dash_cooldown -= dt player.jump_buffer -= dt @@ -236,5 +226,5 @@ update_player :: proc(dt: f32) { } draw_player :: proc() { - draw.sprite(player.sprite) + draw_sprite(player.sprite) } diff --git a/src/resources.odin b/src/resources.odin index 6120812..799ba75 100644 --- a/src/resources.odin +++ b/src/resources.odin @@ -19,9 +19,68 @@ Animation_Resource :: struct { tags: map[string]Tag_Resource, } -Map_Resource :: struct { +Object_Resource :: struct { + pos: Vec2, + parallax: Vec2, + properties: map[string]any, +} + +Room_Resource :: struct { + width: i32, + height: i32, + + tile_width: i32, + tile_height: i32, + + layers: [][]u32, + + objects: []Object_Resource, + + background_image: Maybe(Image_Id), +} + +Tile_Resource :: struct { + tileset: Tileset_Id, + rect: Rect, + + id: u32, + + collisions: []Rect, } Tileset_Resource :: struct { + tiles: []u32, + image: Image_Id, +} + +Room_Position_Resource :: struct { + id: Room_Id, + x: i32, + y: i32, + width: i32, + height: i32, } +get_image :: proc(id: Image_Id) -> rl.Texture2D { + img_res := &images[id] + + if !rl.IsTextureValid(img_res.texture) { + rl_img := rl.LoadImageFromMemory( + ".qoi", + raw_data(img_res.data), + i32(len(img_res.data)), + ) + if !rl.IsImageValid(rl_img) { + die("Could not load asset %v", id) + } + + img_res.texture = rl.LoadTextureFromImage(rl_img); + rl.UnloadImage(rl_img) + } + + return img_res.texture +} + +get_room :: proc(id: Room_Id) -> Room_Resource { + return rooms[id] +} diff --git a/src/sprite.odin b/src/sprite.odin new file mode 100644 index 0000000..af2fdf9 --- /dev/null +++ b/src/sprite.odin @@ -0,0 +1,106 @@ +package demonchime + +import "core:log" + +import rl "vendor:raylib" + +import "draw" + +Sprite :: struct { + image: rl.Texture2D, + anim_id: Animation_Id, + current_tag: Tag_Resource, + frame_time: f32, + current_frame: i32, + + width: i32, + height: i32, + + pos: Vec2, + offset: Vec2, + rotation: f32, + scale: Vec2, + + just_finished_loop: bool, +} + +init_sprite :: proc( + sprite: ^Sprite, + image_id: Image_Id, + anim_id: Maybe(Animation_Id) = nil, +) -> bool { + sprite.image = get_image(image_id) + + switch id in anim_id { + case Animation_Id: + sprite.anim_id = id + case nil: + sprite.anim_id = images[image_id].anim + } + + anim := animations[sprite.anim_id] + + sprite.width = i32(f32(sprite.image.width) / f32(anim.frame_count)) + sprite.height = i32(sprite.image.height) + + log.debug(sprite.width, anim.frame_count, sprite.anim_id) + + sprite.scale = Vec2{1, 1} + + return true +} + +destroy_sprite :: proc(sprite: Sprite) { + rl.UnloadTexture(sprite.image) +} + +set_sprite_active_tag :: proc(sprite: ^Sprite, tag_name: string) { + anim := animations[sprite.anim_id] + sprite.current_tag = anim.tags[tag_name] +} + +update_sprite :: proc(sprite: ^Sprite, dt: f32) { + sprite.just_finished_loop = false + + sprite.frame_time += dt + + anim := animations[sprite.anim_id] + + duration := f32(anim.frame_durations[sprite.current_frame]) / 1000 + + if sprite.frame_time > duration { + sprite.frame_time -= duration + sprite.current_frame += 1 + } + + tag := &sprite.current_tag + + if sprite.current_frame < tag.from { + sprite.current_frame = tag.to + sprite.just_finished_loop = true + } + if sprite.current_frame > tag.to { + sprite.current_frame = tag.from + sprite.just_finished_loop = true + } +} + +draw_sprite :: proc( + sprite: Sprite, +) { + rect := draw.Rect{ + {f32(sprite.width * sprite.current_frame), 0}, + {f32(sprite.width), f32(sprite.height)}, + } + + draw.texture_quad( + sprite.image, + rect, + sprite.pos, + sprite.offset, + sprite.rotation, + sprite.scale, + ) + + // log.debug(rect) +} diff --git a/src/tiled/json.odin b/src/tiled/json.odin deleted file mode 100644 index 874430e..0000000 --- a/src/tiled/json.odin +++ /dev/null @@ -1,208 +0,0 @@ -package tiled - -Json_Map :: struct { - backgroundcolor: string, - class: string, - compressionlevel: i32, - width: i32, - height: i32, - infinite: bool, - layers: []Json_Layer, - nextlayerid: i32, - nextobjectid: i32, - orientation: string, - parallaxoriginx: f64, - parallaxoriginy: f64, - properties: []Json_Property, - renderorder: string, - staggeraxis: string, - staggerindex: string, - tilewidth: i32, - tileheight: i32, - tilesets: []Json_Tile_Set, -} - -Json_Layer :: struct { - class: string, - compression: string, - data: union { - []i32, - string, - }, - draworder: string, - encoding: string, - id: i32, - image: string, - image_width: i32, - image_height: i32, - layers: []Json_Layer, - // locked: bool, - name: string, - objects: []Json_Object, - offsetx: f64, - offsety: f64, - opacity: f32, - parallaxx: f64, - parallaxy: f64, - properties: []Json_Property, - repeatx: bool, - repeaty: bool, - tintcolor: string, - transparentcolor: string, - type: string, - visible: bool, - x: i32, - y: i32, - width: i32, - height: i32, -} - -Json_Object :: struct { - ellipse: bool, - gid: i32, - width: f64, - height: f64, - id: i32, - name: string, - point: bool, - polygon: []Json_Point, - polyline: []Json_Point, - properties: []Json_Property, - rotation: f64, - template: string, - text: Maybe(struct { - fontfamily: string, - color: string, - text: string, - halign: string, - valign: string, - pixelsize: i32, - wrap: bool, - underline: bool, - bold: bool, - italic: bool, - kerning: bool, - strikeout: bool, - }), - type: string, - visible: bool, - x: f64, - y: f64, -} - -Json_Tile_Set :: struct { - background_color: string, - class: string, - rows: i32, - columns: i32, - fillmode: string, - firstgid: i32, - grid: Maybe(Json_Grid), - image: string, - imagewidth: i32, - imageheight: i32, - margin: i32, - name: string, - objectalignment: string, - properties: []Json_Property, - source: string, - spacing: i32, - terrains: []Json_Terrain, - tilecount: i32, - tilewidth: i32, - tileheight: i32, - tileoffset: Json_Tile_Offset, - tilerendersize: string, - tiles: []Json_Tile, - transformations: Json_Transformations, - transparentcolor: string, - type: string, - wangsets: []Json_Wang_Set, -} - -Json_Grid :: struct { - width: i32, - height: i32, - orientation: string, -} - -Json_Tile_Offset :: struct { - x: i32, - y: i32, -} - -Json_Transformations :: struct { - hflip: bool, - vflip: bool, - rotate: bool, - preferuntransformed: bool, -} - -Json_Tile :: struct { - animation: []Json_Frame, - id: i32, - image: string, - imagewidth: i32, - imageheight: i32, - x: i32, - y: i32, - width: i32, - height: i32, - objectgroup: Json_Layer, - probability: f64, - properties: []Json_Property, - terrain: []i32, - type: string, -} - -Json_Frame :: struct { - duration: i32, - tileid: i32, -} - -Json_Terrain :: struct { - name: string, - properties: []Json_Property, - tile: i32, -} - -Json_Wang_Set :: struct { - class: string, - colors: []Json_Wang_Color, - name: string, - properties: []Json_Property, - tile: i32, - type: string, - wangtiles: []Json_Wang_Tile, -} - -Json_Wang_Color :: struct { - class: string, - color: string, - name: string, - probability: f64, - properties: []Json_Property, - tile: i32, -} - -Json_Wang_Tile :: struct { - tileid: i32, - wangid: []u8, -} - -Json_Object_Template :: struct { - tileset: Maybe(Json_Tile_Set), - object: Json_Object, -} - -Json_Property :: struct { - name: string, - type: string, - propertytype: string, - value: any, -} - -Json_Point :: struct { - x: f64, - y: f64, -} diff --git a/src/tiled/tiled.odin b/src/tiled/tiled.odin deleted file mode 100644 index d84c296..0000000 --- a/src/tiled/tiled.odin +++ /dev/null @@ -1,628 +0,0 @@ -package tiled - -import os "core:os/os2" -import mem "core:mem" -import strings "core:strings" -import "core:path/filepath" -import "core:log" -import "core:encoding/json" - -import rl "vendor:raylib" - -Color :: [4]f32 - -Error :: enum { - NONE = 0, - COULD_NOT_LOAD, - NON_ORTHOGONAL_NOT_SUPPORTED, - INFINITE_NOT_SUPPORTED, - ELLIPSE_OBJ_NOT_SUPPORTED, - POLYGON_OBJ_NOT_SUPPORTED, - POLYLINE_OBJ_NOT_SUPPORTED, - TEXT_OBJ_NOT_SUPPORTED, -} - -Axis :: enum { - X, - Y, -} - -Properties :: map[string]any - -Map :: struct { - // Currently, only orthogonal maps are allowed. Any non-orthogonal maps - // throw an error. - // Infinite maps will also throw an error for now. - - background_color: Color, - class: string, - - width: i32, - height: i32, - - layers: []Layer, - - next_layer_id: i32, - next_object_id: i32, - - parallax_origin_x: f64, - parallax_origin_y: f64, - - properties: Properties, - - // stagger_axis: Axis, - // stagger_offset: i32, // To replace stagger index. - - tile_width: i32, - tile_height: i32, - - tile_sets: []Tile_Set, - - tiles: [dynamic]Tile, -} - -Layer :: struct { - // Layers that aren't visible are entirely ignored. - name: string, - properties: Properties, - - parallax_x: f64, - parallax_y: f64, - - tint: Color, - id: i32, - - layer: union #no_nil { - Tile_Layer, - Image_Layer, - Object_Layer, - } -} - -Tile_Layer :: struct { - // Data will automatically become uncompressed. - width: i32, - height: i32, - data: []i32, -} - -Image_Layer :: struct { - texture: rl.Texture2D, - transparent_color: Color, - repeat_x: bool, - repeat_y: bool, -} - -Object_Layer :: []Object - -Object_Type :: enum { - POINT, - TILE, - RECT, -} - -Object :: struct { - // For now, anything that *isn't* one of these is ignored and - // a warning is thrown: - // - Point - // - Tile - // - Rectangle - // - // Objects that aren't visible will be ignored entirely. - - type: Object_Type, - name: string, - class: string, - properties: Properties, - position: [2]f32, - size: [2]f32, - tile_id: i32, -} - -Tile_Set :: struct { - // For now, any autotiling information is ignored. - - properties: Properties, - - rows: i32, - columns: i32, - - first_gid: i32, - - texture: rl.Texture2D, - margin: i32, - spacing: i32, - - tile_count: i32, - tile_width: i32, - tile_height: i32, - tile_offset: [2]i32, // in pixels - - tiles: []i32, // array of GIDs -} - -Tile :: struct { - // For now, animations are ignored. Support in the future is somewhat likely. - // And similar to above, autotiling information is ignored. - - is_image_collection: bool, - - tile_set: i32, // index for the tile set in Map - - id: i32, - gid: i32, - - texture: Maybe(rl.Texture2D), // If the tile is part of an image collection. - - // Where on the texture is this tile - src_start: [2]i32, - src_size: [2]i32, - - object_group: Layer, // Object layer for collisions. - - properties: Properties, -} - -load_map :: proc(path: string) -> (Map, Error) { - defer free_all(context.temp_allocator) - - jmap_text, read_err := os.read_entire_file(path, context.temp_allocator) - if read_err != nil { - log.errorf("Failed to read file %v (%v)", path, read_err) - return {}, .COULD_NOT_LOAD - } - - jmap: Json_Map - unmarshal_err := json.unmarshal( - jmap_text, - &jmap, - allocator = context.temp_allocator, - ) - if unmarshal_err != nil { - log.errorf("Failed to unmarshal file %v (%v)", path, unmarshal_err) - return {}, .COULD_NOT_LOAD - } - - // log.debug(jmap) - - tmap: Map - err := convert_json_map(jmap, &tmap, path) - if err != .NONE { - return {}, err - } - return tmap, .NONE -} - -delete_map :: proc(tmap: Map) { - delete(tmap.class) - delete(tmap.properties) - - for layer in tmap.layers { - delete_layer(layer) - } - delete(tmap.layers) - - for tile_set in tmap.tile_sets { - delete(tile_set.properties) - delete(tile_set.tiles) // all tiles are deleted later - rl.UnloadTexture(tile_set.texture) - } - delete(tmap.tile_sets) - - for tile in tmap.tiles { - delete(tile.properties) - - if tile.texture != nil { - rl.UnloadTexture(tile.texture.(rl.Texture2D)) - } - - delete_layer(tile.object_group) - } - delete(tmap.tiles) -} - -@(private) -delete_layer :: proc(layer: Layer) { - delete(layer.name) - delete(layer.properties) - - switch l in layer.layer { - case Tile_Layer: - delete(l.data) - case Image_Layer: - rl.UnloadTexture(l.texture) - case Object_Layer: - for obj in l { - delete(obj.name) - delete(obj.class) - delete(obj.properties) - } - delete(l) - } -} - -@(private) -convert_json_color :: proc(jcolor: string) -> Color { - return Color{1, 1, 1, 1} -} - -@(private) -convert_json_properties :: proc(jprops: []Json_Property) -> Properties { - props := make(Properties) - - for jprop in jprops { - props[jprop.name] = jprop.value - } - - return props -} - -@(private) -convert_json_map :: proc(jmap: Json_Map, tmap: ^Map, path: string) -> Error { - // ensure the map is orthogonal - if strings.compare(jmap.orientation, "orthogonal") != 0 { - return .NON_ORTHOGONAL_NOT_SUPPORTED - } - - // ensure the map is not infinite - if jmap.infinite { - return .INFINITE_NOT_SUPPORTED - } - - tmap.background_color = convert_json_color(jmap.backgroundcolor) - tmap.class = strings.clone(jmap.class) - - tmap.width = jmap.width - tmap.height = jmap.height - - tmap.tile_width = jmap.tilewidth - tmap.tile_height = jmap.tileheight - - tmap.next_layer_id = jmap.nextlayerid - tmap.next_object_id = jmap.nextobjectid - - tmap.parallax_origin_x = jmap.parallaxoriginx - tmap.parallax_origin_y = jmap.parallaxoriginy - - tmap.properties = convert_json_properties(jmap.properties) - - // TODO: flatten groups - layer_count := len(jmap.layers) - for jlayer in jmap.layers { - layer_count += len(jlayer.layers) // take into consideration groups - } - - tmap.layers = make([]Layer, layer_count) - current_index := 0 - - for jlayer in jmap.layers { - if !jlayer.visible { - continue // ignore hidden layers - } - - // FIXME: Some duplicated code down here - if strings.compare(jlayer.type, "group") == 0 { - for jlayer2 in jlayer.layers { - if !jlayer2.visible { - continue // ignore hidden layers - } - - layer, err := convert_json_layer(jlayer2) - if err != .NONE { - return err - } - tmap.layers[current_index] = layer - current_index += 1 - } - continue - } - - layer, err := convert_json_layer(jlayer) - if err != .NONE { - return err - } - tmap.layers[current_index] = layer - current_index += 1 - } - - tmap.tile_sets = make([]Tile_Set, len(jmap.tilesets)) - - res_dir := filepath.dir(path, allocator = context.temp_allocator) - - for jtile_set, i in jmap.tilesets { - tile_set, err := convert_json_tile_set(tmap, res_dir, jtile_set) - if err != .NONE { - return err - } - tmap.tile_sets[i] = tile_set - - for j in 0..<len(tmap.tiles) { - tmap.tiles[int(tile_set.first_gid) + j].tile_set = i32(i) - } - } - - return .NONE -} - -Map_Iterate_Callback :: proc(i32, i32, Tile, Tile_Set) - -iterate_map_tiles :: proc(tmap: Map, callback: Map_Iterate_Callback) { - for layer in tmap.layers { - tile_layer, ok := layer.layer.(Tile_Layer) - if !ok { - continue - } - - x: i32 = 0 - y: i32 = 0 - - for cell, i in tile_layer.data { - if cell > 0 { - tile := tmap.tiles[cell - 1] - tile_set := tmap.tile_sets[tile.tile_set] - callback(x, y, tile, tile_set) - } - - x += tmap.tile_width - if x > (tmap.width - 1) * tmap.tile_width { - x = 0 - y += tmap.tile_height - } - } - } -} - -test_cells :: proc(tmap: Map) { - for layer in tmap.layers { - tile_layer, ok := layer.layer.(Tile_Layer) - if !ok { - continue - } - - x: i32 = 0 - y: i32 = 0 - - for cell, i in tile_layer.data { - if cell > 0 { - log.debug(i, [2]i32{x, y}, cell) - } - - x += tmap.tile_width - if x > (tmap.width - 1) * tmap.tile_width { - x = 0 - y += tmap.tile_height - } - } - } -} - -draw_map :: proc(tmap: Map) { - draw_tile :: proc(x: i32, y: i32, tile: Tile, tile_set: Tile_Set) { - rl.DrawTexturePro( - tile_set.texture, - rl.Rectangle{ - x = f32(tile.src_start.x), - y = f32(tile.src_start.y), - width = f32(tile.src_size.x), - height = f32(tile.src_size.y), - }, - rl.Rectangle{ - x = f32(x), - y = f32(y), - width = f32(tile.src_size.x), - height = f32(tile.src_size.y), - }, - {0, 0}, - 0, - rl.WHITE, - ) - } - - iterate_map_tiles(tmap, draw_tile) -} - -@(private) -load_image :: proc(filename: string, res_dir: string) -> rl.Texture2D { - path := strings.concatenate({res_dir, "/", filename}) - defer delete(path) - - byte_path := make([]u8, len(path) + 1, context.temp_allocator) - copy(byte_path, path) - byte_path[len(path)] = 0 - return rl.LoadTexture(transmute(cstring)&byte_path[0]) -} - -@(private) -convert_json_layer :: proc(jlayer: Json_Layer) -> (Layer, Error) { - // TODO: uncompress tile data - - layer: Layer - - layer.name = strings.clone(jlayer.name) - - layer.parallax_x = jlayer.parallaxx - layer.parallax_y = jlayer.parallaxy - - layer.id = jlayer.id - - layer.tint = convert_json_color(jlayer.tintcolor) - - layer.properties = convert_json_properties(jlayer.properties) - - switch jlayer.type { - case "tilelayer": - tile_layer := Tile_Layer{ - width = jlayer.width, - height = jlayer.height, - } - - data := jlayer.data.([]i32) - tile_layer.data = make([]i32, len(data)) - copy(tile_layer.data, data) - - layer.layer = tile_layer - - case "objectgroup": - obj_layer := make(Object_Layer, len(jlayer.objects)) - - for jobj, i in jlayer.objects { - if !jobj.visible { - continue // ignore hidden objects - } - - obj, err := convert_json_object(jobj) - if err != .NONE { - return {}, err - } - obj_layer[i] = obj - } - - layer.layer = obj_layer - - case "imagelayer": - image_layer := Image_Layer{ - texture = load_image(jlayer.image, "res"), - transparent_color = convert_json_color(jlayer.transparentcolor), - repeat_x = jlayer.repeatx, - repeat_y = jlayer.repeaty, - } - - layer.layer = image_layer - - case "group": - // groups are handled elsewhere - } - - return layer, .NONE -} - -@(private) -convert_json_object :: proc(jobj: Json_Object) -> (Object, Error) { - obj: Object - - if jobj.ellipse { - return {}, .ELLIPSE_OBJ_NOT_SUPPORTED - } - if jobj.polygon != nil { - return {}, .POLYGON_OBJ_NOT_SUPPORTED - } - if jobj.polyline != nil { - return {}, .POLYLINE_OBJ_NOT_SUPPORTED - } - if jobj.text != nil { - return {}, .TEXT_OBJ_NOT_SUPPORTED - } - - obj.position = { - f32(jobj.x), - f32(jobj.y), - } - obj.size = { - f32(jobj.width), - f32(jobj.height), - } - obj.tile_id = jobj.gid - - obj.name = strings.clone(jobj.name) - obj.class = strings.clone(jobj.type) - obj.properties = convert_json_properties(jobj.properties) - - return obj, .NONE -} - -@(private) -convert_json_tile_set :: proc( - tmap: ^Map, - res_dir: string, - jtile_set: Json_Tile_Set, -) -> (Tile_Set, Error) { - if len(jtile_set.source) > 0 { - // Tileset links somewhere else - path := strings.concatenate({res_dir, "/", jtile_set.source}) - defer delete(path) - - data, err := os.read_entire_file(path, allocator = context.temp_allocator) - if err != nil { - log.errorf("Could not load external tile set '%v'", path) - return {}, .COULD_NOT_LOAD - } - - new_jtile_set: Json_Tile_Set - marshal_err := json.unmarshal( - data, - &new_jtile_set, - allocator = context.temp_allocator, - ) - if marshal_err != nil { - log.errorf("Could not unmarshal external tile set '%v'", path) - return {}, .COULD_NOT_LOAD - } - - return convert_json_tile_set(tmap, res_dir, new_jtile_set) - } - - tile_set: Tile_Set - - tile_set.rows = jtile_set.rows - tile_set.columns = jtile_set.columns - - tile_set.first_gid = jtile_set.firstgid - - tile_set.texture = load_image(jtile_set.image, res_dir) - tile_set.margin = jtile_set.margin - tile_set.spacing = jtile_set.spacing - - tile_set.tile_count = jtile_set.tilecount - tile_set.tile_width = jtile_set.tilewidth - tile_set.tile_height = jtile_set.tileheight - tile_set.tile_offset = { - jtile_set.tileoffset.x, - jtile_set.tileoffset.y, - } - - tile_set.properties = convert_json_properties(jtile_set.properties) - - tile_set.tiles = make([]i32, jtile_set.tilecount) - - // Ignore margin and spacing for now - // TODO: account for margin and spacing - tile_x := tile_set.texture.width / tile_set.tile_width - tile_y := tile_set.texture.height / tile_set.tile_height - - current_index := 0 - for y in 0..<tile_y { - for x in 0..<tile_x { - tile: Tile - - tile.id = i32(current_index) - - tile.src_start = { - x * tile_set.tile_width, - y * tile_set.tile_height, - } - tile.src_size = { - tile_set.tile_width, - tile_set.tile_height, - } - - current_index += 1 - - tile.gid = i32(len(tmap.tiles)) - append(&tmap.tiles, tile) - - tile_set.tiles[current_index - 1] = tile.gid - } - } - - for jtile in jtile_set.tiles { - ttile := &tmap.tiles[tile_set.tiles[jtile.id]] - object_group, err := convert_json_layer(jtile.objectgroup) - if err != .NONE { - return {}, err - } - ttile.object_group = object_group - ttile.properties = convert_json_properties(jtile.properties) - } - - return tile_set, .NONE -} diff --git a/src/tiled/world.odin b/src/tiled/world.odin deleted file mode 100644 index 0a13716..0000000 --- a/src/tiled/world.odin +++ /dev/null @@ -1,88 +0,0 @@ -package tiled - -import os "core:os/os2" -import "core:log" -import "core:encoding/json" -import "core:path/filepath" -import "core:strings" - -World_Room :: struct { - file_name: string `json:"fileName"`, - x: i32, - y: i32, - width: i32, - height: i32, -} - -res_dir: string -world: []World_Room -current_room: struct { - tmap: Map, - using room: World_Room, -} - -load_world :: proc(path: string) -> bool { - world_text, read_err := os.read_entire_file(path, context.temp_allocator) - if read_err != nil { - log.errorf("Failed to read file %v (%v)", path, read_err) - return false - } - - jworld: struct { - maps: []World_Room, - } - unmarshal_err := json.unmarshal( - world_text, - &jworld, - ) - if unmarshal_err != nil { - log.errorf("Failed to unmarshal file %v (%v)", path, unmarshal_err) - return false - } - - world = jworld.maps - res_dir = filepath.dir(path) - - return true -} - -delete_world :: proc() { - for room in world { - delete(room.file_name) - } - - delete_map(current_room.tmap) - delete(world) - delete(res_dir) -} - -open_new_room_at :: proc(pos: [2]i32) -> bool { - pos := pos - pos += {current_room.room.x, current_room.room.y} - - log.debug("trying to change room...", pos) - for room in world { - if strings.compare(room.file_name, current_room.room.file_name) == 0 { - continue - } - - if pos.x >= room.x && pos.x <= room.x + room.width \ - && pos.y >= room.y && pos.y <= room.y + room.height { - delete_map(current_room.tmap) - - path := strings.concatenate( - {res_dir, "/", room.file_name}, - allocator = context.temp_allocator, - ) - new_map, err := load_map(path) - if err != .NONE { - log.error("could not load new room") - return false - } - current_room.tmap = new_map - current_room.room = room - return true - } - } - return false -} diff --git a/src/world.odin b/src/world.odin new file mode 100644 index 0000000..d0e6c74 --- /dev/null +++ b/src/world.odin @@ -0,0 +1,87 @@ +package demonchime + +import "core:log" + +import rl "vendor:raylib" + +current_room: Room_Position_Resource + +open_room_at :: proc(pos: [2]i32) -> bool { + pos := pos + pos += {current_room.x, current_room.y} + + log.debug("trying to change room...", pos) + for room_pos in world { + if room_pos.id == current_room.id { + continue + } + + if pos.x >= room_pos.x && pos.x <= room_pos.x + room_pos.width \ + && pos.y >= room_pos.y && pos.y <= room_pos.y + room_pos.height { + current_room = room_pos + return true + } + } + return false +} + +open_room :: proc(id: Room_Id) -> bool { + for room_pos in world { + if room_pos.id == id { + current_room = room_pos + return true + } + } + + return false +} + +draw_room :: proc(id: Room_Id) { + draw_tile :: proc(x: i32, y: i32, tile_id: u32) { + tile := tiles[tile_id] + tileset := tilesets[tile.tileset] + rl.DrawTexturePro( + get_image(tileset.image), + rl.Rectangle{ + x = f32(tile.rect.start.x), + y = f32(tile.rect.start.y), + width = f32(tile.rect.size.x), + height = f32(tile.rect.size.y), + }, + rl.Rectangle{ + x = f32(x), + y = f32(y), + width = f32(tile.rect.size.x), + height = f32(tile.rect.size.y), + }, + {0, 0}, + 0, + rl.WHITE, + ) + } + + iterate_room_tiles(id, draw_tile) +} + +Map_Iterate_Callback :: proc(i32, i32, u32) + +iterate_room_tiles :: proc(id: Room_Id, callback: Map_Iterate_Callback) { + room := get_room(id) + + for layer in room.layers { + x: i32 = 0 + y: i32 = 0 + + for cell, i in layer { + if cell > 0 { + callback(x, y, cell - 1) + } + + x += room.tile_width + if x > (room.width - 1) * room.tile_width { + x = 0 + y += room.tile_height + } + } + } +} |
