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