commit 80f148c28218a6a83aafe37fbb2e717eb1645b05
parent 736f928759772e12ea59a63b826d60464b39affb
Author: amin <dev@aminmesbah.com>
Date: Wed, 12 Jun 2019 05:31:11 +0000
Fix the air climbing bug
FossilOrigin-Name: 2fe5cbfcc4a4430c0a56375fd4e4cbf05c3cf4de00151c06a5fccb3a66bd88be
Diffstat:
M | src/am_math.h | | | 40 | +++++++++++++++++++++++++++++++--------- |
M | src/game.c | | | 80 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
2 files changed, 101 insertions(+), 19 deletions(-)
diff --git a/src/am_math.h b/src/am_math.h
@@ -44,6 +44,12 @@ internal inline i32 math_floor(f32 x)
return result;
}
+internal inline i32 math_ceil(f32 x)
+{
+ i32 result = ceilf(x);
+ return result;
+}
+
internal inline f32 math_rand(f32 min, f32 max)
{
assert(min < max);
@@ -511,25 +517,43 @@ internal inline bool math_intersect_aabb_aabb(rect r1, rect r2)
return aabbs_do_indeed_intersect;
}
-internal inline rect math_minkowski_sum_rect_rect(rect r1, v2 r2_dimensions)
+internal inline rect math_minkowski_sum_rect(rect r1, v2 r2_dimensions)
{
- f32 r2_half_w = 0.5f * r2_dimensions.width;
- f32 r2_half_h = 0.5f * r2_dimensions.height;
+ v2 r2_half = {
+ .width = 0.5f * r2_dimensions.width,
+ .height = 0.5f * r2_dimensions.height,
+ };
rect sum = {
- .min = {r1.min.x - r2_half_w, r1.min.y - r2_half_h},
- .max = {r1.max.x + r2_half_w, r1.max.y + r2_half_h},
+ .min = {r1.min.x - r2_half.width, r1.min.y - r2_half.height},
+ .max = {r1.max.x + r2_half.width, r1.max.y + r2_half.height},
};
return sum;
}
+internal inline rect math_minkowski_diff_rect(rect r1, v2 r2_dimensions)
+{
+ v2 negated_r2_dim = math_v2_negate(r2_dimensions);
+ rect difference = math_minkowski_sum_rect(r1, negated_r2_dim);
+ return difference;
+}
+
+internal inline rect math_rect_from_center_dim(v2 center, v2 dimensions)
+{
+ v2 half_d = {dimensions.x * 0.5f, dimensions.y * 0.5f};
+ rect result = {
+ .min = {center.x - half_d.x, center.y - half_d.y},
+ .max = {center.x + half_d.x, center.y + half_d.y},
+ };
+ return result;
+}
+
enum MathRectEdge
{
RECT_EDGE_BOTTOM,
RECT_EDGE_TOP,
RECT_EDGE_LEFT,
RECT_EDGE_RIGHT,
-
- NUM_RECT_EDGES,
+ MAX_RECT_EDGE,
};
internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e)
@@ -554,7 +578,6 @@ internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e)
case RECT_EDGE_RIGHT:
edge = (segment) {se, ne};
break;
- case NUM_RECT_EDGES: // fallthrough
default:
assert(false);
break;
@@ -579,7 +602,6 @@ internal v2 math_rect_get_normal(enum MathRectEdge e)
case RECT_EDGE_RIGHT:
normal = (v2) {1.0f, 0.0f};
break;
- case NUM_RECT_EDGES: // fallthrough
default:
assert(false);
break;
diff --git a/src/game.c b/src/game.c
@@ -234,7 +234,53 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
}
else if (player->move_state == MOVE_STATE_CLIMBING)
{
- if (player->facing == previous_facing_dir)
+ bool player_is_still_next_to_wall = true;
+ rect player_rect = math_rect_from_center_dim(player->pos.local, player->dimensions);
+ v2 next_tile_top = {0};
+ v2 next_tile_bottom = {0};
+ if (player->facing == DIR_LEFT)
+ {
+ next_tile_top = (v2) {math_floor(player_rect.min.x - 1.0f), math_floor(player_rect.max.y)};
+ next_tile_bottom = (v2) {math_floor(player_rect.min.x - 1.0f), math_floor(player_rect.min.y)};
+ }
+ else if (player->facing == DIR_RIGHT)
+ {
+ next_tile_top = (v2) {math_ceil(player_rect.max.x), math_floor(player_rect.max.y)};
+ next_tile_bottom = (v2) {math_ceil(player_rect.max.x), math_floor(player_rect.min.y)};
+ }
+ else
+ {
+ assert(false);
+ }
+ renderer_debug_quad_draw(
+ &game_state->renderer,
+ (rect) {
+ .min = next_tile_top,
+ .max = {next_tile_top.x + TILE_SIZE, next_tile_top.y + TILE_SIZE},
+ },
+ (v3) {1.0f, 0.0f, 1.0f});
+ renderer_debug_quad_draw(
+ &game_state->renderer,
+ (rect) {
+ .min = next_tile_bottom,
+ .max = {next_tile_bottom.x + TILE_SIZE, next_tile_bottom.y + TILE_SIZE},
+ },
+ (v3) {1.0f, 0.0f, 1.0f});
+
+ rect player_room_bounds = math_minkowski_diff_rect(
+ (rect) {.min = {0.0f, 0.0f}, .max = {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}},
+ player->dimensions);
+
+ if (math_in_interval_open(player->pos.local.x, player_room_bounds.min.x, player_room_bounds.max.x)
+ && math_in_interval_open(player->pos.local.y, player_room_bounds.min.y, player_room_bounds.max.y))
+ {
+ if (!tile_is_solid(current_room->tiles, next_tile_top) && !tile_is_solid(current_room->tiles, next_tile_bottom))
+ {
+ player_is_still_next_to_wall = false;
+ }
+ }
+
+ if (player_is_still_next_to_wall && player->facing == previous_facing_dir)
{
if (game_input->key_up)
{
@@ -256,8 +302,15 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
}
}
else if (player->move_state == MOVE_STATE_GROUNDED
- || player->move_state == MOVE_STATE_CLIMBING
- || player->move_state == MOVE_STATE_JUMPING)
+ || player->move_state == MOVE_STATE_CLIMBING)
+ {
+ if (game_input->key_jump)
+ {
+ player->acceleration.y = acceleration_rate;
+ player->move_state = MOVE_STATE_JUMPING;
+ }
+ }
+ else if (player->move_state == MOVE_STATE_JUMPING)
{
if (game_input->key_jump)
{
@@ -266,6 +319,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
}
else
{
+ player->acceleration.y = -acceleration_rate;
player->move_state = MOVE_STATE_FALLING;
}
}
@@ -279,7 +333,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
// game_detect_collisions
{
+#if 0
#define RENDER_COLLISION_DEBUG_QUAD(r, c) renderer_debug_quad_draw(&game_state->renderer, (r), (c));
+#else
+#define RENDER_COLLISION_DEBUG_QUAD(r, c)
+#endif
v2 player_delta = math_v2f_m(player->velocity, dt);
v2 new_p = math_v2_a(player->pos.local, player_delta);
@@ -288,7 +346,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
.max = {math_max(player->pos.local.x, new_p.x), math_max(player->pos.local.y, new_p.y)},
};
- rect player_traversal_occupancy_bb = math_minkowski_sum_rect_rect(player_traversal_bb, player->dimensions);
+ rect player_traversal_occupancy_bb = math_minkowski_sum_rect(player_traversal_bb, player->dimensions);
rect tile_search_range = {
.min = {
@@ -309,7 +367,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
v2 wall_normal = {0};
f32 smallest_distance_scale_factor = 1.0f;
bool collision_occurred = false;
- enum MathRectEdge collided_edge = 0;
+ bool edges_collided[MAX_RECT_EDGE] = {0};
for (i32 tile_y = tile_search_range.min.y; tile_y < tile_search_range.max.y; tile_y++)
{
for (i32 tile_x = tile_search_range.min.x; tile_x < tile_search_range.max.x; tile_x++)
@@ -345,9 +403,9 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
};
RENDER_COLLISION_DEBUG_QUAD(tile_aabb, ((v3) {0.8f, 0.4f, 0.4f}));
- rect tile_player_sum = math_minkowski_sum_rect_rect(tile_aabb, player->dimensions);
+ rect tile_player_sum = math_minkowski_sum_rect(tile_aabb, player->dimensions);
- for (enum MathRectEdge edge = 0; edge < NUM_RECT_EDGES; edge++)
+ for (enum MathRectEdge edge = 0; edge < MAX_RECT_EDGE; edge++)
{
segment player_sum_wall = math_rect_get_edge(tile_player_sum, edge);
v2 normal = math_rect_get_normal(edge);
@@ -359,10 +417,10 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
if (c.collision_occurred)
{
collision_occurred = true;
+ edges_collided[edge] = true;
if (smallest_distance_scale_factor > c.distance_scale_factor)
{
smallest_distance_scale_factor = c.distance_scale_factor;
- collided_edge = edge;
}
wall_normal = normal;
RENDER_COLLISION_DEBUG_QUAD(
@@ -380,12 +438,14 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
if (collision_occurred)
{
- if (collided_edge == RECT_EDGE_TOP && player->move_state == MOVE_STATE_FALLING)
+ if (edges_collided[RECT_EDGE_TOP] && player->move_state == MOVE_STATE_FALLING)
{
+ printf("Noo! I am stuck on the ground!");
player->move_state = MOVE_STATE_GROUNDED;
}
- else if (collided_edge == RECT_EDGE_LEFT || collided_edge == RECT_EDGE_RIGHT)
+ else if (edges_collided[RECT_EDGE_LEFT] || edges_collided[RECT_EDGE_RIGHT])
{
+ printf("Yay! I can climb now!");
player->move_state = MOVE_STATE_CLIMBING;
}
}