commit 37f3791a33110ddee4973098008ec3765f9c9389
parent 3a3cd0eae1f1aca6d74ecd94737482d8689a5290
Author: amin <dev@aminmesbah.com>
Date: Tue, 23 Apr 2019 05:10:33 +0000
Compress that mess
FossilOrigin-Name: d1ec9791b868cb79a3ebe060351644b4e4f1655a02f23e1c31891b24fe80b0df
Diffstat:
M | src/game.c | | | 184 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
M | src/types.h | | | 14 | ++++++++++++++ |
2 files changed, 116 insertions(+), 82 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -76,6 +76,57 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
}
}
+struct WallCollision
+{
+ bool collision_occurred;
+ f32 game_time_offset;
+ v2 collision_point;
+};
+
+internal struct WallCollision get_wall_collision(v2 entity_p_initial, v2 entity_p_final, segment wall)
+{
+ struct WallCollision result = {0};
+ result.collision_occurred = false;
+
+ assert(wall.min.x <= wall.max.x);
+ assert(wall.min.y <= wall.max.y);
+
+ bool wall_is_horizontal = wall.min.y == wall.max.y;
+ bool wall_is_vertical = wall.min.x == wall.max.x;
+ assert(wall_is_horizontal || wall_is_vertical);
+
+ enum VectorAxis wall_axis = AXIS_X;
+ enum VectorAxis wall_normal_axis = AXIS_Y;
+ if (wall_is_vertical)
+ {
+ wall_axis = AXIS_Y;
+ wall_normal_axis = AXIS_X;
+ }
+
+ v2 player_delta = glmth_v2_s(entity_p_final, entity_p_initial);
+
+ if (player_delta.E[wall_normal_axis] != 0.0f)
+ {
+ f32 wall_position = wall.min.E[wall_normal_axis];
+ f32 initial_d = wall.min.E[wall_normal_axis] - entity_p_initial.E[wall_normal_axis];
+
+ f32 scale_factor = initial_d / player_delta.E[wall_normal_axis];
+ v2 collision_point = glmth_v2_a(entity_p_initial, glmth_v2f_m(player_delta, scale_factor));
+
+ if (scale_factor > 0.0f && scale_factor < 1.0f)
+ {
+ if (collision_point.E[wall_axis] >= wall.min.E[wall_axis]
+ && collision_point.E[wall_axis] <= wall.max.E[wall_axis])
+ {
+ result.collision_occurred = true;
+ result.collision_point = collision_point;
+ }
+ }
+ }
+
+ return result;
+}
+
// NOTE(amin): For now updating and rendering are interleaved. We simulate the
// world at the same rate we render it. Our timestep is not fixed. We may want
// to change this in the future.
@@ -369,91 +420,60 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
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);
- }
- }
+ 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};
+
+ segment tile_b = {tile_sw, tile_se};
+ segment tile_t = {tile_nw, tile_ne};
+ segment tile_l = {tile_sw, tile_nw};
+ segment tile_r = {tile_se, tile_ne};
+
+ v2 wall_normal = {0};
+
+ struct WallCollision bottom = get_wall_collision(old_p, new_p, tile_b);
+ if (bottom.collision_occurred)
+ {
+ wall_normal = (v2) {0.0f, -1.0f};
+ 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);
- }
- }
+
+ struct WallCollision top = get_wall_collision(old_p, new_p, tile_t);
+ if (top.collision_occurred)
+ {
+ wall_normal = (v2) {0.0f, 1.0f};
+ 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);
- }
- }
+
+ struct WallCollision left = get_wall_collision(old_p, new_p, tile_l);
+ if (left.collision_occurred)
+ {
+ wall_normal = (v2) {-1.0f, 0.0f};
+ 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);
- }
- }
+
+ struct WallCollision right = get_wall_collision(old_p, new_p, tile_r);
+ if (right.collision_occurred)
+ {
+ wall_normal = (v2) {1.0f, 0.0f};
+ 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);
}
}
}
diff --git a/src/types.h b/src/types.h
@@ -115,7 +115,21 @@ typedef struct
typedef struct
{
+ v2 min, max;
+} segment;
+
+typedef struct
+{
// row-major, so you probably want to transpose before passing to opengl,
// which uses column-major matrices
f32 E[4][4]; // E[row][column]
} m4;
+
+enum VectorAxis
+{
+ AXIS_X = 0,
+ AXIS_Y = 1,
+ AXIS_Z = 2,
+ AXIS_W = 3,
+ AXIS_MAX = 4,
+};