]> git.lizzy.rs Git - nothing.git/commitdiff
Better platform collision detection (#21)
authorrexim <reximkut@gmail.com>
Sat, 9 Dec 2017 17:46:00 +0000 (00:46 +0700)
committerrexim <reximkut@gmail.com>
Sat, 9 Dec 2017 17:46:00 +0000 (00:46 +0700)
src/platforms.c
src/platforms.h
src/player.c
src/player.h
src/point.c
src/point.h
src/rect.c

index f457502d1bacda0e571b14e2ec4fd11e23bccb79..05361ad84a93d8879622dcf5d26f8bee87ef7693 100644 (file)
@@ -12,6 +12,13 @@ struct platforms_t {
     size_t rects_size;
 };
 
+static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
+    { .x = 1.0f,  .y =  0.0f  },  /* RECT_SIDE_LEFT = 0, */
+    { .x = -1.0f, .y =  0.0f  },  /* RECT_SIDE_RIGHT, */
+    { .x = 0.0f,  .y =  1.0f, },  /* RECT_SIDE_TOP, */
+    { .x = 0.0f,  .y = -1.0f,  }    /* RECT_SIDE_BOTTOM, */
+};
+
 platforms_t *create_platforms(const rect_t *rects, size_t rects_size)
 {
     assert(rects);
@@ -64,14 +71,30 @@ int render_platforms(const platforms_t *platforms,
     return 0;
 }
 
-void platforms_rect_object_collide(const platforms_t *platforms,
-                                   const rect_t *object,
-                                   int *sides)
+vec_t platforms_rect_object_collide(const platforms_t *platforms,
+                                    rect_t object)
 {
     assert(platforms);
-    assert(object);
+
+    int sides[4];
+    memset(sides, 0, sizeof(sides));
 
     for (size_t i = 0; i < platforms->rects_size; ++i) {
-        rect_object_impact(object, &platforms->rects[i], sides);
+        rect_object_impact(&object, &platforms->rects[i], sides);
+    }
+
+    vec_t opposing_force = {
+        .x = 0.0f,
+        .y = 0.0f
+    };
+
+    for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
+        if (sides[side]) {
+            vec_add(
+                &opposing_force,
+                opposing_rect_side_forces[side]);
+        }
     }
+
+    return opposing_force;
 }
index 94f92203161aae0a09855c44d02c25ae62c1bf56..24a4e7220eaaf63b1d20b03f3d30f52985b80240 100644 (file)
@@ -14,8 +14,7 @@ int render_platforms(const platforms_t *platforms,
                      SDL_Renderer *renderer,
                      const camera_t *camera);
 
-void platforms_rect_object_collide(const platforms_t *platforms,
-                                   const rect_t *object,
-                                   int *sides);
+vec_t platforms_rect_object_collide(const platforms_t *platforms,
+                                    rect_t object);
 
 #endif  // PLATFORMS_H_
index 1eaee269da61088952f9dab852eebdc513c6ef50..c65edc5900cfe2ebf5b40cced0d3ff4db518d786 100644 (file)
@@ -41,6 +41,18 @@ void destroy_player(player_t * player)
     free(player);
 }
 
+rect_t player_hitbox(const player_t *player)
+{
+    rect_t hitbox = {
+        .x = player->position.x,
+        .y = player->position.y,
+        .w = PLAYER_WIDTH,
+        .h = PLAYER_HEIGHT
+    };
+
+    return hitbox;
+}
+
 int render_player(const player_t * player,
                   SDL_Renderer *renderer,
                   const camera_t *camera)
