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:
M | src/game.c | | | 166 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
M | src/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);