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;
}