diff options
| author | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:26:01 +0100 |
|---|---|---|
| committer | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:26:01 +0100 |
| commit | c15c603b35e86fd42e6db94a7382ba7a1ddadd6e (patch) | |
| tree | ab56040ce4768564bef5fbe9e65fe4c025cea6ce /collisions.c | |
Initial commit
Diffstat (limited to 'collisions.c')
| -rw-r--r-- | collisions.c | 130 |
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); + } + } + } +} |
