a-game

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

commit b27f37b973503385c93e0ce37cf021d95dc0d46d
parent 71d684de3b226f7d186ecf86f644e0d4a4e26286
Author: amin <dev@aminmesbah.com>
Date:   Sat, 20 Apr 2019 23:57:33 +0000

Replace previous approach with swept cast

FossilOrigin-Name: 16708e369b6b524371c16724997305a1e14ccf4aa49b6cd14c499263a115707b
Diffstat:
Msrc/game.c | 51++++++++++++++++++++++++++++++++++++---------------
Msrc/glmth.h | 34++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -112,7 +112,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#if 0 + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif m4 view = glmth_m4_init_id(); // World origin is in the lower left @@ -148,7 +152,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: restore friction + //f32 friction = 0.7f; + f32 friction = 1.0f; if (game_input->key_up) { @@ -186,6 +192,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga player->pos = glmth_v2_a(player->pos, glmth_v2f_m(player->velocity, dt)); glmth_clamp(&(player->pos.x), 0, ROOM_TILE_DIM_X); glmth_clamp(&(player->pos.y), 0, ROOM_TILE_DIM_Y); + } // render tiles @@ -233,6 +240,33 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga .min = tile_pos, .max = {tile_pos.x + tile_size, tile_pos.y + tile_size}, }; + + // cast player + if (glmth_v2_is_nonzero(player->velocity)) + { + v2 player_direction = glmth_v2_normalize(player->velocity); + + i32 max_cast = glmth_round(glmth_v2_length((v2) {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y})); + for (i32 i = 0; i < max_cast; i++) + { + v2 cast_pos = glmth_v2_a(player->pos, glmth_v2f_m(player_direction, i)); + rect cast_aabb = { + .min = {cast_pos.x - half_w, cast_pos.y - half_h}, + .max = {cast_pos.x + half_w, cast_pos.y + half_h}, + }; + bool cast_intersects = glmth_aabb_intersect(cast_aabb, tile_aabb); + if(cast_intersects) + { + color = (v3) {0.4f, 0.4f, 0.8f}; + } + if(cast_intersects && tile_id > 0) + { + color = (v3) {0.8f, 0.4f, 0.8f}; + break; + } + } + } + bool player_is_in_tile = glmth_aabb_intersect(player_aabb, tile_aabb); if (player_is_in_tile) { @@ -241,18 +275,6 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga if (player_is_in_tile && tile_id > 0) { color = (v3) {0.8f, 0.4f, 0.4f}; - v2 tile_center = glmth_v2_a(tile_aabb.min, glmth_v2f_m(glmth_v2_s(tile_aabb.max, tile_aabb.min), 0.5f)); - v2 diff = glmth_v2_s(player->pos, tile_center); - if (x == 13 && y == 3) - { - printf("***"); - glmth_v2_print(player->pos); - printf("- "); - glmth_v2_print(tile_center); - printf("= "); - glmth_v2_print(diff); - } - player->pos = glmth_v2_a(player->pos, diff); } } @@ -273,7 +295,6 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga glBindVertexArray(game_state->tiles.vao); struct Entity player = game_state->player; - m4 model = glmth_m4_init_id(); model = glmth_translate(model, (v3) {player.pos.x, player.pos.y, 0.0f}); model = glmth_scale(model, (v3) {player.dimensions.x, player.dimensions.y, 1.0f}); diff --git a/src/glmth.h b/src/glmth.h @@ -5,6 +5,11 @@ // TODO: make sure these functions are inlineable and that the compiler does // indeed inline them. +internal inline i32 glmth_round(f32 n) +{ + return n < 0.0f ? n - 0.5 : n + 0.5; +} + internal inline bool glmth_aabb_intersect(rect r1, rect r2) { f32 total_w = (r1.max.x - r1.min.x) + (r2.max.x - r2.min.x); @@ -125,6 +130,21 @@ internal inline v4 glmth_m4v4_m(m4 m, v4 v) return r; } +internal inline bool glmth_approx(f32 n, f32 compare, f32 epsilon) +{ + return fabsf(n - compare) <= epsilon; +} + +internal inline bool glmth_v2_is_nonzero(v2 v) +{ + // TODO: Figure out whether this epsilon is universally appropriate. + f32 epsilon = 0.000001; + return ( + !glmth_approx(v.x, 0.0f, epsilon) + || !glmth_approx(v.y, 0.0f, epsilon) + ); +} + internal inline v2 glmth_v2_a(v2 vec1, v2 vec2) { v2 r = { @@ -151,6 +171,19 @@ internal inline v2 glmth_v2f_m(v2 v, f32 s) return r; } +internal inline f32 glmth_v2_length(v2 v) +{ + return sqrtf((v.x * v.x) + (v.y * v.y)); +} + +// TODO: handle degenerate case where l is near 0.0f +internal inline v2 glmth_v2_normalize(v2 v) +{ + f32 l = glmth_v2_length(v); + v2 r = {v.x / l, v.y / l}; + return r; +} + internal inline void glmth_v2_print(v2 v) { printf("( %f, %f )\n", v.x, v.y); @@ -183,6 +216,7 @@ internal inline v3 glmth_v3_negate(v3 v) return r; } +// TODO: handle degenerate case where l is near 0.0f internal inline v3 glmth_v3_normalize(v3 v) { f32 l = glmth_v3_length(v);