-1
\$\begingroup\$

Say I have a circle of diameter c and a square with a base of s.

Is there a simple formula to check whether they have collided?

Something like distance(square, circle) < s / 2 + c / 2 where distance(square, circle) finds the distance between the centers of the objects?

I know the full solution is more complicated due to diagonals, but would my formula be OK in a fast moving game where exact precision is not required? Is there another "good enough" solution which is simple to implement?

enter image description here

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Does this answer your question? Problems with moving 2D circle/box collision detection \$\endgroup\$ – Tyyppi_77 Mar 7 '20 at 9:47
  • 1
    \$\begingroup\$ Also gamedev.stackexchange.com/q/96337/35344 \$\endgroup\$ – Tyyppi_77 Mar 7 '20 at 9:47
  • \$\begingroup\$ Not really. I'm more looking for a simple rule of thumb to use when accurate collision detection is not required. \$\endgroup\$ – Robin Andrews Mar 7 '20 at 9:58
  • 2
    \$\begingroup\$ "good enough" is s̶u̶b̶j̶e̶t̶i̶v̶e context sensitive. On one hand, usually you will be trading performance and precision. On the other, this depends on the genre, for example an RPG will probably not need perfect collision detection. Even in a shooter you may be sloppy with enemy colliders to make it easier on players. Which reminds me, you got decide if you prefer false positives or false negatives. However, it seems to me you just want validation for your implementation. To that I say, try it out. If alpha testers like it, then move forward. \$\endgroup\$ – Theraot Mar 7 '20 at 12:36
2
\$\begingroup\$

We can think of collisions between a square and a circle as a collision between a rounded square and a point. Effectively, we strip off all the "round stuff" making up the disc, and add it onto the square instead (an operation called Minkowski addition).

Diagram showing a square-circle collision mapping to a point inside the rounded rectangle, and a separated case mapping to a point outside.

If the the remaining center point of the circle is inside the rounded square, then the original square and circle collide. If there's a separation between the point and the rounded square, then the original square and circle are separated by this same distance.

We can quickly compute the signed distance of a point from a rounded rectangle (a square is just a special rectangle with equal width and height) using the formula provided by Inigo Quilez here:

float Separation(Rectangle rectangle, Circle circle) {

    // Here I assume the square is never rotated, and stays axis-aligned.
    Vector2 relativeCenter = circle.center - rectangle.center;

    Vector2 offsetFromCorner = abs(relativeCenter) - rectangle.halfExtents;

    return min(max(offsetFromCorner.x, offsetFromCorner.y), 0)
         + length(max(offsetFromCorner, Vector2.zero))
         - circle.radius;
}

If this value is negative, the circle and square overlap by this penetration distance. If it's positive, they're separated by this distance. If it's zero, they're kissing exactly edge-to-edge / edge-to-corner.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.