Question

I have four 32 x 32 rectangles that I use for my game character (collectively they are a ship and each of the rectangles represents a cell (ship compartment) that has it's own collision detection system).

I keep these cells together in a 2x2 format. Moving the 'ship' along the X and Y axes is all fine. However, when I rotate the 'ship', the individual rectangles rotate and face the correct direction, but they are no longer 'together'. That is to say, rectangle A1's right border is out of sync with rectangle A2's left border, and so on...

How do I rectify the rectangles' positions so they are still aligned after rotation? This is my first game and I'm not a maths person, thus I find myself asking for your expertise in this matter!

Many thanks in advance for your assistance. If you require more information (i.e., code) then I will provide!

UPDATE:

I finally got this working! Below is my code. I hope this helps others!

//The point we want to rotate around (in this example, I was rotating around another ship)
Vector2 origin = new Vector2(selectedShip.Position.X, selectedShip.Position.Y);

test1.Position = Vector2.Transform(test1.Position - origin, Matrix.CreateRotationZ(testRot)) + origin;
test2.Position = Vector2.Transform(test2.Position - origin, Matrix.CreateRotationZ(testRot)) + origin;
test3.Position = Vector2.Transform(test3.Position - origin, Matrix.CreateRotationZ(testRot)) + origin;
test4.Position = Vector2.Transform(test4.Position - origin, Matrix.CreateRotationZ(testRot)) + origin;

// Alter the rotation of the four ship compartments for drawing
test1.Rotation += testRot;
test2.Rotation += testRot;
test3.Rotation += testRot;
test4.Rotation += testRot;

// Update rectangle positions
test1.Rect = new Rectangle((int)test1.Position.X, (int)test1.Position.Y, ship01Texture.Width, ship01Texture.Height);
test2.Rect = new Rectangle((int)test2.Position.X, (int)test2.Position.Y, ship01Texture.Width, ship01Texture.Height);
test3.Rect = new Rectangle((int)test3.Position.X, (int)test3.Position.Y, ship01Texture.Width, ship01Texture.Height);
test4.Rect = new Rectangle((int)test4.Position.X, (int)test4.Position.Y, ship01Texture.Width, ship01Texture.Height);

theSprite.Draw(ship01Texture, test1.Rect, null, Color.White, test1.Rotation, Vector2.Zero, SpriteEffects.None, 0.0f);
theSprite.Draw(ship01Texture, test2.Rect, null, Color.White, test2.Rotation, Vector2.Zero, SpriteEffects.None, 0.0f);
theSprite.Draw(ship01Texture, test3.Rect, null, Color.White, test3.Rotation, Vector2.Zero, SpriteEffects.None, 0.0f);
theSprite.Draw(ship01Texture, test4.Rect, null, Color.White, test4.Rotation, Vector2.Zero, SpriteEffects.None, 0.0f);

Big thanks to everyone that helped!

Was it helpful?

Solution 2

Anchor the rectangles at their center, not one of the four vertices.

You'll have an hierarchical structure:

  • a collection with a translation (the position of the center of the collection)
  • for each element in the collection you'll have a relative position to the collection's center

At that point, you'll have to rotate the position of the rectangles and the rectangles themselves this way:

  • rotate element at origin (before translation)
  • rotate relative position
  • add absolute position and relative position
  • translate rectangle

This is a little diagram:

+-----+-----+
|     |     |
|  e  |  e  |
|     |     |
+-----C-----+
|     |     |
|  e  |  e  |
|     |     |
+-----+-----+

C is the center of the collection, e are the centers of the elements. The relative position is the vector e-C. This is pretty basic stuff, it may sound difficult but it's just a matter of adding/subtracting vectors (positions) and rotating them by angles in the right order.

The order of translating/rotating the elements/collection is very important.

To rotate around the center of the rectangle:

RotateAboutOrigin(new Vector2(test1.Width / 2, test1.Height / 2), Vector2.zero, rotation)

At this point translate by the relative position, which is one of these (one line for each rectangle):

Vector2 p1 = new Vector2(+test1.Width / 2, +test1.Height / 2)
Vector2 p2 = new Vector2(+test2.Width / 2, -test2.Height / 2)
Vector2 p3 = new Vector2(-test3.Width / 2, +test3.Height / 2)
Vector2 p4 = new Vector2(-test4.Width / 2, -test4.Height / 2)

The actual mapping of relative translations to the rectangles has to be determined, here I just try to give an idea. By changing the actual lines up/down the right combination will be easy to find.

Finally, translate by the center of the cluster:

p1 + c // c is also a Vector2

All this code can afterwards be corrected and optimized by removing a lot of excess code and saving vectors in appropriate places. Especially the CreateRotationZ() inside RotateAboutOrigin should be cached, like this:

Matrix[] rot = new Matrix[64];

for(phi = 0; phi < 64; phi++)
{
    rot[phi] = Matrix.CreateRotationZ(phi / 64 * 2 * Math.PI);
}

In the example above you'll then have 64 matrices and a 64 step-wise rotation. You can then rotate only by discrete multiples of the minimum angle 1 / 64 * 2 * Math.PI. This will make the function much faster.

OTHER TIPS

From your question I'm assuming you started at the left and ended up with the middle image instead of the right.

enter image description here

The difference between the images in that the middle image the rectangles are all rotated around their individual centers instead of all being rotated about the same point.

See here for how to rotate around a given point

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top