Detecting collision of rectangle with circle

Detecting circle-rect collisions is not trivial (but not that complicated either).

@kuroi neko’s solution is correct and about as simple as the code is going to get.

Luckily, you don’t need to fully understand the math theory to use the hit-test function.

If you do want more details about how the function works, here is a description using 4 steps to test if a circle and a rectangle are colliding:

Demo: http://jsfiddle.net/m1erickson/n6U8D/

First, define a circle and a rectangle

var circle={x:100,y:290,r:10};
var rect={x:100,y:100,w:40,h:100};

Step#1: Find the vertical & horizontal (distX/distY) distances between the circle’s center and the rectangle’s center

    var distX = Math.abs(circle.x - rect.x-rect.w/2);
    var distY = Math.abs(circle.y - rect.y-rect.h/2);

Step#2: If the distance is greater than halfCircle + halfRect, then they are too far apart to be colliding

    if (distX > (rect.w/2 + circle.r)) { return false; }
    if (distY > (rect.h/2 + circle.r)) { return false; }

Step#3: If the distance is less than halfRect then they are definitely colliding

    if (distX <= (rect.w/2)) { return true; } 
    if (distY <= (rect.h/2)) { return true; }

Step#4: Test for collision at rect corner.

  • Think of a line from the rect center to any rect corner
  • Now extend that line by the radius of the circle
  • If the circle’s center is on that line they are colliding at exactly that rect corner

Using Pythagoras formula to compare the distance between circle and rect centers.

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

Heres the full code:

var circle={x:100,y:290,r:10};
var rect={x:100,y:100,w:40,h:100};

// return true if the rectangle and circle are colliding
function RectCircleColliding(circle,rect){
    var distX = Math.abs(circle.x - rect.x-rect.w/2);
    var distY = Math.abs(circle.y - rect.y-rect.h/2);

    if (distX > (rect.w/2 + circle.r)) { return false; }
    if (distY > (rect.h/2 + circle.r)) { return false; }

    if (distX <= (rect.w/2)) { return true; } 
    if (distY <= (rect.h/2)) { return true; }

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

Leave a Comment