a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit c4891b75f41e2a026a825a72c941e4e9a975b420
parent d4a3bfc002951be50bd276299c12f673e6c4137f
Author: amin <dev@aminmesbah.com>
Date:   Fri, 14 Jun 2019 01:34:25 +0000

Get tile value from any room

This change removes the need for a bunch of nasty state checking we used
to have to do before getting a tile's value. Nice!

As a bonus, this fixed the bug in the previous commit where if you tried
to climb an offscreen wall you would get a failed assert.

While working on this project, I'm trying to improve my habits of
thought when it comes to measurement and reasoning, to recognize when
I'm going down a bad path with no clear justification.

I was resisting this change for so long because of vague ideas of
'performance'. However I have no measurements to back those up, and the
change is justified by the clear benefits to robustness and ease of use.

FossilOrigin-Name: 35cd1b37dfeed2467e70ec6d628de7d218adff499f7c4116446127ce0d194ef6
Diffstat:
Msrc/game.c | 24++++++++----------------
Msrc/world.c | 62+++++++++++++++++++++++++-------------------------------------
2 files changed, 33 insertions(+), 53 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -28,7 +28,7 @@ internal void move_state_print(enum MoveState s) } } -internal bool entity_is_adjacent_to_solid_tiles(rect entity_rect, u32 *tiles, enum Direction dir) +internal bool entity_is_adjacent_to_solid_tiles(struct World *world, struct AbsolutePos entity_p, rect entity_rect, enum Direction dir) { v2 tile_p_to_search_from_min = {0}; v2 tile_p_to_search_from_max = {0}; @@ -56,8 +56,8 @@ internal bool entity_is_adjacent_to_solid_tiles(rect entity_rect, u32 *tiles, en } bool result = false; - if (tile_is_solid(tiles, tile_p_to_search_from_min) - || tile_is_solid(tiles, tile_p_to_search_from_max)) + if (world_tile_is_solid(world, (struct AbsolutePos) {.room = entity_p.room, .local = tile_p_to_search_from_min}) + || world_tile_is_solid(world, (struct AbsolutePos) {.room = entity_p.room, .local = tile_p_to_search_from_max})) { result = true; } @@ -306,7 +306,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga case MOVE_STATE_CLIMBING: if (player_is_strictly_within_room && player->facing == previous_facing_dir - && entity_is_adjacent_to_solid_tiles(player_rect, current_room->tiles, player->facing)) + && entity_is_adjacent_to_solid_tiles(game_state->world, player->pos, player_rect, player->facing)) { if (game_input->key_up) { @@ -355,7 +355,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga // game_detect_collisions { -#if 0 +#if 1 #define RENDER_COLLISION_DEBUG_QUAD(r, c) renderer_debug_quad_draw(&game_state->renderer, (r), (c)); #else #define RENDER_COLLISION_DEBUG_QUAD(r, c) @@ -394,30 +394,22 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga { for (i32 tile_x = tile_search_range.min.x; tile_x < tile_search_range.max.x; tile_x++) { - struct AbsolutePos tile_pos = world_tile_pos_recanonicalize( (struct AbsolutePos) { .room = current_room_i, .local = (v2) {tile_x, tile_y}, }); - // NOTE(amin): pointer alias - u32 *tile_set = current_room->tiles; bool tile_is_past_world_edge = false; if (!math_v2i_eq(tile_pos.room, current_room_i)) { - struct Room *room_containing_tile = world_room_get(game_state->world, tile_pos.room); - if (room_containing_tile) - { - tile_set = room_containing_tile->tiles; - } - else + if (!world_room_get(game_state->world, tile_pos.room)) { tile_is_past_world_edge = true; } } - if ((!tile_is_past_world_edge) && tile_is_solid(tile_set, tile_pos.local)) + if ((!tile_is_past_world_edge) && world_tile_is_solid(game_state->world, tile_pos)) { rect tile_aabb = { .min = {tile_x, tile_y}, @@ -577,7 +569,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga model = math_scale(model, (v3) {TILE_SIZE, TILE_SIZE, 1.0f}); v3 color; - bool solid = tile_is_solid(current_room->tiles, tile_pos); + bool solid = world_tile_in_room_is_solid(current_room->tiles, tile_pos); if (solid) { color = (v3) {0.4f, 0.4f, 0.4f}; diff --git a/src/world.c b/src/world.c @@ -247,16 +247,26 @@ internal u32 get_tile_value(u32 *tiles, v2 tile_pos) return tile_value; } -internal bool tile_is_solid(u32 *tiles, v2 tile_pos) +internal bool world_tile_in_room_is_solid(u32 *tiles, v2 tile_pos) { - assert(tiles); - bool is_solid = false; u32 tile_value = get_tile_value(tiles, tile_pos); is_solid = tile_value > 0; return is_solid; } +internal bool world_tile_is_solid(struct World *world, struct AbsolutePos abs_tile_p) +{ + assert(world); + struct AbsolutePos p = world_tile_pos_recanonicalize(abs_tile_p); + struct Room *r = world_room_get(world, p.room); + // TODO: we have the opportunity here to just make every 'tile' beyond the + // edge of the world solid. + assert(r); + bool is_solid = world_tile_in_room_is_solid(r->tiles, p.local); + return is_solid; +} + internal bool wall_is_screen_edge(segment wall) { bool is_screen_edge = false; @@ -294,48 +304,26 @@ internal bool wall_is_internal(struct World *world, v2i room_i, segment wall) && math_f32_is_i32(wall.max.x) && math_f32_is_i32(wall.max.y)); - v2 lesser_neighbor = {0}; - v2 greater_neighbor = {0}; + struct AbsolutePos lesser_neighbor = { + .room = room_i, + .local = {0}, + }; + struct AbsolutePos greater_neighbor = { + .room = room_i, + .local = {0}, + }; if (wall_is_vertical) { - lesser_neighbor = (v2) {wall.min.x - TILE_SIZE, wall.min.y}; + lesser_neighbor.local = (v2) {wall.min.x - TILE_SIZE, wall.min.y}; } else { - lesser_neighbor = (v2) {wall.min.x, wall.min.y - TILE_SIZE}; - } - greater_neighbor = wall.min; - - struct Room *room = world_room_get(world, room_i); - u32 *lesser_tiles = room->tiles; - u32 *greater_tiles = room->tiles; - { - struct AbsolutePos l = world_tile_pos_recanonicalize( - (struct AbsolutePos) { - .room = room_i, - .local = lesser_neighbor, - }); - struct AbsolutePos g = world_tile_pos_recanonicalize( - (struct AbsolutePos) { - .room = room_i, - .local = greater_neighbor, - }); - if (!math_v2i_eq(l.room, room_i)) - { - lesser_neighbor = l.local; - lesser_tiles = world_room_get(world, l.room)->tiles; - } - if (!math_v2i_eq(g.room, room_i)) - { - greater_neighbor = g.local; - greater_tiles = world_room_get(world, g.room)->tiles; - } + lesser_neighbor.local = (v2) {wall.min.x, wall.min.y - TILE_SIZE}; } + greater_neighbor.local = wall.min; - assert(lesser_tiles); - assert(greater_tiles); - is_internal = tile_is_solid(lesser_tiles, lesser_neighbor) && tile_is_solid(greater_tiles, greater_neighbor); + is_internal = world_tile_is_solid(world, lesser_neighbor) && world_tile_is_solid(world, greater_neighbor); return is_internal; }