diff options
| author | iamcheeseman <[hidden email]> | 2026-01-15 12:13:41 -0500 |
|---|---|---|
| committer | iamcheeseman <[hidden email]> | 2026-01-15 12:13:41 -0500 |
| commit | 1ebeadbad7f7ee757096320d9c5daf3b55373f6a (patch) | |
| tree | ffa9ce9d9df6f93970c488441f0a74c8bfcc9022 | |
| parent | d6f276be6bc1214c88cfc5346ceb7a5bea610638 (diff) | |
Bullets! And buncha physics fixes! And more!
| -rwxr-xr-x | src.bin | bin | 5507120 -> 5524024 bytes | |||
| -rw-r--r-- | src/assets.odin | 14 | ||||
| -rw-r--r-- | src/bullet.odin | 47 | ||||
| -rw-r--r-- | src/entity_list.odin | 25 | ||||
| -rw-r--r-- | src/phys/body.odin | 5 | ||||
| -rw-r--r-- | src/phys/world.odin | 110 | ||||
| -rw-r--r-- | src/platform.odin | 8 | ||||
| -rw-r--r-- | src/player.odin | 90 |
8 files changed, 158 insertions, 141 deletions
| Binary files differ diff --git a/src/assets.odin b/src/assets.odin index a9a4d36..fbb3cb8 100644 --- a/src/assets.odin +++ b/src/assets.odin @@ -10,19 +10,19 @@ import rl "vendor:raylib" Image_Id :: enum { BULLET, - PLAYER, TILESETS, PISTOL, + PLAYER, } Animation_Id :: enum { - NONE, PLAYER, + NONE, } Room_Id :: enum { - ROOM_BEGIN, ROOM_BEGIN_1, + ROOM_BEGIN, ROOM_BEGIN_SECRET_1, } @@ -31,8 +31,8 @@ Tileset_Id :: enum { } Object_Type :: enum { - COLLISION, PLAYER_SPAWN, + COLLISION, } Resource_Id :: union { @@ -44,19 +44,19 @@ Resource_Id :: union { images: [Image_Id]Image_Resource = { .BULLET = {data = #load("../res/img/bullet.qoi"), anim = .NONE}, - .PLAYER = {data = #load("../.compiled-res/player-sheet.qoi"), anim = .PLAYER}, .TILESETS = {data = #load("../.compiled-res/tilesets.qoi"), anim = .NONE}, .PISTOL = {data = #load("../res/img/pistol.qoi"), anim = .NONE}, + .PLAYER = {data = #load("../.compiled-res/player-sheet.qoi"), anim = .PLAYER}, } 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 = {"jump_up"={from = 14, to = 15}, "run"={from = 6, to = 13}, "jump_trans"={from = 16, to = 16}, "jump_down"={from = 17, to = 18}, "idle"={from = 0, to = 5}, "sleep"={from = 19, to = 22}}}, .NONE = {frame_count=1, frame_durations={100}, tags={}}, - .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 = {"jump_trans"={from = 16, to = 16}, "sleep"={from = 19, to = 22}, "run"={from = 6, to = 13}, "idle"={from = 0, to = 5}, "jump_up"={from = 14, to = 15}, "jump_down"={from = 17, to = 18}}}, } 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, 7, 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, 16, 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, 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, 41, 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={{type = .PLAYER_SPAWN, pos = {240, 200}, size = {0, 0}, parallax = {0, 0}, properties = {}}, {type = .COLLISION, pos = {0, 0}, size = {48, 48}, parallax = {0, 0}, properties = {}}, }, 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, 27, 19, 31, 31, 19, 19, 31, 19, 19, 19, 19, 28, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 21, 19, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 31, 19, 28, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 27, 19, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 31, 28, 40, 40, 40, 40, 40, 40, 27, 31, 31, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 28, 40, 40, 40, 40, 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, 16, 28, 40, 40, 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, 7, 40, 40, 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, 16, 28, 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, 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, 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, 0, 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, 0, 40, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 18, 20, 20, 20, 20, 18, 9, 18, 9, 40, 38, 9, 18, 42, 0, 0, 0, 0, 0, 0, 0, 41, 9, 18, 18, 9, 18, 18, 20, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 43, 20, 9, 18, 9, 18, 20, 9, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}}, objects={}, background_image=nil}, + .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, 7, 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, 16, 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, 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, 41, 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={{type = .PLAYER_SPAWN, pos = {240, 200}, size = {0, 0}, parallax = {0, 0}, properties = {}}, {type = .COLLISION, pos = {0, 0}, size = {48, 48}, parallax = {0, 0}, properties = {}}, }, background_image=nil}, .ROOM_BEGIN_SECRET_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, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 27, 31, 31, 19, 31, 31, 28, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 21, 17, 0, 0, 0, 0, 0, 10, 19, 19, 31, 19, 31, 19, 28, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 27, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 27, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 9, 18, 9, 18, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 20, 9, 18, 9, 9, 9, 20, 20, 9, 18, 9, 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, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 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}, } diff --git a/src/bullet.odin b/src/bullet.odin index b26cc14..eb8190b 100644 --- a/src/bullet.odin +++ b/src/bullet.odin @@ -7,7 +7,7 @@ import "phys" Bullet :: struct { handle: Entity_Handle, - body_handle: phys.Body_Handle, + body: phys.Body_Handle, sprite: Sprite, lifetime: f32, } @@ -34,58 +34,51 @@ make_bullet :: proc( start = {-3, -3}, size = {6, 6}, } - body_handle, body := phys.make_body(body_rect, layers, mask) + body := phys.make_body(body_rect, layers, mask) - body.vel = vel - - phys.set_body_position(body_handle, pos) + phys.set_velocity(body, vel) + phys.set_position(body, pos) return make_entity(&state.bullet_list, Bullet{ - body_handle = body_handle, + body = body, sprite = sprite, lifetime = lifetime, }) } -delete_bullet :: proc(bullet_handle: Entity_Handle) { - bullet := get_entity(state.bullet_list, bullet_handle) - - phys.remove_body(bullet.body_handle) - delete_entity(&state.platform_list, bullet.handle) +delete_bullet :: proc(h: Entity_Handle) { + b := get_entity(state.bullet_list, h) + phys.remove_body(b.body) + delete_entity(&state.bullet_list, h) } update_bullets :: proc(dt: f32) { iter := iter_entity_list(state.bullet_list) - for bullet in entity_list_iter(&iter) { - bullet.lifetime -= dt + for b in entity_list_iter(&iter) { + b.lifetime -= dt - phys.update_body(bullet.body_handle) - body := phys.get_body(bullet.body_handle) + phys.update_body(b.body) - if body.collisions != {} || bullet.lifetime < 0 { - delete_entity(&state.bullet_list, bullet.handle) + if phys.get_collisions(b.body) != {} || b.lifetime < 0 { + delete_bullet(b.handle) + continue } - bullet.sprite.pos = body.pos + b.sprite.pos = phys.get_position(b.body) } } draw_bullets :: proc() { iter := iter_entity_list(state.bullet_list) - for bullet in entity_list_iter(&iter) { - draw_sprite(bullet.sprite) - - body := phys.get_body(bullet.body_handle) - rect := body.rect - rect.start += body.pos - draw_rect(transmute(Rect)rect) + for b in entity_list_iter(&iter) { + draw_sprite(b.sprite) } } clear_bullets :: proc() { iter := iter_entity_list(state.bullet_list) - for bullet in entity_list_iter(&iter) { - delete_bullet(bullet.handle) + for b in entity_list_iter(&iter) { + delete_bullet(b.handle) } } diff --git a/src/entity_list.odin b/src/entity_list.odin index 3ee553e..d5cdb50 100644 --- a/src/entity_list.odin +++ b/src/entity_list.odin @@ -1,7 +1,5 @@ package demonchime -import "core:math" - Entity_Handle :: struct { idx: u32, uses: u32, @@ -24,8 +22,7 @@ make_entity :: proc(list: ^Entity_List($T), ent: T) -> (Entity_Handle, ^T) { handle = pop(&list.holes) handle.uses += 1 } else { - // because index 0 in a handle is considered a null handle - resize(&list.items, math.max(2, len(list.items) + 1)) + resize(&list.items, len(list.items) + 1) handle.idx = u32(len(list.items) - 1) handle.uses = 1 } @@ -35,21 +32,18 @@ make_entity :: proc(list: ^Entity_List($T), ent: T) -> (Entity_Handle, ^T) { return handle, &list.items[handle.idx] } -delete_entity :: proc(list: ^Entity_List($T), handle: Entity_Handle) { - if handle.idx <= 0 || int(handle.idx) >= len(list.items) { - return - } - if list.items[handle.idx].handle != handle { +delete_entity :: proc(list: ^Entity_List($T), h: Entity_Handle) { + if int(h.idx) >= len(list.items) || + list.items[h.idx].handle != h { return } - append(&list.holes, handle) - list.items[handle.idx] = {} + append(&list.holes, h) + list.items[h.idx] = {} } get_entity :: proc(list: Entity_List($T), h: Entity_Handle) -> ^T { - if h.idx < 1 || - h.idx >= u32(len(list.items)) || + if h.idx >= u32(len(list.items)) || list.items[h.idx].handle != h { return nil } @@ -57,8 +51,7 @@ get_entity :: proc(list: Entity_List($T), h: Entity_Handle) -> ^T { } active_entity_count :: proc(list: Entity_List($T)) -> int { - // - 1 because there's an empty slot at the beginning - return len(list.items) - len(list.holes) - 1 + return len(list.items) - len(list.holes) } Entity_List_Iter :: struct($T: typeid) { @@ -72,7 +65,7 @@ iter_entity_list :: proc(list: Entity_List($T)) -> Entity_List_Iter(T) { entity_list_iter :: proc(it: ^Entity_List_Iter($T)) -> (^T, bool) { for it.idx < len(it.list.items) { - if it.list.items[it.idx].handle.idx > 0 { + if it.list.items[it.idx].handle.uses > 0 { entity := &it.list.items[it.idx] it.idx += 1 return entity, true diff --git a/src/phys/body.odin b/src/phys/body.odin index 93d8623..09dc95a 100644 --- a/src/phys/body.odin +++ b/src/phys/body.odin @@ -42,10 +42,7 @@ make_body :: proc( rect: Rect, layers := bit_set[Layer;u16]{.DEFAULT}, mask := bit_set[Layer;u16]{.DEFAULT}, -) -> ( - Body_Handle, - ^Body, -) { +) -> Body_Handle { b := Body { rect = rect, layers = layers, diff --git a/src/phys/world.odin b/src/phys/world.odin index 7a56990..189f0b0 100644 --- a/src/phys/world.odin +++ b/src/phys/world.odin @@ -8,12 +8,14 @@ import rl "vendor:raylib" BIN_COUNT :: 2056 BIN_SIZE :: 64 -Body_Handle :: u32 +Body_Handle :: struct { + idx: u32, + uses: u32, +} world: struct { - handles: [dynamic]u32, - unused_handles: [dynamic]Body_Handle, bodies: [dynamic]Body, + holes: [dynamic]Body_Handle, bins: [BIN_COUNT][dynamic]Body_Handle, } @@ -21,8 +23,7 @@ destroy_world :: proc() { for bin in world.bins { delete(bin) } - delete(world.handles) - delete(world.unused_handles) + delete(world.holes) delete(world.bodies) } @@ -87,61 +88,74 @@ _remove_from_bins :: proc(b: Body) { // log.debug(last, b.handle) bin[b.bin_idx] = last - last_body := get_body(last) + last_body := _get_body(last) last_body.bin_idx = b.bin_idx } } -get_body :: proc(h: Body_Handle) -> ^Body { - return &world.bodies[world.handles[h]] +@(private = "file") +_get_body :: proc(h: Body_Handle, location := #caller_location) -> ^Body { + if h.idx >= u32(len(world.bodies)) { + log.warn("Handle is out of range", location = location) + return nil + } + if world.bodies[h.idx].handle != h { + log.warnf( + "Handle isn't yours (querying %v, got %v)", + h, + world.bodies[h.idx].handle, + location = location, + ) + } + return &world.bodies[h.idx] } -add_body :: proc(b: Body) -> (Body_Handle, ^Body) { +add_body :: proc(b: Body) -> Body_Handle { handle: Body_Handle if b.rect.size.x > BIN_SIZE || b.rect.size.y > BIN_SIZE { log.warnf("Body size is too big (%vx%v)", b.rect.size.x, b.rect.size.y) } - if len(world.unused_handles) > 0 { - handle = pop(&world.unused_handles) + if len(world.holes) > 0 { + handle = pop(&world.holes) + handle.uses += 1 } else { - handle = cast(Body_Handle)len(world.handles) - append(&world.handles, 0) + resize(&world.bodies, len(world.bodies) + 1) + handle.idx = u32(len(world.bodies) - 1) + handle.uses = 1 } + + world.bodies[handle.idx] = b + world.bodies[handle.idx].handle = handle - world.handles[handle] = u32(len(world.bodies)) - append(&world.bodies, b) - - body := &world.bodies[world.handles[handle]] - body.handle = handle - - _add_to_bins(body) + _add_to_bins(_get_body(handle)) - return handle, body + return handle } remove_body :: proc(h: Body_Handle) { - b := get_body(h) - - _remove_from_bins(b^) - - last := pop(&world.bodies) - if last.handle != h { - world.bodies[world.handles[h]] = last - world.handles[last.handle] = world.handles[h] + if h.idx >= u32(len(world.bodies)) || + world.bodies[h.idx].handle != h { + log.warn("Handle isn't yours, or is out of range") + return } - append(&world.unused_handles, h) + b := _get_body(h) + + _remove_from_bins(b^) + + append(&world.holes, b.handle) + world.bodies[h.idx] = {} } -get_collisions :: proc( +get_colliding_bodies :: proc( h: Body_Handle, allocator := context.allocator ) -> []Body_Handle { bodies := make([dynamic]Body_Handle, allocator) - b := get_body(h) + b := _get_body(h) rect := b.rect rect.start += b.pos @@ -154,7 +168,7 @@ get_collisions :: proc( continue } - c := get_body(c_h) + c := _get_body(c_h) c_rect := c.rect c_rect.start += c.pos @@ -171,7 +185,7 @@ get_collisions :: proc( update_body :: proc(h: Body_Handle) { dt := rl.GetFrameTime() - b := get_body(h) + b := _get_body(h) res_pos := b.pos + b.vel * dt @@ -191,7 +205,7 @@ update_body :: proc(h: Body_Handle) { continue } - c := get_body(c_h) + c := _get_body(c_h) if b.mask & c.layers == {} { continue @@ -231,11 +245,23 @@ update_body :: proc(h: Body_Handle) { b.vel.y = 0 } - set_body_position(h, res_pos) + set_position(h, res_pos) } -set_body_position :: proc(h: Body_Handle, new_pos: Vec2) { - b := get_body(h) +get_velocity :: proc(h: Body_Handle) -> Vec2 { + return _get_body(h).vel +} + +set_velocity :: proc(h: Body_Handle, vel: Vec2) { + _get_body(h).vel = vel +} + +get_position :: proc(h: Body_Handle) -> Vec2 { + return _get_body(h).pos +} + +set_position :: proc(h: Body_Handle, new_pos: Vec2) { + b := _get_body(h) prev_bin := _hash_bin(_world_to_bin(b.pos + b.rect.start)) res_bin := _hash_bin(_world_to_bin(new_pos + b.rect.start)) @@ -248,3 +274,11 @@ set_body_position :: proc(h: Body_Handle, new_pos: Vec2) { b.pos = new_pos } } + +get_collisions :: proc(h: Body_Handle) -> bit_set[Collision_Type;u8] { + return _get_body(h).collisions +} + +get_rect :: proc(h: Body_Handle) -> Rect { + return _get_body(h).rect +} diff --git a/src/platform.odin b/src/platform.odin index b155905..a974811 100644 --- a/src/platform.odin +++ b/src/platform.odin @@ -8,16 +8,16 @@ Platform :: struct { } make_platform :: proc(rect: Rect) -> (Entity_Handle, ^Platform) { - handle, body := phys.make_body(transmute(phys.Rect)rect) - return make_entity(&state.platform_list, Platform{body = handle}) + body := phys.make_body(transmute(phys.Rect)rect) + return make_entity(&state.platform_list, Platform{body = body}) } draw_platforms :: proc() { iter := iter_entity_list(state.platform_list) renderer.tint = {1, 0, 0, 0.25} for p in entity_list_iter(&iter) { - body := phys.get_body(p.body) - draw_rect(cast(Rect)body.rect) + rect := phys.get_rect(p.body) + draw_rect(cast(Rect)rect) } renderer.tint = {1, 1, 1, 1} } diff --git a/src/player.odin b/src/player.odin index c758f31..abed174 100644 --- a/src/player.odin +++ b/src/player.odin @@ -30,7 +30,7 @@ Player_State :: enum { // there will only ever be one player, so just make it a global :) player: struct { - body_handle: phys.Body_Handle, + body: phys.Body_Handle, sprite: Sprite, gun_sprite: Sprite, jump_buffer: f32, @@ -43,14 +43,12 @@ player: struct { } init_player :: proc() { - handle, body := phys.make_body( + body := phys.make_body( phys.Rect{{-4, -16}, {8, 16}}, layers = {.PLAYER}, mask = {.DEFAULT} ) - player.body_handle = handle - - phys.set_body_position(handle, Vec2{50, 100}) + player.body = body init_sprite(&player.sprite, .PLAYER) @@ -68,7 +66,7 @@ init_player :: proc() { } deinit_player :: proc() { - phys.remove_body(player.body_handle) + phys.remove_body(player.body) } @(private = "file") @@ -104,13 +102,16 @@ _default_state :: proc(dt: f32) { return } - body := phys.get_body(player.body_handle) + // body := phys.get_body(player.body_handle) + pos := phys.get_position(player.body) + vel := phys.get_velocity(player.body) + collisions := phys.get_collisions(player.body) - if .DOWN in body.collisions { + if .DOWN in collisions { player.coyote_time = PLAYER_COYOTE_TIME player.has_double_jumped = false } else { - switch body.vel.y { + switch vel.y { case -math.INF_F32..<-50: set_sprite_active_tag(&player.sprite, "jump_up") case 50..<math.INF_F32: @@ -120,12 +121,12 @@ _default_state :: proc(dt: f32) { } } - rel_mouse_pos := get_mouse_pos() - body.pos + rel_mouse_pos := get_mouse_pos() - pos if is_keybind_just_down(actions.shoot) { mouse_dir := linalg.normalize0(rel_mouse_pos) - bullet_pos := body.pos + bullet_pos := pos bullet_pos.y -= PLAYER_GUN_HEIGHT bullet_pos += mouse_dir * PLAYER_GUN_DIST @@ -133,49 +134,49 @@ _default_state :: proc(dt: f32) { bullet_pos, mouse_dir * 200, ) - - // `make_bullet()` adds a new physics body, which could invalidate the - // pointer to our body when the body array reallocs - body = phys.get_body(player.body_handle) } player.sprite.scale.x = math.sign(rel_mouse_pos.x) if player.jump_buffer > 0 { if player.coyote_time > 0 { - body.vel.y = -PLAYER_JUMP_FORCE + vel.y = -PLAYER_JUMP_FORCE player.jump_buffer = 0 player.coyote_time = 0 } else if !player.has_double_jumped { - body.vel.y = -PLAYER_DOUBLE_JUMP_FORCE + vel.y = -PLAYER_DOUBLE_JUMP_FORCE player.has_double_jumped = true player.jump_buffer = 0 } } - if .DOWN not_in body.collisions && + if .DOWN not_in collisions && !is_keybind_down(actions.jump) && - body.vel.y < PLAYER_JUMP_RELEASE_CUT { - body.vel.y = PLAYER_JUMP_RELEASE_CUT + vel.y < PLAYER_JUMP_RELEASE_CUT { + vel.y = PLAYER_JUMP_RELEASE_CUT } - body.vel.x = math.lerp( - body.vel.x, + vel.x = math.lerp( + vel.x, input * PLAYER_SPEED, math.pow(0.5, dt * PLAYER_ACCEL), ) - body.vel.y = math.min(body.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) + vel.y = math.min(vel.y + GRAVITY * dt, TERMINAL_VELOCITY) + + phys.set_velocity(player.body, vel) - phys.update_body(player.body_handle) + phys.update_body(player.body) } @(private = "file") _enter_dash :: proc() { - body := phys.get_body(player.body_handle) // the sprite x scale is the direction the player is facing :) - body.vel = {math.sign(player.sprite.scale.x) * PLAYER_DASH_SPEED, 0} + phys.set_velocity( + player.body, + {math.sign(player.sprite.scale.x) * PLAYER_DASH_SPEED, 0}, + ) player.dash_timer = PLAYER_DASH_TIME player.state = .DASH @@ -183,12 +184,12 @@ _enter_dash :: proc() { @(private = "file") _dash_state :: proc(dt: f32) { - phys.update_body(player.body_handle) + phys.update_body(player.body) player.dash_timer -= dt - body := phys.get_body(player.body_handle) + // body := phys.get_body(player.body_handle) - if player.dash_timer <= 0 || body.collisions != {} { + if player.dash_timer <= 0 || phys.get_collisions(player.body) != {} { _exit_dash() } } @@ -199,31 +200,30 @@ _exit_dash :: proc() { player.dash_cooldown = PLAYER_DASH_COOLDOWN - body := phys.get_body(player.body_handle) - body.vel /= 2 + vel := phys.get_velocity(player.body) + phys.set_velocity(player.body, vel / 2) } @(private = "file") _change_rooms :: proc() { - body := phys.get_body(player.body_handle) - 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 { + pos := phys.get_position(player.body) + + if pos.x < 0 || + pos.x > width || + pos.y < 0 || + pos.y > height { prev_room_pos := Vec2{f32(current_room.x), f32(current_room.y)} - changed := open_room_at({i32(body.pos.x), i32(body.pos.y)}) + changed := open_room_at({i32(pos.x), i32(pos.y)}) if changed { new_room_pos := Vec2{f32(current_room.x), f32(current_room.y)} diff := prev_room_pos - new_room_pos - body = phys.get_body(player.body_handle) - new_pos := body.pos + diff - {0, 0} - phys.set_body_position(player.body_handle, new_pos) + new_pos := pos + diff - {0, 0} + phys.set_position(player.body, new_pos) } } } @@ -234,12 +234,12 @@ update_player :: proc(dt: f32) { case .DASH: _dash_state(dt) } - body := phys.get_body(player.body_handle) + pos := phys.get_position(player.body) - player.sprite.pos = body.pos + player.sprite.pos = pos update_sprite(&player.sprite, dt) - player.gun_sprite.pos = body.pos - Vec2{0, PLAYER_GUN_HEIGHT} + player.gun_sprite.pos = pos - Vec2{0, PLAYER_GUN_HEIGHT} mouse_dir := get_mouse_pos() - player.gun_sprite.pos player.gun_sprite.rotation = math.atan2( @@ -270,5 +270,5 @@ object_spawner_player_spawn :: proc(obj: Object_Resource) { } already_spawned_player = true - phys.set_body_position(player.body_handle, obj.pos) + phys.set_position(player.body, obj.pos) } |
