奇怪的行为与XNA SpriteBatch.Draw起源

我有一个256×256像素的纹理。

考虑这段代码:

protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(texture, new Rectangle(0, 0, 100, 100), null, Color.White); spriteBatch.End(); base.Draw(gameTime); } 

如果我运行这个,贴图出现(可预测)在窗口的左上角与正确的大小(100×100)。

如果我这样做(仅XNA 4.0):

 spriteBatch.Draw(texture, new Rectangle(0, 0, 100, 100), null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0); 

一切仍然如预期。 但是,一旦我改变原点参数,位置变得怪异。

  protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(texture, new Rectangle(0, 0, 100, 100), null, Color.White, 0, new Vector2(128, 128), SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); } 

在最后一个例子中,只有纹理的1/4是可见的。

换句话说,原点参数不仅改变旋转的原点,还改变目标矩形。 换句话说,矩形的Top / Left坐标不是绘制的精灵的Top / Left坐标,而是Origin.X / Origin.Y纹理像素的坐标。

如果目标位置只是一个Vector2,我会理解(并完全支持)这个行为,但是对于一个目标矩形,这看起来很奇怪,特别是因为文档似乎没有提到这个事实(尽管说实话,文档根本没有说什么)。

一个StackOverflow答案甚至表明,旋转的目标矩形没有多大意义,但XNA提供它。

这种行为的原因是什么?

虽然你提出的关于Draw参数的问题是可以理解的,但我确实认为这是devise。 也,

矩形的Top / Left坐标不是绘制的精灵的Top / Left坐标,而是Origin.X / Origin.Y纹理像素的坐标。

这是一个不正确的说法。 您的出身已经成为左上角的可见像素,这是由屏幕空间,而不是错误devise的Spritebatchdevise。 实际的左上角像素是简单的在屏幕外。

为了清晰起见,我把所有的绘图放在一个截图中,并添加了一些旋转。 黑线是在destinationRectangle X和Y坐标处的网格线。

 spriteBatch.Draw(texture, new Rectangle(100, 50, 100, 100), null, Color.White); spriteBatch.Draw(texture, new Rectangle(100, 225, 100, 100), null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0); spriteBatch.Draw(texture, new Rectangle(100, 400, 100, 100), null, Color.White, 0, new Vector2(128, 128), SpriteEffects.None, 0); spriteBatch.Draw(texture, new Rectangle(400, 50, 100, 100), null, Color.White, MathHelper.PiOver4, Vector2.Zero, SpriteEffects.None, 0); spriteBatch.Draw(texture, new Rectangle(400, 225, 100, 100), null, Color.White, MathHelper.PiOver4, new Vector2(0, 0), SpriteEffects.None, 0); spriteBatch.Draw(texture, new Rectangle(400, 400, 100, 100), null, Color.White, MathHelper.PiOver4, new Vector2(128, 128), SpriteEffects.None, 0); 

正如你所看到的,你的纹理坐标没有改变。 目标矩形已经移动(在旋转之前)。

那有意义吗?

我想是这样。

为了回答你的问题,是的,原点同时影响旋转中心和抽签目的地。 但是这种改变是完全合乎逻辑的。 抢先总结:目标矩形对于旋转的四元组没有意义,并且SpriteBatch.Draw()的参数尽可能地有意义。

考虑绘制这个精灵的过程。 使用你的矩形的位置和大小, Spritebatch产生一个四舍五入,它会折腾成“批”。 这个四元素需要围绕某个点进行旋转( 没有包括旋转的绘制过载,但不包括原点 )为了使这个想法有意义,四元组的某些顶点需要从原点后面或上方旋转。 但是你没有指定一个位置,你只能指定一个目标矩形。 这意味着左上角顶点(基于矩形的X和Y)必须从旋转点移开,并且该移动是-1 * origin 。 这发生在内部,没有任何额外的工作由你。 是的,它改变了目标矩形的“想法”。 但是旋转后的高度和宽度都没有任何意义(它们都改变了)。

比较这个select。 对于要绘制的每个矩形,为了确定其位置,必须手动旋转相对于原点的最左上角,然后变换矩形的X和Y,然后将该新矩形传递给实际绘制调用。 您只需完成所有这些工作即可使destinationRectangle的位置与屏幕空间位置匹配。 与此同时,矩形的高度和宽度仍然是错误的,因为旋转也改变了它们。 而你的一些矩形比你的位置值更远,所以这一切都是无论如何。

希望这是有道理的。 我相信你的大部分问题都来自你认为已经消失的像素(但实际上只是在屏幕外)。 如果不是的话,我会很乐意再争论它。 🙂

PS我正在试图推出一些二维物理,我确定SpriteBatch会导致更多的问题,而不是完全由于这种内部devise决定的解决。 所以我select手动生成四个顶点,以避免我的左上角未经我的许可变换。 但是,我这样做的权衡是,我必须做很多工作,手工更多的工作。

你的问题是“这是什么原因?”,对吗?

我的猜测是,这种行为的原因是渲染在一个轴alignment的矩形内旋转的纹理。

一个例子; 假设你在游戏中有一个多人游戏大厅,你希望能够在那里进行简单的聊天。 你可以制作一个复活节蛋(适合季节,呃?!),通过在聊天中写入“/ loop-de-loop”来使你的头像旋转。 由于你的用户界面在头像周围有一些不错的框架,所以这看起来有些蹩脚,所以你使用这个绘制方法来确保头像在旋转时不会超出框架边界。

这可能不是最常用的Draw版本,但是我可以看到它的用途,如果它的工作方式我从你的post了解。

编辑; 值得注意的是,为了绘制一个自由旋转的纹理,你最好使用一个重载位置来指定位置为Vector2。

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.draw.aspx

EDIT2; ReRead你的问题,并注意到你也想知道为什么改变原点改变矩形内的纹理的位置? 当我到家时,我将不得不看看这是如何工作的,以便能够给出更好的答案。 我会想,改变原点并不是“移动”目标矩形内的纹理,所以我必须尝试一下,看看它是如何工作的,并决定如何/如果它是有用的:P