#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); } } } }