uint8 obj_collide_hitbox (obj_t *obj, hitbox_t *testbox) { int32 a; uint8 ret = 0; fixed *delta; fixed *omina, omaxa, tmina, tmaxa; fixed ominb, omaxb, tminb, tmaxb; if (obj->flags & OF_NOCLIP) return 0; for (a = 0; a < 2; a++) { // 'a' is current axis, 'b' is opposite if (!a) // Y Axis { if (obj->hitbox.y + obj->deltay > testbox->y + testbox->h || obj->hitbox.y + obj->hitbox.h + obj->deltay < testbox->y) // not touching continue; tmina = testbox->y; tmaxa = tmina + testbox->h; omina = &obj->hitbox.y; omaxa = *omina + obj->hitbox.h - 1; tminb = testbox->x; tmaxb = tminb + testbox->w; ominb = obj->hitbox.x; omaxb = ominb + obj->hitbox.w - 1; delta = &obj->deltay; } else // X axis { if (obj->hitbox.x + obj->deltax > testbox->x + testbox->w || obj->hitbox.x + obj->hitbox.w + obj->deltax < testbox->x) // not touching continue; tmina = testbox->x; tmaxa = tmina + testbox->w; omina = &obj->hitbox.x; omaxa = *omina + obj->hitbox.w - 1; tminb = testbox->y; tmaxb = tminb + testbox->h; ominb = obj->hitbox.y; omaxb = ominb + obj->hitbox.h - 1; delta = &obj->deltax; } // test for actual intersection if ((ominb > tminb && ominb < tmaxb) || (omaxb > tminb && omaxb < tmaxb) || (tminb > ominb && tmaxb < omaxb)) { fixed cost; // Which side are we going into? // Only correct if this is the cheapest way out if (*delta < 0 && *omina + *delta <= tmaxa) // left/up { cost = abs (tmaxa - *omina); if (cost <= abs (omaxb - tminb) && cost <= abs (ominb - tmaxb)) { *delta = 0; *omina = tmaxa; } } else if (*delta > 0 && omaxa + *delta >= tmina) // right/down { cost = abs (tmina - omaxa); if (cost <= abs (omaxb - tminb) && cost <= abs (ominb - tmaxb)) { *delta = 0; *omina = tmina - (1 + omaxa - *omina); } } ret = 1; } } return ret; }