1
\$\begingroup\$

I'm trying to detect collision between two circles like this:

var circle1 = {radius: 20, x: 5, y: 5}; //moving
var circle2 = {radius: 12, x: 10, y: 5}; //not moving

var dx = circle1.x - circle2.x;
var dy = circle1.y - circle2.y;
var distance = Math.sqrt(dx * dx + dy * dy);


if (distance < circle1.radius + circle2.radius) {
    // collision detected

}else{ 
    circle1.x += 1 * Math.cos(circle1.angle);
    circle1.y += 1 * Math.sin(circle1.angle);
}

Now when collision is detected I want to slide the circle1 from on the circle2 (circle1 is moving) like this:

enter image description here
--circle1---------------------------------circle2-------------------------

I could do this by updating the angle of circle1 and Moving it toward the new angle when collision is detected.

Now My question is that how can I detect whether to update/increase the angle or update/decrease the angle based on which part of circle2 circle1 is colliding with ??

I would appreciate any help

\$\endgroup\$
1
\$\begingroup\$

TL-DR:

  1. Get vector from circle2 to circle1.
  2. Get its heading.
  3. Use that heading to determine which Cartesian quadrant the collision occurred in.
  4. Based on the direction circle1 is heading, turn left or right based on which side of circle2 circle1 touched to steer away from the other circle.

If you have the x and y of both circles, you could see which 'quadrant' of the non-moving circle the moving circle hits, and go from there.

Use some simple vector math. Get a vector in (x, y) from the centre of the non-moving circle to the moving one. It will be handy ot know that the vector going from A to B is $$\vec{C} = \vec{B} - \vec{A}$$ and the heading of a vector (in computing, anyways, I'm not sure about regular linear algebra) is atan2(c.y, c.x);. This is a built in Javascript function. This is how p5.js does it, and where I got this from.


Get vector which points from circle1 to circle2:

let vecBetweenX = circle2.x - circle1.x;
let vecBetweenY = circle2.y - circle1.y;

Get its heading:

let heading = Math.atan2(vecBetweenY, vecBetweenX);
// or in degrees:
heading = heading * 180 / Math.PI;

Based on how the atan2 function returns angles, get it's quadrant by checking where in the unit circle it falls:

let quadrant;
if (heading <= 0 && heading > -1 * Math.PI / 2) quadrant = 0;
else if (heading <= -1 * Math.PI / 2 && heading >= -1 * Math.PI) quadrant = 1;
else if (heading >=  0 && heading < Math.PI / 2) quadrant = 3;
else if (heading >= Math.PI / 2 && heading <= Math.PI) quadrant = 2;

// or in degrees:

let quadrant;
if (heading <= 0 && heading > -90) quadrant = 0;
else if (heading <= -90 && heading >= -180) quadrant = 1;
else if (heading >=  0 && heading < 90) quadrant = 3;
else if (heading >= 90 && heading <= 180) quadrant = 2;

This tells you which quarter of the non-moving circle the moving circle has hit, with

  • quadrant = 0 being the top right;
  • quadrant = 1 being the top left;
  • quadrant = 2 being the bottom left;
  • quadrant = 3 being the bottom right.

Then, based on what direction the moving circle is headed, change the angle. I'm not sure how you're implementing the angle of the moving circle, so here's some pseudo-code, assuming you're going to increase or decrease circle1.angle when you want to turn.

if ( /*circles touch*/ ) {
  if (circle.angle == /*moving right*/ ) {
    /* should only ever touch quadrant 1 or 2 if it's moving right */
    angle += (quadrant == 1 /*touch top left*/) ? /*turn left*/ : /*turn right*/;

  } else if (circle.angle == /*moving left*/ ) {
    /* should only ever touch quadrant 0 or 3 if it's moving right */
    angle += (quadrant == 0 /*touch top right*/) ? /*turn right*/ : /*turn left*/;

  } else if (circle.angle == /*moving down*/ ) {
    /* should only ever touch quadrant 0 or 1 if it's moving down */
    angle += (quadrant == 0 /*touch right-hand-side*/) ? /*turn left*/ : /*turn right*/;

  } else if (circle.angle == /*moving up*/ ) {
    /* should only ever touch quadrant 2 or 3 if it's moving up */
    angle += (quadrant == 2 /*touch left-hand-side*/) ? /*turn left*/ : /*turn right*/;
  }
}

I hope I understood what you're asking. This is the most intuitive solution that comes to my mind without using an actual physics engine/rigid collisions.

|improve this answer|||||
\$\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.