How would I go about making a rotated bounding box rectangle as well as getting the displacement vector for the intersecting object?

Right now I have a grid aligned solution in a method, probably not the most efficient, but it works.

if (this.hitbox.box.Intersects(o.hitbox.box) && (o.id != this.id))
        {
				intersect = Rectangle.Intersect(this.hitbox.box, o.hitbox.box);

				float widthRatio = (float)intersect.Width / this.hitbox.box.Width;
				float heightRatio = (float)intersect.Height / this.hitbox.box.Height;

				if (widthRatio > heightRatio)
            {
					this.velocity = new Vector2(this.velocity.X, 0);

					if (intersect.Center.Y < o.hitbox.absOrigin.Y)
                {
						UpdatePosition(new Vector2(this.position.X, this.position.Y - intersect.Height));
					}
					else if (intersect.Center.Y > o.hitbox.absOrigin.Y)
                {
						UpdatePosition(new Vector2(this.position.X, this.position.Y + intersect.Height));
					}
				}
				else if (widthRatio < heightRatio)
				{
					this.velocity = new Vector2(0, this.velocity.Y);

					if (intersect.Center.X < o.hitbox.absOrigin.X)
					{
						UpdatePosition(new Vector2(this.position.X - intersect.Width, this.position.Y));
					}
					else if (intersect.Center.X > o.hitbox.absOrigin.X)
					{
						UpdatePosition(new Vector2(this.position.X + intersect.Width, this.position.Y));
					}
				} 
				else if (widthRatio == heightRatio)
				{
					this.velocity = new Vector2(0, 0);
					UpdatePosition(new Vector2(this.position.X - intersect.Width, this.position.Y - intersect.Height));
                }
           }
     }
}

The Method UpdatePosition() updates the position of the rectangle of the sprite and the rectangle of the bounding box for the next Update().

Currently it only supports aligned rectangles, because it depends on the coordinate grid being aligned with the rectangles as well as the Rectangle struct not supporting rotation.

I would try to extend the Rectangle struct to include a rotation, but I have no idea how to do that.

I’ve heard there’s an extension library, I’m not sure if that might have my solution.

I’m pretty bad at vectors so I would appreciate any help. (Also why are rotated rectangles not built in? :expressionless:)

Intersection with a rotated rectangle is a different beast. There are probably many ways to solve this (I recommend you google around), but I think you can solve this with polygon collision tests. If you divide your bounding box into two triangles, which are then comprised of three line segments, you can test if any of those line segments intersect the line segments of the bounding box you’re checking against. I think you not only have to test intersection, but containment of the points too (since no segments could intersect as they would all be inside one of the bounding boxes).

To test if any given point inside a polygon, I believe you consider a line segment from some outside point (ie, -9999, -9999, assuming that’s outside your world) and count the intersections of the destination polygon. If there’s an odd number of intersections, the point is inside. If there’s an even number of intersections the point is outside. I think that requires a convex hull but I’m not actually sure, it’s been a while.

You can probably find the equation for line intersection on the interwebs but if not, it’s easy to derive.

The equation of a line is [x, y] = [x0, y0] + [Dx, Dy] * t, where [x, y] is the resulting point on the line, [x0, y0] is the starting point of the line, [Dx, Dy] is the x and y components of the line’s direction, and t is a value that denotes where you are on the line. For example, if you have a vector between A and B, you can calculate that as B - A (you can just do this with MonoGame Vec2). You can then normalize that vector to get the direction. With the starting point being A, if you use the line equation with t = 0 you will get point A. If you do it with t = 1 you will get point B. If you use t = 2 you will get a line that is twice as long as the original line.

Now consider two vectors, one between A and B (B - A, or BA, normalized to BAn) and one between C and D (D - C, or DC, normalized to DCn). You can test to see if they intersect by setting their two line equations equal to each other… [Ax, Ay] + [BAnx, BAny] * t = [Cx, Cy] + [DCnx, DCny] * s (where s is just the scale variable, like t, for the second line).

This equation either has a solution, which is the intersection point, or no solution because the lines are parallel. I’ll let you work on the math for that since learning about vectors is pretty important if you want to do this kind of stuff :slight_smile:

Last thing of note is that this calculation for collision is more computationally complex than the AABB collision test (bounding box) that you’re doing above. This means you probably want to do a two-stage collision test. A simple test to see if your objects are even in the ballpark of each other, then a more complex test to see if they are actually colliding. For a simple test, you can use the bounding box test you’re already doing, where the bounding box will be the minimal rectangle that contains your hit polygons, or you can use a bounding circle method, with a minimal circle that contains your polygons.

That was a big information dump! Give it a go. Also, that’s just how I would solve it right now based on the things I know. It’s definitely worth googling around. Maybe there’s a simpler method, or someone has already packaged this up into a library that you can use (though I still recommend taking the time to learn it).

I hope that helps! Good luck :slight_smile:

1 Like