aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriamcheeseman <[hidden email]>2026-01-12 20:51:28 -0500
committeriamcheeseman <[hidden email]>2026-01-12 20:51:28 -0500
commit7fb83578b99aa224f7545f4118a46e84b58a9295 (patch)
tree515e294ac7de167c4501cc0a8d375b13213faf36 /src
parent2b3a3ea9f4bc902b1b357fd149952d4570b25bf3 (diff)
NEW ASSET SYSTEM WOOOOOOOOHOOOOOOOOOOOOOOOOOOOOOOOOO
Diffstat (limited to 'src')
-rw-r--r--[-rwxr-xr-x]src/assets.odin106
-rw-r--r--src/draw/sprite.odin94
-rw-r--r--src/main.odin15
-rw-r--r--src/platform.odin18
-rw-r--r--src/player.odin50
-rw-r--r--src/resources.odin61
-rw-r--r--src/sprite.odin106
-rw-r--r--src/tiled/json.odin208
-rw-r--r--src/tiled/tiled.odin628
-rw-r--r--src/tiled/world.odin88
-rw-r--r--src/world.odin87
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
+ }
+ }
+ }
+}