# Circle Depth Penetration

I'm resolving some collision between circles and I keep getting this problem.

Note: The rectangles are perfect squares fitting the circles so when I type rect.Width I mean the radius of the circle.

What I was trying to do was make it so that if it penetrated it would get pushed out and then the else if would take over and not call the if anymore. but the depth turns out to be a small number such as .6 and then since it's a float it rounds down and doesn't affect the rectangle at all. Even if I add a round function in there it just starts to jitter a bunch.

if (r < rect2.Width / 2 + rect1.Width / 2 && (fN + fG + fA).Length() != 0)
{
// Resolve depth penetration
float mDepth = rect2.Width / 2 + rect1.Width / 2 - r;
Vector2 depth = new Vector2(mDepth * (float)Math.Cos(theta), mDepth * (float)Math.Sin(theta));
rect2.X -= (int)depth.X;
rect2.Y -= (int)depth.Y;

// Apply an equal and opposite force
fN = -fG

// Stop the earth from moving
v2 = Vector2.Zero;
}
else if(r == rect2.Width / 2 + rect1.Width / 2)
fN = -fG;
else
fN = Vector2.Zero;


I also tried changing depth penetration too this but the results are no different.

float mDepth = rect2.Width / 2 + rect1.Width / 2 - r;
Vector2 direction = rect1.Location.ToVector2() - rect2.Location.ToVector2();
direction.Normalize();
Vector2 depth = direction * mDepth;
rect2.X -= (int)depth.X;
rect2.Y -= (int)depth.Y;


The only solution we could think of is creating a range of 5 in which the object could be at rest.

if (r < rect2.Width / 2 + rect1.Width / 2 + 5 && r > rect2.Width / 2 + rect1.Width / 2)
fN = -fG;
else if (r < rect2.Width / 2 + rect1.Width / 2 && (fN + fG + fA).Length() != 0)
{
// Resolve depth penetration
float mDepth = rect2.Width / 2 + rect1.Width / 2 - r;
Vector2 depth = new Vector2(mDepth * (float)Math.Cos(theta), mDepth * (float)Math.Sin(theta));
rect2.X -= (int)depth.X;
rect2.Y -= (int)depth.Y;

// Apply an equal and opposite force
fN = -fG;

// Stop the earth from moving
v2 = Vector2.Zero;
}
else
fN = Vector2.Zero;


Is there not a better way to do this?

Here is a video outlining the problem. https://www.youtube.com/watch?v=ZREQDA5BN0s Essentially since depth resolution isn't exact the == part of the if statement isn't used I know this because I placed a breakpoint in the first if statement it keeps going there with a depth of around .6. Then rounds down and doesn't move it at all. If I round it appropriately it just jitters a bunch.

• Have you tried to force a round up? rect2.X -= (int)depth.X + 1; Jun 30 '15 at 13:13

Yes, you can do this with no expensive trig at all.

Steps:

1. Find the distance between the 2 circles.
2. Find the combined radius between the 2 circles.
3. Subtract the distance from the combined radius to get the depth of the penetration.
4. Multiply the direction between the circles by the penetration depth.

I.e.:

Circle c1;
Circle c2;

float Distance = (c1.position - c2.position).magnitude;
float Depth = CombinedRadius - Distance;

Vector2 Direction = (c1.position - c2.position).normalized;
Vector2 Penetration = Direction * depth;

//Resolve the collision
c1.position -= Penetration / 2;
c2.position += Penetration / 2;


That's the penetration of 2 circles. As for a circle and an axis-aligned square, I'm not really sure where you were going with it but the penetration vector is just the penetration of the objects' bounding boxes.

If you want to be more accurate, you could find the direction between the circle and squares' centers then project the circle and square onto it, then find the penetration vector by subtracting the circle and square's extents on that direction.

• I tried this but it didn't produce any different results. Object 2 supposed to be immovable so I left out the penetration / 2. Jun 30 '15 at 8:08
• What shapes are the objects? Jun 30 '15 at 20:17
• They are circles. Jun 30 '15 at 23:37
• Change the last 2 lines to this: c1.position -= Penetration. The other way around if c1 is immovable and c2 isn't. Jul 1 '15 at 0:07
• I edited my original poster to show me trying that. where it says rect2.X -= (int)depth.X and rect2.Y -= (int)depth.Y Jul 1 '15 at 0:35