不正确的 SpriteBatch 旋转

Improper SpriteBatch Rotation

我试图让旋转的 Texture2D 正确地适应 within/fill 旋转的 Polygon 的边界(我自己的 class),但它拒绝好好工作。我使用的SpriteBatch方法是:

spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, Vector2.Zero, SpriteEffects.None, 1.0f);

但是,其中唯一重要的位是 Rectangle 和当前设置为 Vector2.Zero 的原点。当上述为 运行 时,它会生成 this 图像,其中 Texture2D(填充的红色方块)与 Polygon(石灰线框)的偏移值为(texture.Width / 2, texture.Height / 2)。但是,旋转是正确的,因为两种形状都有平行边。

我试过:

spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, new Vector2(Width / 2, Height / 2), SpriteEffects.None, 1.0f);

此调用的唯一区别是我将原点(Texture2D 旋转的点)更改为 new Vector2(Width / 2, Height / 2),这生成 this 图像,其中 Texture2DPolygon 偏移值 (-Width, -Height),但它仍随 Polygon.[=31 旋转=]

发生的另一个错误是,当使用与第一个具有不同宽度和高度的不同 Texture2D 时——尽管它应该产生相同的结果,因为 destinationRectangle 字段没有改变—— - 它在程序中有所不同,如this 图像所示。同样,这使用了与之前的完全相同的调用,只是使用了不同的图像(具有不同的尺寸)。

如果您能就这些问题中的任何一个提供帮助,我们将不胜感激。谢谢!

http://www.monogame.net/documentation/?page=M_Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw

为了正确旋转,您需要确保 origin 正确,

如果是标准化值,则为 0.5f, 0.5f,否则为 width / 2.0f, height / 2.0f

或任何其他适合您旋转的角。

我的两个问题的答案都在于一个错误:

SpriteBatch 在应用缩放平移之前应用围绕原点的旋转。

为了解释这一点,这里有一个例子:

您有一个 Texture2D 大小 (16, 16),并希望它在围绕原点 (destinationRectangle.Width / 2, destinationRectangle.Height / 2) 旋转时填充 (48, 48) 大小 destinationRectangle(其中等于 (24, 24))。因此,您希望最终得到一个围绕其中心点旋转的正方形。

首先,SpriteBatch 将围绕点 (24, 24) 旋转 Texture2D,因为 Texture2D 尚未缩放,因此大小为 (16, 16), 将导致不正确和意外的结果。在此之后,它将被缩放,使其只是旋转不佳的正方形的放大版本。

为了解决这个问题,使用(texture.Width / 2, texture.Height / 2)而不是(destinationRectangle.Width / 2, destinationRectangle.Height / 2)作为原点.

示例:spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, new Vector2(texture.Width / 2, texture.Height / 2), SpriteEffects.None, 0f);

可以找到进一步的解释 here and here

原点根据源矩形调整旋转中心。 (当像您的情况一样作为 null 传递时,源矩形是整个纹理。

请记住,在涉及平移、旋转和缩放时,顺序很重要。

旋转应用于源矩形的平移原点,允许旋转精灵的各个帧 sheet。

以下代码应产生预期的输出:

spriteBatch.Draw(texture, new Rectangle((int)Position.Center.X, (int)Position.Center.Y, Width, Height), null, color, Rotation, new Vector2(texture.Width / 2, texture.Height / 2), SpriteEffects.None, 1.0f);