a-game

2D platformer written from scratch.
Log | Files | Refs | README | LICENSE

commit f56e967c62f3523639741f2b72214ecff3272914
parent d184dfdfaff147da80faa72cde8b6409a2878a56
Author: Amin Mesbah <dev@aminmesbah.com>
Date:   Wed, 24 Apr 2019 16:17:18 -0700

Apply epsilon in world, and not player delta space

I'm not going to claim yet again that this is fixed. It needs more
testing and investigation  The epsilon I was applying was scaled based
on the size of the player delta. That in turn was scaled based on the
frame DT. So for any epsilon I supplied, there existed an arbitrarily
tiny DT that would scale it down beyond 32-bit representation, turning
it into a 0.0f. This caused the player to end up sharing an edge with
the wall.

On sufficiently fast computers, we were hitting sufficiently small DTs.
Why that happens is a whole other issue: I thought we were letting vsync
govern our frame rate, so why do we occasionally get such fast frames?
But this solution should address at least part of the problem by
defining the epsilon independently of the time step.

Diffstat:
M.gdbinit | 27+++++++++++++++++++++++----
MMakefile | 2+-
Msrc/game.c | 24+++++++++++++++++++-----
3 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/.gdbinit b/.gdbinit @@ -1,9 +1,28 @@ -break game.c:126 if wall.min.y > 7 && entity_p_final.y > wall.min.y && entity_p_final.x < wall.max.x && entity_p_final.x > wall.min.x && !result.collision_occurred +break game.c:458 if tile_b.min.y > 7 && new_p.y > tile_b.min.y && new_p.x < tile_b.max.x && new_p.x > tile_b.min.x +commands +print player->pos +print new_p +print tile_b.min +cont +end + +break game.c:128 if wall.min.y > 7 && entity_p_final.y > wall.min.y && entity_p_final.x < wall.max.x && entity_p_final.x > wall.min.x +commands +print player_delta +cont +end + +break game.c:533 +commands +print player->pos +cont +end -break game.c:550 +break game.c:562 commands -print player_aabb -print tile_aabb +print player_aabb.max +print tile_aabb.min +print dt end r diff --git a/Makefile b/Makefile @@ -20,7 +20,7 @@ RELLIB = $(RELDIR)/$(LIB_NAME) RELLIBTMP = $(RELLIB).tmp RELCFLAGS = -DPLATFORM_HOTLOAD_GAME_CODE -O2 -Os -DEBUGGER = gdb +DEBUGGER = gdb -q .PHONY: default all build_debug build_lib build_release clean debug dir_debug dir_release memcheck run todo diff --git a/src/game.c b/src/game.c @@ -2,6 +2,8 @@ #include "glad.c" #include "shader.c" +#define FIX_TUNNELING_BUG + #ifdef PLATFORM_HOTLOAD_GAME_CODE void game_load_opengl_symbols(void) { @@ -14,7 +16,7 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) struct GameState *game_state = game_memory->game_state; // init player - game_state->player.pos = (v2) {12.5f, 5.0f}; + game_state->player.pos = (v2) {12.5f, 7.70844983f};//game_state->player.pos = (v2) {12.5f, 5.0f}; // In Knytt, the player is 9 by 14 texels and a tile is 24 by 24 texels. // These dimensions are relative to a square 'meter', one tile @@ -116,9 +118,11 @@ internal struct WallCollision get_wall_collision(v2 entity_p_initial, v2 entity_ && collision_point.E[wall_axis] <= wall.max.E[wall_axis]) { result.collision_occurred = true; - result.distance_scale_factor = glmth_max( - 0.0f, - segment_scale_factor - 0.0001f); +#ifdef FIX_TUNNELING_BUG + result.distance_scale_factor = glmth_max(0.0f, segment_scale_factor); +#else + result.distance_scale_factor = glmth_max(0.0f, segment_scale_factor - 0.0001f); +#endif } } } @@ -294,6 +298,10 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga printf("WARNING: Clamping frame dt to 1/60\n"); dt = 1.0f / 60.0f; } + + // TODO: remove this absurdly small test dt + dt = 0.00068f; + f32 max_meters_per_second = 5.0f; f32 acceleration_rate = 50.0f; f32 friction = 0.7f; @@ -326,7 +334,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga player->velocity.x = player->velocity.x * friction; } - // TODO: remove this constant acceleration with is just for debugging + // TODO: remove this constant acceleration which is just for debugging player->acceleration = (v2) {0.0f, 50.0f}; // Semi implicit Euler integration: https://gafferongames.com/post/integration_basics/ @@ -431,6 +439,12 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga }; rect tile_player_sum = glmth_minkowski_sum_rect_rect(tile_aabb, player->dimensions); +#ifdef FIX_TUNNELING_BUG + f32 collision_border_epsilon = 0.0001f; + tile_player_sum = glmth_minkowski_sum_rect_rect( + tile_player_sum, + (v2) {collision_border_epsilon, collision_border_epsilon}); +#endif RENDER_COLLISION_DEBUG_QUAD(tile_player_sum, ((v3) {0.8f, 0.4f, 0.4f})); v2 tile_nw = {tile_player_sum.min.x, tile_player_sum.max.y};