a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit 92d80b01e56ff8cdc8855c6ee5267fad815ce626
parent 45154d7306f1a3100061ddbdcf6e5823853d63e6
Author: amin <dev@aminmesbah.com>
Date:   Mon, 22 Apr 2019 21:57:28 +0000

Render BBs for per frame player movement

This is part way through work on the new collision system. I noticed a
big stutter in the distance the player will travel when velocity gets
high. This stutter is due to varying frame dt, which in turn appears to
be caused by some kind of vsync problem when I run this on Linux, where
frame time periodically spikes up to 32ms. I don't see the same problem
on Windows.

FossilOrigin-Name: 175d39b191afce000fdfcf62fe944e8bd0003682355acf1e5eca047a221527b8
Diffstat:
Msrc/game.c | 48++++++++++++++++++++++++++++++++++++++++++++----
Msrc/glmth.h | 27+++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -15,6 +15,8 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) // init player game_state->player.pos = (v2) {12.5f, 5.0f}; + // TODO: remove test velocity + game_state->player.velocity = (v2) {290.0f, 80.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 @@ -236,7 +238,9 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga f32 dt = game_input->dt; f32 max_meters_per_second = 5.0f; f32 acceleration_rate = 50.0f; - f32 friction = 0.7f; + // TODO: refriction + //f32 friction = 0.7f; + f32 friction = 1.0f; if (game_input->key_up) { @@ -268,10 +272,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga // Semi implicit Euler integration: https://gafferongames.com/post/integration_basics/ player->velocity = glmth_v2_a(player->velocity, glmth_v2f_m(player->acceleration, dt)); - glmth_clamp(&player->velocity.x, -max_meters_per_second, max_meters_per_second); - glmth_clamp(&player->velocity.y, -max_meters_per_second, max_meters_per_second); + // TODO: reclamp + //glmth_clamp(&player->velocity.x, -max_meters_per_second, max_meters_per_second); + //glmth_clamp(&player->velocity.y, -max_meters_per_second, max_meters_per_second); - // prevent collision with tiles +#if 0 { f32 half_w = 0.5f * player->dimensions.width; f32 half_h = 0.5f * player->dimensions.height; @@ -318,6 +323,41 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga player->pos = next_player_pos; } } +#else + { + v2 old_p = player->pos; + v2 new_p = glmth_v2_a(old_p, glmth_v2f_m(player->velocity, dt)); + + printf("-------------------\n"); + printf("P OLD: "); + glmth_print(old_p); + printf("V ABS: "); + glmth_print(player->velocity); + printf("DT : %f\n", dt); + printf("V FRM; "); + glmth_print(glmth_v2f_m(player->velocity, dt)); + printf("P NEW: "); + glmth_print(new_p); + + rect player_movement_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)}, + }; + render_debug_quad(game_state, player_movement_bb, (v3) {0.4f, 0.4f, 0.4f}, &view, &projection); + + rect player_occupancy_bb = glmth_minkowski_sum_rect_rect(player_movement_bb, player->dimensions); + render_debug_quad(game_state, player_occupancy_bb, (v3) {0.8f, 0.4f, 0.8f}, &view, &projection); + + rect tile_search_range = { + .min = {(i32)player_occupancy_bb.min.x, (i32)player_occupancy_bb.min.y}, + .max = {(i32)player_occupancy_bb.max.x + 1, (i32)player_occupancy_bb.max.y + 1}, + }; + + render_debug_quad(game_state, tile_search_range, (v3) {0.8f, 0.8f, 0.8f}, &view, &projection); + + //player->pos = new_p; + } +#endif glmth_clamp(&player->pos.x, 0.0f, ROOM_TILE_DIM_X); glmth_clamp(&player->pos.y, 0.0f, ROOM_TILE_DIM_Y); diff --git a/src/glmth.h b/src/glmth.h @@ -5,6 +5,18 @@ // TODO: make sure these functions are inlineable and that the compiler does // indeed inline them. +internal inline f32 glmth_min(f32 a, f32 b) +{ + f32 min = a < b ? a : b; + return min; +} + +internal inline f32 glmth_max(f32 a, f32 b) +{ + f32 max = a > b ? a : b; + return max; +} + internal inline i32 glmth_round(f32 n) { return n < 0.0f ? n - 0.5 : n + 0.5; @@ -23,6 +35,17 @@ internal inline bool glmth_aabb_intersect(rect r1, rect r2) return aabbs_do_indeed_intersect; } +internal inline rect glmth_minkowski_sum_rect_rect(rect r1, v2 r2_dimensions) +{ + f32 r2_half_w = 0.5f * r2_dimensions.width; + f32 r2_half_h = 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}, + }; + return sum; +} + internal inline f32 glmth_wrap(f32 n, f32 min, f32 max) { if (n > max) @@ -163,10 +186,12 @@ internal inline v2 glmth_v2f_m(v2 v, f32 s) internal inline f32 glmth_v2_length(v2 v) { + // TODO: Use inner product of v with itself return sqrtf((v.x * v.x) + (v.y * v.y)); } // TODO: handle degenerate case where l is near 0.0f +// TODO: scale by 1.0f / l internal inline v2 glmth_v2_normalize(v2 v) { f32 l = glmth_v2_length(v); @@ -186,6 +211,7 @@ internal inline v3 glmth_v3_cross(v3 vec1, v3 vec2) internal inline f32 glmth_v3_length(v3 v) { + // TODO: Use inner product of v with itself return sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z)); } @@ -202,6 +228,7 @@ internal inline v3 glmth_v3_negate(v3 v) } // TODO: handle degenerate case where l is near 0.0f +// TODO: scale by 1.0f / l internal inline v3 glmth_v3_normalize(v3 v) { f32 l = glmth_v3_length(v);