15

Actually I am trying to detect thee collision of the Rectangle with the circle in the following piece of code:-

function checkCollision() {
     //checking of the Collision
     if (ry + rh > cy - radius && rx + rw > cx - radius && rx + rw < cx + radius ) {
          dy = -dy;
     }
}

This is also the part of my code:-

var rx = 50; //distance from the x-axis of the Rect. 
var ry = 50; //distance from the y-axis of the Rect.
var rw = 80; //width of the Rect
var rh = 30; //Height of the Rect.

// Distance to moved of the Rect.
var dx = 2;
var dy = 2;

// Center of the circle from the x-axis and y-axis.
var cx = 105;
var cy = 135;
var radius = 16;
var cx1 = 6;
var cy1 = 6;

Can anyone help me out here to figure out what is wrong?

3 Answers 3

56

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));
}
Sign up to request clarification or add additional context in comments.

10 Comments

I know this solution is very good ,,,i have seen the fiddle file and really thanks for that guys @markE ,,but actually i have just started the html5 canvas,,it is not so tough code,,,but neither of my need,,,i am actually having a type of ping-pong game where i have to detect collision between the circle(paddle) and rectangle(obj acting as ball) thats it..!!! hope u can derive a simple sol for that..!!
@markE This version is more streamlined in case you consider the rectangle "solid" (the circle is considered colliding when inside the rectangle). I ran it through my test fiddle, and it worked like a charm.
,yaah working superb,,i will look through in near time,,busy now,,,but thanks and awesome work @kuroi neko..!!!
WARNING This code expects that the x and y of the circle are the center, but the x and y of the rectangle to be the upper left corner. Hopefully this saves someone the time and pain I just went through debugging my collision code.
To be more specific the rect.x and rect.y are actually rect.topLeftX and rect.topLeftY. In my case, in Rectangle object x and y where the center of the coordinates of the center of the rect. It depends on how you build the objects and also as stated above, you need to take into consideration that this is Canvas 2d, where the upper-left corner has the coordinates (0,0).
|
2

I found I came across problems with the selected answer. Here's mine that, I think works well:

function collisionCheckCircleRect(circle, rect)
{
    var distx = Math.abs(circle.x - rect.x);
    var disty = Math.abs(circle.y - rect.y);

    if (distx > (rect.width/2 + circle.radius)) { return false; }
    if (disty > (rect.height/2 + circle.radius)) { return false; }

    if (distx <= (rect.width/2)) { return true; } 
    if (disty <= (rect.height/2)) { return true; }

    var hypot = (distx - rect.width/2)*(distx- rect.width/2) +
                         (disty - rect.height/2)*(disty - rect.height/2);

//console.log(hypot <= (circle.radius*circle.radius))
    return (hypot <= (circle.radius*circle.radius));
}

2 Comments

Can anyone explain the steps? For my understanding it’s much clearer and easier this way:
In pseudo code: ``` boolean checkCollision(rect, circle) { closest.x = circle.x; closest.y = circle.y; if (circle.x < rect.x) closest.x = rect.x; else if (circle.x > rect.x + rect.width) closest.x = rect.x + rect.width; if (circle.y < rect.y) closest.y = rect.y; else if (circle.y > rect.y + rect.height) closest.y = rect.y + rect.height; delta.x = circle.x - closest.x; delta.x = circle.y - closest.y; return delta.x * delta.x + delta.y * delta.y <= circle.radius * circle.radius; ```
0
boolean checkCollision(rect, circle)
{
    closest.x = circle.x;
    closest.y = circle.y;
 
    if (circle.x < rect.x)
        closest.x = rect.x;
    else if (circle.x > rect.x + rect.width)
        closest.x = rect.x + rect.width;
 
    if (circle.y < rect.y)
         closest.y = rect.y;
    else if (circle.y > rect.y + rect.height)
        closest.y = rect.y + rect.height;

    delta.x = circle.x - closest.x;
    delta.y = circle.y - closest.y;

    distanceSquared = delta.x * delta.x + delta.y * delta.y;
    radiusSquared = circle.radius * circle.radius;
    

    return distanceSquared <= radiusSquared;
}

For me this is much more clearer. Can anyone explain the other method, posted here? Sadly it did unformat my pseudo-code in the comment.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.