0
\$\begingroup\$

I have a circle and a rectangle one of the two objects is moving the other is static. How can I prevent them from overlapping each other? For now there is only one thing that I don't know how to calculate - the depth between the two objects. Could you tell me how to do that? I am using monogame

public void CircleVsRectangle(CircleBody circle, RectangleBody rect)
{
  float circleDistanceX = Math.Abs(circle.CenterX - rect.CenterX);
  float circleDistanceY = Math.Abs(circle.CenterY - rect.CenterY);

  Vector2 circleDistance = new Vector2(circleDistanceX, circleDistanceY);

  if (circleDistance.X > (rect.Width / 2 + circle.Radius)) { return false; }
  if (circleDistance.Y > (rect.Height / 2 + circle.Radius)) { return false; }

  if (circleDistance.X <= (rect.Width / 2)) { return true; }
  if (circleDistance.Y <= (rect.Height / 2)) { return true; }

  float cornerDistance_sq = ((circleDistance.X - rect.Width / 2) * (circleDistance.X - rect.Width / 2)) + ((circleDistance.Y - rect.Height / 2) * (circleDistance.Y - rect.Height / 2));

  if( (cornerDistance_sq <= (circle.Radius * circle.Radius)))
  {
  float dept = CalcDept() // ??????
  if(circle.IsMoving) circle.position += dept;
  else if(rectangle.IsMoving) rect.position += dept;
  }
}
\$\endgroup\$
1
1
\$\begingroup\$

To get the distance and the separation/collision normal you reduce the "circle to aabb" to a "point to plane" problem which can be easily solved.

In detail:

  • Get closest point from circle center to aabb

  • Get distance from closest point to circle center

  • Create a normalized version of this distance vector (Separation normal)

  • Project the distance onto the separation normal (Voila, you have your depth scalar)

There is one downside for this approach, if the circle center is inside the aabb you need to find the axis for the smallest penetration instead and use a point to plane approach again.

\$\endgroup\$
0
\$\begingroup\$

You should take a look at this classic tutorial on the Separating Axis Theorem.

There is too much maths involved to reasonably reproduce it here.


Note that, in your code, you've got CalcDept returning a float (1D value), and you're attempting to add it to position (a 2D value). This is not correct.

If you look at Section 3 of the tutorial, you'll note that there are six possible axes along which a rectangle and a circle could interpenetrate. So your "depth" is always going to be associated with an axis (a direction) - so it will be a 2D value (a Vector2).


In most cases, however, you should use a pre-built solution such as Farseer Physics Engine.

\$\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.