Problem rotating a rectangle around desired point

I’m drawing a rectangle in real time from a 1 x 1 pixel (stretching it). Everything works great EXCEPT it’s not rotating around the point I want. Apparently, there’s something weird about rotating a rectangle (as opposed to rotating a sprite). Here’s what I’ve got happening:


And here’s the code that creates it:

  Vector2 end = new Vector2 (BlueArmy[DisplayUnitID].Location.X, BlueArmy[DisplayUnitID].Location.Y);
                        Vector2 edge = ArrowEnd - end;
                        // calculate angle to rotate line
                        float angle =
                            (float)Math.Atan2(edge.Y, edge.X);

                        spriteBatch.Draw(BlueMovementArrow,
                            new Rectangle(// rectangle defines shape of line and position of start of line
                             (int)BlueArmy[DisplayUnitID].Location.X + LeftMapOffset, 
                             (int)BlueArmy[DisplayUnitID].Location.Y + TopMapOffset ,
                             (int)edge.Length(), //sb will strech the texture to fill this rectangle
                             PieceWidth), //width of line, change this to make thicker line
                             null,
                             Color.White * 0.5f, // opacity is 50%, 
                             angle,     //angle of line (calulated above)
                             new Vector2( 0, 0 ), // point in line about which to rotate
                             SpriteEffects.None,
                             0);

Whatever values I put into the Vector2 that controls rotation produces very weird results.
Anybody deal with rotating a rectangle that’s generated programmatically (not a sprite)?
Thanks.

I ended up doing away with the Texture2D 1x1 blue pixel and replaced it with a 5 x 5 blue sprite which you can set the origin on. Now it works the way I want:


I think it’s not really possible to set the origin for rect for rotation.

You can rotate a rectangle (or any other stretched out sprite, which is all this is even though it isn’t loaded from an xnb or whatever else). The origin is set from the point of view of the sprite, not the draw size. In your case, you’d want something like origin: new Vector2(0, 0.5f) since you want the origin to be half way down your 1x1 sprite. The origin parameter in the Draw method determines both the rotation point, and the “draw from” point. Meaning, when you set the X and Y in your rectangle, the origin value you set will be the part of the sprite that renders at that point.

Example code:

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;


namespace TestRectAngle
{
	public class Game1 : Game
	{
		private GraphicsDeviceManager _graphics;
		private SpriteBatch _spriteBatch;
		Texture2D plainTexture;


		public Game1()
		{
			_graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
			IsMouseVisible = true;
		}

		protected override void LoadContent()
		{
			_spriteBatch = new SpriteBatch(GraphicsDevice);

			plainTexture = new Texture2D(_graphics.GraphicsDevice, 1, 1);
			plainTexture.SetData(new Color[] { Color.White });
		}

		protected override void Update(GameTime gameTime)
		{
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
				Exit();

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.Tan);

			_spriteBatch.Begin();

			_spriteBatch.Draw(
				texture: plainTexture,
				destinationRectangle: new Rectangle(50, 10, 200, 50),
				sourceRectangle: null,
				color: Color.Blue * 0.5f,
				rotation: 0.5f,
				origin: new Vector2(0, 0),
				effects: SpriteEffects.None,
				layerDepth: 1f
			);

			_spriteBatch.Draw(plainTexture, new Rectangle(50, 10, 2, 2), Color.Red);
			_spriteBatch.Draw(plainTexture, new Rectangle(50, 35, 2, 2), Color.Red);

			_spriteBatch.End();

			base.Draw(gameTime);
		}
	}
}

Which draws:
topLeftRotation

But if you update these 2 lines:
destinationRectangle: new Rectangle(50, 35, 200, 50), // Y value has changed since we want it to rotate from this position
origin: new Vector2(0, 0.5f), // 0 for X, and 0.5 for Y since we want it to rotate from the left middle of the sprite (our 1x1 source texture), and then stretch it to our defined rectangle

It draws:
originRotation

Hope this helps!

1 Like

Wow! Thanks! For some reason, I just thought I couldn’t set Origin < 1. When I made a 5 x 5 sprite the offset

origin: new Vector2(0, 3),

worked perfectly. But, still this is good to know!
Many thanks!