Rotation in place?

So, I’m trying to render a hex tile grid. I use the following code to calculate the size and position of a hex tile, and other code calculates which part of my sprite sheet to use for the source rectangle. It’s good until I add rotation.

TBH I’m not super sure how “Origin” works, but after checking another question it seemed like setting the origin to be half the size of the dimensions I would render would work. It got the grid to line up, until I add rotation. Then once I add rotation, the tiles shift dramatically, where I want them to just rotate in place. I set “Rotation” below to some multiple of 60 then convert it to radians.

Anyone know what I’m doing wrong?

var Ratio = (float)tileHeight / tileWidth;
var adjDim = new Point(size,
    (int)(size * Ratio));

var cornerToEdgeOffset = adjDim.X * 3 /4;

var yFromXOffset = loc.X % 2 == 0
    ? 0
    : adjDim.Y / 2;

var crnr = new Point(
    cornerToEdgeOffset * loc.X,
    loc.Y * adjDim.Y + yFromXOffset);

var dstRec = new Rectangle(crnr.X, crnr.Y, adjDim.X, adjDim.Y);

var srcRec = new Rectangle(sourceFrame.X * tileWidth, sourceFrame.Y * tileHeight, tileWidth, tileHeight);

spriteBatch.Draw(_texture, dstRec, srcRec, 
    new Vector2(adjDim.X / 2, adjDim.Y / 2),
    SpriteEffects.None, 1);

Your code is a tad inscrutable to me, but hopefully this will help:

The origin is relative to the source rectangle, not the destination rectangle, so if the two rectangles have different sizes, then the size of the source rectangle should be used to determine the origin in order to rotate around the center point.

Also, you’ll need to offset the destination location by half the width and half the height of the destination rectangle if you want it to look right, because by changing the origin you essentially change the anchor point for drawing.

Here’s an example method for drawing a center-rotated texture, assuming the source rectangle exactly matches the texture:

public void DrawTexture(Texture2D texture, Rectangle destination, Color color, float rotation)
    Vector2 origin = new(texture.Width / 2f, texture.Height / 2f);
    destination.X = (int)(destination.X + destination.Width / 2f);
    destination.Y = (int)(destination.Y + destination.Height / 2f);
    batch.Draw(texture, destination, null, color, rotation, origin, SpriteEffects.None, 1f);

//inscrutible code
Haha, sorry, yeah, I guess there’s a lot of fields referenced and it’s still a prototype.

//The origin is relative to the source rectangle, not the destination rectangle
Perfect, that was what I was missing. Thank you!

1 Like

You’re welcome! Glad I was able to help. And sorry, I didn’t mean to sound insulting by saying that your code was inscrutable to me. I just personally had a hard time trying to understand exactly what it was doing, in part because of lack of context and in part because I’ve never worked with hexagonal tiles.

Oh, no worries, it was totally reasonable feedback. Thank you!

1 Like