TL-DR:
- Get vector from
circle2
to circle1
.
- Get its heading.
- Use that heading to determine which Cartesian quadrant the collision occurred in.
- 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.