commit 04e28e9ae00cf5c88989f220e4473eb1c0a1d2ba
parent d992550e2cdc08fe6034d49ac84bbf9c936f3fe0
Author: Amin Mesbah <dev@aminmesbah.com>
Date: Tue, 23 Apr 2019 14:31:54 -0700
Fix tunneling bug
Wow! So satisfying! We were failing to take into account the new player
delta during the consecutive iterations of the collision solver, so
residual velocity was being allowed to push the player through walls.
Diffstat:
M | src/game.c | | | 62 | ++++++++++++++------------------------------------------------ |
1 file changed, 14 insertions(+), 48 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -373,33 +373,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
#define RENDER_COLLISION_DEBUG_QUAD(r, c) render_debug_quad(game_state, (r), (c), &view, &projection);
v2 old_p = player->pos;
v2 new_p = glmth_v2_a(old_p, glmth_v2f_m(player->velocity, dt));
- player->pos = new_p;
- glmth_clamp(&player->pos.x, 0.0f, ROOM_TILE_DIM_X);
- glmth_clamp(&player->pos.y, 0.0f, ROOM_TILE_DIM_Y);
- v2 collision_ghost_origin = {
- 11.0f + (0.5f * player->dimensions.width),
- 4.0f + (0.5f * player->dimensions.height)
- };
- old_p = collision_ghost_origin;
- { // render collision ghost origin
- shader_use(&game_state->player.shader);
- glBindVertexArray(game_state->tiles.vao);
-
- m4 model = glmth_m4_init_id();
- model = glmth_translate(model, (v3) {collision_ghost_origin.x, collision_ghost_origin.y, 0.0f});
- model = glmth_scale(model, (v3) {player->dimensions.x, player->dimensions.y, 1.0f});
-
- v3 color = (v3) { 1.0f, 1.0f, 0.0f };
-
- shader_setv3(&game_state->tiles.shader, "color", &color);
- shader_setm4(&game_state->tiles.shader, "model", &model);
- shader_setm4(&game_state->tiles.shader, "view", &view);
- shader_setm4(&game_state->tiles.shader, "projection", &projection);
-
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
- glBindVertexArray(0);
- }
rect player_traversal_bb = {
.min = {glmth_min(old_p.x, new_p.x), glmth_min(old_p.y, new_p.y)},
.max = {glmth_max(old_p.x, new_p.x), glmth_max(old_p.y, new_p.y)},
@@ -421,11 +395,13 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
};
RENDER_COLLISION_DEBUG_QUAD(tile_search_range, ((v3) {0.8f, 0.8f, 0.8f}));
- struct Entity collision_ghost = {0};
v2 player_delta = glmth_v2_s(new_p, old_p);
f32 remaining_time_factor = 1.0f;
for (u32 i = 0; i < 4 && remaining_time_factor > 0.0f; i++)
{
+ old_p = player->pos;
+ new_p = glmth_v2_a(old_p, glmth_v2f_m(player->velocity, dt));
+ player_delta = glmth_v2_s(new_p, old_p);
v2 wall_normal = {0};
f32 smallest_distance_scale_factor = 1.0f;
for (i32 tile_y = tile_search_range.min.y; tile_y < tile_search_range.max.y; tile_y++)
@@ -522,32 +498,22 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
}
}
v2 nearest_collision_p = glmth_v2_a(old_p, glmth_v2f_m(player_delta, smallest_distance_scale_factor));
- collision_ghost.pos = nearest_collision_p;
+ player->pos = nearest_collision_p;
+ player->velocity = glmth_v2_s(
+ player->velocity,
+ glmth_v2f_m(wall_normal, glmth_v2_dot(player->velocity, wall_normal))
+ );
+ player_delta = glmth_v2_s(
+ player_delta,
+ glmth_v2f_m(player_delta, glmth_v2_dot(player->velocity, wall_normal))
+ );
remaining_time_factor -= smallest_distance_scale_factor * remaining_time_factor;
}
-
- // render collision_ghost
- {
- shader_use(&game_state->player.shader);
- glBindVertexArray(game_state->tiles.vao);
-
- m4 model = glmth_m4_init_id();
- model = glmth_translate(model, (v3) {collision_ghost.pos.x, collision_ghost.pos.y, 0.0f});
- model = glmth_scale(model, (v3) {player->dimensions.x, player->dimensions.y, 1.0f});
-
- v3 color = (v3) { 0.0f, 1.0f, 1.0f };
-
- shader_setv3(&game_state->tiles.shader, "color", &color);
- shader_setm4(&game_state->tiles.shader, "model", &model);
- shader_setm4(&game_state->tiles.shader, "view", &view);
- shader_setm4(&game_state->tiles.shader, "projection", &projection);
-
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
- glBindVertexArray(0);
- }
}
#undef RENDER_COLLISION_DEBUG_QUAD
#endif
+ glmth_clamp(&player->pos.x, 0.0f, ROOM_TILE_DIM_X);
+ glmth_clamp(&player->pos.y, 0.0f, ROOM_TILE_DIM_Y);
}