a-game

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

commit 3a3cd0eae1f1aca6d74ecd94737482d8689a5290
parent 92d80b01e56ff8cdc8855c6ee5267fad815ce626
Author: amin <dev@aminmesbah.com>
Date:   Tue, 23 Apr 2019 04:05:52 +0000

Test for wall collisions along player path

FossilOrigin-Name: 27f850f36a2aaa599fa6b6ac4215f8d3d55f298c27b02b04712d2e710ad3542a
Diffstat:
Msrc/game.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/glmth.h | 48++++++++++++++++++++++++------------------------
2 files changed, 169 insertions(+), 45 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -210,7 +210,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga .max = {tile_pos.x + tile_size, tile_pos.y + tile_size}, }; - bool player_is_in_tile = glmth_aabb_intersect(player_aabb, tile_aabb); + bool player_is_in_tile = glmth_intersect_aabb_aabb(player_aabb, tile_aabb); if (player_is_in_tile) { color = (v3) {0.4f, 0.8f, 0.4f}; @@ -236,7 +236,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga { struct Entity *player = &game_state->player; f32 dt = game_input->dt; - f32 max_meters_per_second = 5.0f; + //f32 max_meters_per_second = 5.0f; f32 acceleration_rate = 50.0f; // TODO: refriction //f32 friction = 0.7f; @@ -312,7 +312,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga v2u tile_index = {x, ROOM_TILE_DIM_Y - y - 1}; u32 tile_id = tiles[tile_index.y][tile_index.x]; - if(glmth_aabb_intersect(player_aabb, tile_aabb) && tile_id == 1) + if(glmth_intersect_aabb_aabb(player_aabb, tile_aabb) && tile_id == 1) { next_pos_is_valid = false; } @@ -328,34 +328,158 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga 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 = { + 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)}, }; - render_debug_quad(game_state, player_movement_bb, (v3) {0.4f, 0.4f, 0.4f}, &view, &projection); + //render_debug_quad(game_state, player_traversal_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 player_traversal_occupancy_bb = glmth_minkowski_sum_rect_rect(player_traversal_bb, player->dimensions); + //render_debug_quad(game_state, player_traversal_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}, + .min = { + (i32)glmth_max(0.0f, player_traversal_occupancy_bb.min.x), + (i32)glmth_max(0.0f, player_traversal_occupancy_bb.min.y), + }, + .max = { + (i32)glmth_min(ROOM_TILE_DIM_X, player_traversal_occupancy_bb.max.x + 1), + (i32)glmth_min(ROOM_TILE_DIM_Y, player_traversal_occupancy_bb.max.y + 1), + }, }; - render_debug_quad(game_state, tile_search_range, (v3) {0.8f, 0.8f, 0.8f}, &view, &projection); + for (i32 tile_y = tile_search_range.min.y; tile_y < tile_search_range.max.y; tile_y++) + { + for (i32 tile_x = tile_search_range.min.x; tile_x < tile_search_range.max.x; tile_x++) + { + assert(tile_x < ROOM_TILE_DIM_X); + assert(tile_y < ROOM_TILE_DIM_Y); + + v2u tile_index = {tile_x, ROOM_TILE_DIM_Y - tile_y - 1}; + u32 tile_id = tiles[tile_index.y][tile_index.x]; + + if (tile_id == 1) + { + rect tile_aabb = { + .min = {tile_x, tile_y}, + .max = {tile_x + tile_size, tile_y + tile_size}, + }; + + rect tile_player_sum = glmth_minkowski_sum_rect_rect(tile_aabb, player->dimensions); + render_debug_quad(game_state, tile_player_sum, (v3) {0.8f, 0.4f, 0.4f}, &view, &projection); + + //v2 tile_nw = {tile_player_sum.min.x, tile_player_sum.max.y}; + //v2 tile_ne = tile_player_sum.max; + //v2 tile_sw = tile_player_sum.min; + //v2 tile_se = {tile_player_sum.max.x, tile_player_sum.min.y}; + + //bool hit_bottom = glmth_intersect_segment_segment(old_p, new_p, tile_sw, tile_se); + //bool hit_top = glmth_intersect_segment_segment(old_p, new_p, tile_nw, tile_ne); + //bool hit_left = glmth_intersect_segment_segment(old_p, new_p, tile_sw, tile_nw); + //bool hit_right = glmth_intersect_segment_segment(old_p, new_p, tile_se, tile_ne); + + { // bottom + f32 initial_dist_from_wall = tile_player_sum.min.y - old_p.y; + v2 player_delta = glmth_v2_s(new_p, old_p); + f32 scale_factor = initial_dist_from_wall / player_delta.y; + v2 collision_pos = glmth_v2_a(old_p, glmth_v2f_m(player_delta, scale_factor)); + printf("%f\n", scale_factor); + + if (scale_factor > 0.0f && scale_factor < 1.0f) + { + if (collision_pos.x >= tile_player_sum.min.x && collision_pos.x <= tile_player_sum.max.x) + { + rect collision = { + .min = tile_aabb.min, + .max = {tile_aabb.max.x, tile_aabb.min.y + 0.2f}, + }; + render_debug_quad(game_state, collision, (v3) {1.0f, 0.0f, 0.0f}, &view, &projection); + } + } + } + { // top + f32 initial_dist_from_wall = tile_player_sum.max.y - old_p.y; + v2 player_delta = glmth_v2_s(new_p, old_p); + f32 scale_factor = initial_dist_from_wall / player_delta.y; + v2 collision_pos = glmth_v2_a(old_p, glmth_v2f_m(player_delta, scale_factor)); + printf("%f\n", scale_factor); + + if (scale_factor > 0.0f && scale_factor < 1.0f) + { + if (collision_pos.x >= tile_player_sum.min.x && collision_pos.x <= tile_player_sum.max.x) + { + rect collision = { + .min = {tile_aabb.min.x, tile_aabb.max.y - 0.2f}, + .max = tile_aabb.max, + }; + render_debug_quad(game_state, collision, (v3) {0.0f, 1.0f, 0.0f}, &view, &projection); + } + } + } + { // left + f32 initial_dist_from_wall = tile_player_sum.min.x - old_p.x; + v2 player_delta = glmth_v2_s(new_p, old_p); + f32 scale_factor = initial_dist_from_wall / player_delta.x; + v2 collision_pos = glmth_v2_a(old_p, glmth_v2f_m(player_delta, scale_factor)); + printf("%f\n", scale_factor); + + if (scale_factor > 0.0f && scale_factor < 1.0f) + { + if (collision_pos.y >= tile_player_sum.min.y && collision_pos.y <= tile_player_sum.max.y) + { + rect collision = { + .min = tile_aabb.min, + .max = {tile_aabb.min.x + 0.2f, tile_aabb.max.y}, + }; + render_debug_quad(game_state, collision, (v3) {0.0f, 0.0f, 1.0f}, &view, &projection); + } + } + } + { // right + f32 initial_dist_from_wall = tile_player_sum.max.x - old_p.x; + v2 player_delta = glmth_v2_s(new_p, old_p); + f32 scale_factor = initial_dist_from_wall / player_delta.x; + v2 collision_pos = glmth_v2_a(old_p, glmth_v2f_m(player_delta, scale_factor)); + printf("%f\n", scale_factor); + + if (scale_factor > 0.0f && scale_factor < 1.0f) + { + if (collision_pos.y >= tile_player_sum.min.y && collision_pos.y <= tile_player_sum.max.y) + { + rect collision = { + .min = {tile_aabb.max.x - 0.2f, tile_aabb.min.y}, + .max = tile_aabb.max, + }; + render_debug_quad(game_state, collision, (v3) {1.0f, 0.0f, 1.0f}, &view, &projection); + } + } + } + } + } + } + //player->pos = new_p; + // render new player + { + shader_use(&game_state->player.shader); + glBindVertexArray(game_state->tiles.vao); + struct Entity player = game_state->player; + + m4 model = glmth_m4_init_id(); + model = glmth_translate(model, (v3) {new_p.x, new_p.y, 0.0f}); + model = glmth_scale(model, (v3) {player.dimensions.x, player.dimensions.y, 1.0f}); + + v3 color = (v3) { 1.0f, 0.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); + } } #endif glmth_clamp(&player->pos.x, 0.0f, ROOM_TILE_DIM_X); diff --git a/src/glmth.h b/src/glmth.h @@ -22,30 +22,6 @@ 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); - f32 total_h = (r1.max.y - r1.min.y) + (r2.max.y - r2.min.y); - bool aabbs_do_indeed_intersect = ( - fabsf(r1.max.x - r2.min.x) <= total_w - && fabsf(r1.max.y - r2.min.y) <= total_h - && fabsf(r2.max.x - r1.min.x) <= total_w - && fabsf(r2.max.y - r1.min.y) <= total_h - ); - 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) @@ -478,6 +454,30 @@ internal inline m4 glmth_camera_look_at(v3 camera_pos, v3 camera_target, v3 up) return glmth_m4m4_m(look, glmth_translate(glmth_m4_init_id(), glmth_v3_negate(camera_pos))); } +internal inline bool glmth_intersect_aabb_aabb(rect r1, rect r2) +{ + f32 total_w = (r1.max.x - r1.min.x) + (r2.max.x - r2.min.x); + f32 total_h = (r1.max.y - r1.min.y) + (r2.max.y - r2.min.y); + bool aabbs_do_indeed_intersect = ( + fabsf(r1.max.x - r2.min.x) <= total_w + && fabsf(r1.max.y - r2.min.y) <= total_h + && fabsf(r2.max.x - r1.min.x) <= total_w + && fabsf(r2.max.y - r1.min.y) <= total_h + ); + 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 void glmth_v2_print(v2 v) { printf("( %f, %f )\n", v.x, v.y);