So, I had this code working for AABB collision until I decided to make a sprite bigger on Y axis than in X axis. I tried to fix the code but now it just doubles the collision size than the actual sprite size. ex. size of sprite 1 iVec2(50,100), size of sprite 2 iVec2(30,30).
CollisionData Collision::DoCollision(GameObject &object1, GameObject &object2) {
iVec2 center(object1.Position.x + object1.Size.x / 2, object1.Position.y + object1.Size.y / 2);
iVec2 half_extents(object2.Size.x / 2, object2.Size.y / 2);
iVec2 aabb_center(object2.Position.x + half_extents.x, object2.Position.y + half_extents.y);
iVec2 difference = center - aabb_center;
iVec2 difference2 = center - aabb_center;
iVec2 clamped = glm::clamp(difference, -half_extents, half_extents);
iVec2 clamped2 = glm::clamp(difference2, -iVec2(object1.Size.x / 2, object1.Size.y / 2), iVec2(object1.Size.x / 2, object1.Size.y / 2));
iVec2 closest = aabb_center + clamped;
iVec2 closest2 = aabb_center + clamped2;
difference = closest - center;
difference2 = closest2 - center;
if (glm::length(difference) <= object1.Size.x / 2 || glm::length(difference2) <= object1.Size.y / 2)
return std::make_tuple(GL_TRUE, VectorDirection(difference), difference);
else return std::make_tuple(GL_FALSE, UP, glm::vec2(0, 0));
}
I recommend to do a simple overlap check.
If 2 segments are overlapping, can be checked by:
overlap = (x1+w1) > x2 && (x2+w2) > x1
where x1
is the start and w1
the width of the first segment. x2
is the start and w2
the width of the 2n segment.
If you want to check if to axis aligned bounding boxes are overlapping, then ypu have to do the test for both dimensions
bool overlap =
(object1.Position.x + object1.Size.x) > object2.Position.x) &&
(object2.Position.x + object2.Size.x) > object1.Position.x) &&
(object1.Position.y + object1.Size.y) > object2.Position.y) &&
(object2.Position.y + object2.Size.y) > object1.Position.y);
If you want to know the amount of the overlapping, the you have to calculate the center points of the boxes and to compare the distance of the center points, to common half size of the boxes:
CollisionData Collision::DoCollision(GameObject &object1, GameObject &object2) {
iVec2 center1(
object1.Position.x + object1.Size.x / 2,
object1.Position.y + object1.Size.y / 2);
iVec2 center2(
object2.Position.x + object2.Size.x / 2,
object2.Position.y + object2.Size.y / 2);
iVec2 dist = center1 - center2;
iVec2 size((object1.Size.x + object2.Size.x) / 2, (object1.Size.y + object2.Size.y) / 2);
iVec2 difference = size - iVec2(abs(dist.x), abs(dist.y));
bool overlap = difference.x > 0 && difference.y > 0;
if ( overlap )
{
iVec2 min1 = object1.Position;
iVec2 min2 = object2.Position;
iVec2 max1 = object1.Position + object1.Size;
iVec2 max2 = object2.Position + object2.Size;
bool horizontal = difference.x > difference.y;
if ( min2.x > min1.x && max1.x < max2.x || min1.x > min2.x && max2.x < max1.x )
horizontal = false;
else if ( min2.y > min1.y && max1.y < max2.y || min1.y > min2.y && max2.y < max1.y )
horizontal = true;
return std::make_tuple(
GL_TRUE, !horizontal ? (dist.x < 0 ? LEFT: RIGHT) : (dist.y < 0 ? UP : DOWN), difference );
}
return std::make_tuple(GL_FALSE, UP, glm::vec2(0, 0));
}