0

Here's 2 methods available;

if(rectangle.Intersects(otherRectangle))
{
    //collision stuff
}

Catch: Only works with non-rotating rectangles.

if(Vector2.Distance(player.pos, enemy.pos) < 50)
{
    //collision stuff
}

Catch: Only works with circles.

What I want is to calculate x and y in this image: problem

Facts

The width and length of both rectangles is defined, along with their rotations. I can calculate D using the Pythagorean theorem. But the TRUE distance is D - (X + Y).

General approach

Evidently x and y can be calculated using the Cosine rule. But I only have the width or length and the angle between the two shapes.

Complication

Plus, this needs to work for any rotation. The rectangle on the left could be rotated in any direction, and x would be different depending on said rotation.

Question

How would I calculate x and y? I just want an effective collision detection method more complex than bounding boxes and Pythagoras' theorem.

3
  • 1
    "I just want an effective collision detection method more complex..." Be careful not to seek complexity... it will find you and you may regret it. Seriously though, search for SAT. Commented Feb 19, 2014 at 16:02
  • So do you want to use the Pythagorean theorem or not? You could also look into Vector2 methods, such as Vector2.Dot() Commented Feb 19, 2014 at 18:06
  • I need to use Pythagoras' theorem anyway to get the distance. Commented Feb 20, 2014 at 12:06

1 Answer 1

1

One approach is to rotate the line with the inverse angle and check with the axis-aligned box:

class RotatedBox 
{
    ...

    float CalcIntersectionLength(Vector2 lineTo) //assume that the line starts at the box' origin
    {
        Matrix myTransform = Matrix.CreateRotationZ(-this.RotationAngle);
        var lineDirection = Vector2.Transform(lineTo -this.Center, myTransform);
        lineDirection.Normalize();
        var distanceToHitLeftOrRight = this.Width / 2 / Math.Abs(lineDirection.X);
        var distanceToHitTopOrBottom = this.Height / 2 / Math.Abbs(lineDirection.Y);
        return Math.Min(distanceToHitLeftOrRight, distanceToHitTopOrBottom);
    }
}

Now you can calculate the actual distance with

 var distance = (box1.Center - box2.Center).Length
                - box1.CalcIntersectionLength(box2.Center)
                - box2.CalcIntersectionLength(box1.Center);

Be sure that the rotation direction matches your visualization.

Sign up to request clarification or add additional context in comments.

3 Comments

Center and lineTo would be what?
Center is the box' center and lineTo the line's target.
I just implemented this in a test application. It works. Make sure that Width belongs to the unrotated x-axis, Height belongs to the unrotated y-axis. Make sure that your visualization matches the data (i.e. correct center point, correct rotation direction). The center point in the video seems to be a bit off. I drew the sample box with sb.Draw(Texture, new Rectangle((int)Center.X, (int)Center.Y, (int)Width, (int)Height), null, Color.White, RotationAngle, new Vector2(Texture.Width / 2, Texture.Height / 2), SpriteEffects.None, 0);. RotationAngle has to be in radians.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.