@@ -72,41 +84,41 @@ void update_player(player_t *player,
 
     float d = (float) delta_time / 1000.0f;
 
-    rect_t player_object = rect_from_point(
-        vec_sum(
-            player->position,
-            vec_scala_mult(
-                vec_sum(
-                    player->velocity,
-                    player->movement),
-                d)),
-        PLAYER_WIDTH,
-        PLAYER_HEIGHT);
-
-    int sides[4] = {0, 0, 0, 0};
-
-    platforms_rect_object_collide(platforms, &player_object, sides);
-
-    if (sides[RECT_SIDE_LEFT] || sides[RECT_SIDE_RIGHT]) {
-        player->velocity.x = 0.0f;
-        player->movement.x = 0.0f;
-    }
-
-    if (sides[RECT_SIDE_TOP] || sides[RECT_SIDE_BOTTOM]) {
-        player->velocity.y = 0.0f;
-        player->movement.y = 0.0f;
-    }
-
-
-    vec_add(
-        &player->position,
+    player->velocity.y += PLAYER_GRAVITY * d;
+    player->position = vec_sum(
+        player->position,
         vec_scala_mult(
             vec_sum(
                 player->velocity,
                 player->movement),
             d));
+    player->position.y = fmodf(player->position.y, 800.0f);
 
-    player->velocity.y += PLAYER_GRAVITY * d;
+    vec_t opposing_force = platforms_rect_object_collide(
+        platforms,
+        player_hitbox(player));
+
+    while (vec_length(opposing_force) > 1e-6) {
+        player->position = vec_sum(
+            player->position,
+            vec_scala_mult(
+                opposing_force,
+                1e-2f));
+
+        if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((player->velocity.x + player->movement.x) < 0.0f)) {
+            player->velocity.x = 0.0f;
+            player->movement.x = 0.0f;
+        }
+
+        if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((player->velocity.y + player->movement.y) < 0.0f)) {
+            player->velocity.y = 0.0f;
+            player->movement.y = 0.0f;
+        }
+
+        opposing_force = platforms_rect_object_collide(
+            platforms,
+            player_hitbox(player));
+    }
 }
 
 void player_move_left(player_t *player)
@@ -137,7 +149,7 @@ void player_jump(player_t *player)
 {
     assert(player);
 
-    player->velocity.y = -1000.0f;
+    player->velocity.y = -500.0f;
 }
 
 void player_focus_camera(player_t *player,
index 19263b727df3d5cab2d5c5e5a96896b881d22695..27dd78b679eec31704609e31cfb3caadc5bc8afa 100644 (file)
@@ -17,6 +17,8 @@ void update_player(player_t * player,
                    const platforms_t *platforms,
                    Uint32 delta_time);
 
+rect_t player_hitbox(const player_t *player);
+
 void player_move_left(player_t *player);
 void player_move_right(player_t *player);
 void player_stop(player_t *player);
index 6d1b588d81fd229e8d1c8424c28ddb2d0c41bcb7..58c02a0adb498d6ecb855860f1466fe9d8e76a8a 100644 (file)
@@ -1,3 +1,4 @@
+#include <math.h>
 #include "./point.h"
 
 vec_t vec(float x, float y)
@@ -18,6 +19,21 @@ vec_t vec_sum(vec_t v1, vec_t v2)
     return result;
 }
 
+vec_t vec_neg(vec_t v)
+{
+    vec_t result = {
+        .x = -v.x,
+        .y = -v.y
+    };
+
+    return result;
+}
+
+float vec_length(vec_t v)
+{
+    return sqrtf(v.x * v.x + v.y * v.y);
+}
+
 void vec_add(vec_t *v1, vec_t v2)
 {
     v1->x += v2.x;
@@ -32,3 +48,13 @@ vec_t vec_scala_mult(vec_t v, float scalar)
     };
     return result;
 }
+
+vec_t vec_entry_mult(vec_t v1, vec_t v2)
+{
+    vec_t result = {
+        .x = v1.x * v2.x,
+        .y = v1.y * v2.y
+    };
+
+    return result;
+}
index 1f1ebfc9080bab3206d683cb48cbe21c39e4375c..29d0f854810ce5535578e3c14755673210fe72e4 100644 (file)
@@ -9,7 +9,10 @@ typedef point_t vec_t;
 
 vec_t vec(float x, float y);
 vec_t vec_sum(vec_t v1, vec_t v2);
+vec_t vec_neg(vec_t v);
 void vec_add(vec_t *v1, vec_t v2);
+float vec_length(vec_t v);
 vec_t vec_scala_mult(vec_t v, float scalar);
+vec_t vec_entry_mult(vec_t v1, vec_t v2);
 
 #endif  // POINT_H_
index 0e98b7e71f58b4736f9f8356bf6e9ff241adfd6c..b2e498c5b4afb5eaf60bda7b71d43b11d7b1c28a 100644 (file)
@@ -47,7 +47,7 @@ void rect_object_impact(const rect_t *object,
             line_t object_side = rect_side(*object, side);
             line_t int_side = rect_side(int_area, side);
 
-            if (line_length(int_side) > 1.0f) {
+            if (line_length(int_side) > 10.0f) {
                 sides[side] =
                     (fabs(object_side.p1.x - object_side.p2.x) < 1e-6
                      && fabs(object_side.p1.x - int_side.p1.x) < 1e-6