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:
| M | src/game.c |  |  | 24 | ++++++++---------------- | 
| M | src/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;
 }