0

I'm trying to understand circle-rectangle collision detection for a game like breakout with a ball and a paddle. I have a function that is supposed to return true if the circle and rectangle are colliding and false otherwise.

         function circleRectCollision(circle, rect) {
                let xDistBetweenCenters = Math.abs(circle.xPos - (rect.xPos + rect.width / 2));
                let yDistBetweenCenters = Math.abs(circle.yPos - (rect.yPos + rect.height / 2));
    
                // Exit conditions
                if (xDistBetweenCenters > circle.size + rect.width / 2) {
                    return false;
                }
                if (yDistBetweenCenters > circle.size + rect.height / 2) {
                    return false;
                }

                // If we've made it this far, this means the circle is either touching the rectangle or 
                // "relatively close" to touching it. The circle's center is somewhere inside
                // of a new, expanded rectangle that surrounds the original rectangle. This new rectangle's dimensions are what
                // would result from expanding each edge outward by the radius of the circle)
            }

However, knowing that the circle's center lives inside (or on an edge/corner) of this new outer rectangle is not enough to determine if the circle and rectangle are colliding. There is a small area near each corner of this outer rectangle that doesn't lead to collision. We have to round the corners, and then the outer rounded rectangle will represent every point that the circle's radius can reside in for there to be a collision between the circle and the original rectangle.

Now, I should mention that I'm not particularly good at math, so maybe my solution to try to find the distance between the rectangle's center and one of the rectangle's corners, then add the radius of the ball was naive. This is simple enough using the Pythagorean theorem/formula. I thought that this would give the maximum distance that the circle's center can be from the center of the rectangle for there to still be a collision. So, I added the following lines to the end of the function

                let maxDist = Math.sqrt((paddle.width / 2) ** 2 + (paddle.height / 2) ** 2) + circle.size;
                if (Math.sqrt(xDistBetweenCenters ** 2 + yDistBetweenCenters ** 2) <= maxDist) {
                    console.log("collision");
                }

However, this doesn't quite work. I'm still being notified that a collision is taking place even when the ball is touching air near the corners. Is it because the maximum distance that the circle's center can be from the rectangle's center while still touching is not equal to the distance between the circle's center and the rectangle's center when the circle is touching the rectangle's corner? Is this just the wrong approach altogether? My math must be off. (By the way, I am aware that using Math.sqrt is expensive and that squaring the numbers instead is better).

I've seen other solutions posed elsewhere like

cornerDistanceSq = Math.sqr(circleDistance.x - rect.width/2) +
                        Math.sqr(circleDistance.y - rect.height/2);
return (cornerDistanceSq <= (Math.sqr(circle.r)));

and

    var dx=distX-rect.w/2;
    var dy=distY-rect.h/2;
    return (dx*dx+dy*dy<=(circle.r*circle.r));

I'm not sure I understand why this works but my solution doesn't. Can someone explain in terms I can understand? Why does my math not work out, and why do these solutions work? Thanks.

fishgas
  • 23
  • 6
  • I recommend you to forget about this math. You need to find some trick. These games were implemented 30+ years ago on 1000-times slower computers without any support of math. And it worked, because they used quick tricks, not mathematics. – Al Kepp Mar 16 '21 at 23:23
  • Does this answer your question? [Collision Detection of Circle and Rectangle](https://stackoverflow.com/questions/34345765/collision-detection-of-circle-and-rectangle) – ggorlen Mar 17 '21 at 23:13

0 Answers0