commit 5f3c63a64a837cc1fe154cc9c5d4d4a26f62f8bf
parent fa903d6ce3844311099e9a08ea966ccd55c73969
Author: Amin Mesbah <dev@aminmesbah.com>
Date: Mon, 22 Apr 2019 14:57:28 -0700
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.
Diffstat:
M | src/game.c | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++---- |
M | src/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);