aboutsummaryrefslogtreecommitdiff
path: root/collisions.c
diff options
context:
space:
mode:
authorThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:26:01 +0100
committerThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:26:01 +0100
commitc15c603b35e86fd42e6db94a7382ba7a1ddadd6e (patch)
treeab56040ce4768564bef5fbe9e65fe4c025cea6ce /collisions.c
Initial commit
Diffstat (limited to 'collisions.c')
-rw-r--r--collisions.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/collisions.c b/collisions.c
new file mode 100644
index 0000000..e9f0c13
--- /dev/null
+++ b/collisions.c
@@ -0,0 +1,130 @@
+#include "game.h"
+
+struct FRect
+{
+ float x, y, w, h;
+};
+
+static inline bool colliding2D(const struct FRect *a, const struct FRect *b)
+{
+ return ((a->x + a->w > b->x && a->x < b->x + b->w)
+ && (a->y + a->h > b->y && a->y < b->y + b->h));
+}
+
+bool frect_intersect(const struct FRect *a, const struct FRect *b, struct FRect *res)
+{
+ res->x = fmaxf(a->x, b->x);
+ res->w = fminf(a->x + a->w, b->x + b->w) - fmaxf(a->x, b->x);
+ res->y = fmaxf(a->y, b->y);
+ res->h = fminf(a->y + a->h, b->y + b->h) - fmaxf(a->y, b->y);
+
+ return colliding2D(a, b);
+}
+
+bool colliding_vertically(const struct Entity *a, const struct Entity *b, const struct FRect *res)
+{
+ //return a->y + a->h < b->y + b->h / 2.0f || b->y + b->h < a->y + a->h / 2.0f;
+ return res->w > res->h;
+}
+
+void collide_with_fixed(struct Entity *e, struct Entity *fixed, const struct FRect *res)
+{
+ // Check if either of the boxes
+ if( colliding_vertically(e, fixed, res) )
+ {
+ e->y += (e->y < fixed->y) ? -res->h : res->h;
+ e->dy = 0.0f;
+ }
+ else
+ {
+ e->x += (e->x < fixed->x) ? -res->w : res->w;
+ e->dx = 0.0f;
+ }
+}
+
+void collide(struct Entity *a, struct Entity *b, const struct FRect *res)
+{
+ float a_disp, b_disp;
+
+ float vx_sum, vy_sum;
+ vx_sum = fabsf(a->dx) + fabsf(b->dx);
+ vy_sum = fabsf(a->dy) + fabsf(b->dy);
+
+ // Check if either of the boxes
+ if( colliding_vertically(a, b, res) )
+ {
+ a_disp = vy_sum == 0.0f ? res->h / 2.0f : res->h * (fabsf(a->dy) / vy_sum);
+ b_disp = vy_sum == 0.0f ? res->h / 2.0f : res->h * (fabsf(b->dy) / vy_sum);
+ //a_disp = res->h / 2.0f;
+ //b_disp = res->h / 2.0f;
+
+ a->y += (a->y < b->y) ? -a_disp : a_disp;
+ b->y -= (a->y < b->y) ? -b_disp : b_disp;
+
+ a->dy = 0.0f;
+ b->dy = 0.0f;
+ }
+ else
+ {
+ a_disp = vx_sum == 0.0f ? res->w / 2.0f : res->w * (fabsf(a->dx) / vx_sum);
+ b_disp = vx_sum == 0.0f ? res->w / 2.0f : res->w * (fabsf(b->dx) / vx_sum);
+ //a_disp = res->w / 2.0f;
+ //b_disp = res->w / 2.0f;
+
+ a->x += (a->x < b->x) ? -a_disp : a_disp;
+ b->x -= (a->x < b->x) ? -b_disp : b_disp;
+
+ a->dx = 0.0f;
+ b->dx = 0.0f;
+ }
+}
+
+void check_collisions(void)
+{
+ int i, j;
+ struct Entity *a, *b;
+
+ for(i = 0; i < game->num_entities; i ++)
+ {
+ a = game->entities[i];
+
+ if(!a)
+ continue;
+
+ for(j = i + 1; j < game->num_entities; j ++)
+ {
+ b = game->entities[j];
+
+ if(!b)
+ continue;
+
+ struct FRect res;
+ struct FRect r1 = {a->x, a->y, a->w, a->h};
+ struct FRect r2 = {b->x, b->y, b->w, b->h};
+
+ if( frect_intersect(&r1, &r2, &res) )
+ {
+ if(a->collidable && b->collidable)
+ {
+ if(!a->fixed && !b->fixed)
+ {
+ collide(a, b, &res);
+ }
+ else if(a->fixed && !b->fixed)
+ {
+ collide_with_fixed(b, a, &res);
+ }
+ else if(!a->fixed && b->fixed)
+ {
+ collide_with_fixed(a, b, &res);
+ }
+ }
+
+ if(a->on_collision)
+ a->on_collision(a, b);
+ if(b->on_collision)
+ b->on_collision(b, a);
+ }
+ }
+ }
+}