0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Have you tried to force a round up? rect2.X -= (int)depth.X + 1; \$\endgroup\$ – Steve H Jun 30 '15 at 13:13
2
\$\begingroup\$

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 CombinedRadius = c1.radius + c2.radius;
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.

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

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.