MonoGame/XNA 缩放和原点
MonoGame/XNA Scaling and Origin
我希望能够缩放我的精灵并将它们保持在缩放前的相同位置。我使用精灵的中心作为原点参数,因为我也希望能够旋转我的精灵。
我确定解决方案会很简单,但我找不到解决此问题的 proper/general 解决方案。
如果不是很清楚,我做了一些图片来展示我的代码、这段代码的结果以及我想要实现的目标。
1 - 这是我的代码和结果,这是我缩放精灵时得到的结果,如您所见,精灵已缩放但它 "moved":
这里评论中建议的是代码:
Vector2 scale = Vector2.One;
float rotation = 0;
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale += new Vector2(0.05f, 0.0f);
if (Input.IsKeyPressed(Keys.M))
scale -= new Vector2(0.05f, 0.0f);
if (Input.IsKeyPressed(Keys.O))
scale += new Vector2(0.0f, 0.05f);
if (Input.IsKeyPressed(Keys.L))
scale -= new Vector2(0.0f, 0.05f);
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(4));
spriteBatch.Draw(Sprites.BACKGROUND, Vector2.Zero, new Rectangle(0, 0, 128, 128), Color.White);
Vector2 marioPosition = new Vector2(64, 112 - 32);
Rectangle source = new Rectangle(0,0,16,32);
Vector2 origin = source.Size.ToVector2() / 2;
spriteBatch.Draw(Sprites.MARIO, marioPosition + origin, source, Color.White, rotation, origin, scale, SpriteEffects.None, 0f);
spriteBatch.End();
}
2 - 这是我想要实现的,我知道我可以通过移动我的原点来做到这一点,但我想将它保持在精灵的中心,这样我就可以围绕这一点应用旋转:http://pasteboard.co/rzMfc0p.png
嗯,你肯定是在保持你的性格。字面上地。您需要做的是实际 移动 您的角色,以便他的腿始终保持在地面上。
如果这是你的全部代码,那么这意味着你还没有物理知识。在这种情况下,您必须将角色的位置 up/down 移动其屏幕高度的一半(image.height * 比例),并且仅当他的垂直比例发生变化时才这样做。一旦你把物理学放在适当的位置,这将不会很好地工作,但现在,这是未经测试但建议的代码。
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale.X += .05f;
if (Input.IsKeyPressed(Keys.M))
scale.X -= .05f;
if (Input.IsKeyPressed(Keys.O))
{
scale.Y += .05f;
marioPosition.Y -= scale.Y * (Sprites.MARIO.Height / 2f);
}
if (Input.IsKeyPressed(Keys.L))
{
scale.Y -= .05f;
marioPosition.Y += scale.Y * (Sprites.MARIO.Height / 2f);
}
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
我将 scale += new Vector2(0.0f, 0.05f);
更改为 scale.Y += .05f;
的唯一原因是让您看到它可以更快地完成,并且可以使您的代码更具可读性。
此外,由于 XNA 中的倒置垂直 (Y) 轴,要使角色向上移动,您必须从他的位置 减去 ,反之亦然。
一些额外的提示:
所有精灵的class是个好主意,而且,所有输入(输入)的class也很棒
不是在 4 个地方写 .05f,而是创建一个变量,将在这些地方,并将其值设置为 .05f
有人帮助我并找到了解决我的问题的方法 (Pema99 @pemathedev),正如其他人所建议的那样,解决方案确实是移动 sprite,这里是移动 sprite 需要多少:
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale.X += .05f;
if (Input.IsKeyPressed(Keys.M))
scale.X -= .05f;
//Solution ---------------------------------------------------
if (Input.IsKeyPressed(Keys.O))
{
float previousSize = source.Height * scale.Y;
float newSize = source.Height * (scale.Y + .05f);
scale.Y += .05f;
marioPosition.Y -= (Math.Abs(previousSize - newSize)/2)
}
if (Input.IsKeyPressed(Keys.L))
{
float previousSize = source.Height * scale.Y;
float newSize = source.Height * (scale.Y - .05f);
scale.Y -= .05f;
marioPosition.Y += (Math.Abs(previousSize - newSize)/2)
}
//--------------------------------------------------------------
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
感谢大家!
我希望能够缩放我的精灵并将它们保持在缩放前的相同位置。我使用精灵的中心作为原点参数,因为我也希望能够旋转我的精灵。
我确定解决方案会很简单,但我找不到解决此问题的 proper/general 解决方案。
如果不是很清楚,我做了一些图片来展示我的代码、这段代码的结果以及我想要实现的目标。
1 - 这是我的代码和结果,这是我缩放精灵时得到的结果,如您所见,精灵已缩放但它 "moved":
这里评论中建议的是代码:
Vector2 scale = Vector2.One;
float rotation = 0;
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale += new Vector2(0.05f, 0.0f);
if (Input.IsKeyPressed(Keys.M))
scale -= new Vector2(0.05f, 0.0f);
if (Input.IsKeyPressed(Keys.O))
scale += new Vector2(0.0f, 0.05f);
if (Input.IsKeyPressed(Keys.L))
scale -= new Vector2(0.0f, 0.05f);
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(4));
spriteBatch.Draw(Sprites.BACKGROUND, Vector2.Zero, new Rectangle(0, 0, 128, 128), Color.White);
Vector2 marioPosition = new Vector2(64, 112 - 32);
Rectangle source = new Rectangle(0,0,16,32);
Vector2 origin = source.Size.ToVector2() / 2;
spriteBatch.Draw(Sprites.MARIO, marioPosition + origin, source, Color.White, rotation, origin, scale, SpriteEffects.None, 0f);
spriteBatch.End();
}
2 - 这是我想要实现的,我知道我可以通过移动我的原点来做到这一点,但我想将它保持在精灵的中心,这样我就可以围绕这一点应用旋转:http://pasteboard.co/rzMfc0p.png
嗯,你肯定是在保持你的性格。字面上地。您需要做的是实际 移动 您的角色,以便他的腿始终保持在地面上。
如果这是你的全部代码,那么这意味着你还没有物理知识。在这种情况下,您必须将角色的位置 up/down 移动其屏幕高度的一半(image.height * 比例),并且仅当他的垂直比例发生变化时才这样做。一旦你把物理学放在适当的位置,这将不会很好地工作,但现在,这是未经测试但建议的代码。
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale.X += .05f;
if (Input.IsKeyPressed(Keys.M))
scale.X -= .05f;
if (Input.IsKeyPressed(Keys.O))
{
scale.Y += .05f;
marioPosition.Y -= scale.Y * (Sprites.MARIO.Height / 2f);
}
if (Input.IsKeyPressed(Keys.L))
{
scale.Y -= .05f;
marioPosition.Y += scale.Y * (Sprites.MARIO.Height / 2f);
}
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
我将 scale += new Vector2(0.0f, 0.05f);
更改为 scale.Y += .05f;
的唯一原因是让您看到它可以更快地完成,并且可以使您的代码更具可读性。
此外,由于 XNA 中的倒置垂直 (Y) 轴,要使角色向上移动,您必须从他的位置 减去 ,反之亦然。
一些额外的提示:
所有精灵的class是个好主意,而且,所有输入(输入)的class也很棒
不是在 4 个地方写 .05f,而是创建一个变量,将在这些地方,并将其值设置为 .05f
有人帮助我并找到了解决我的问题的方法 (Pema99 @pemathedev),正如其他人所建议的那样,解决方案确实是移动 sprite,这里是移动 sprite 需要多少:
public void Update(GameTime gameTime)
{
if (Input.IsKeyPressed(Keys.P))
scale.X += .05f;
if (Input.IsKeyPressed(Keys.M))
scale.X -= .05f;
//Solution ---------------------------------------------------
if (Input.IsKeyPressed(Keys.O))
{
float previousSize = source.Height * scale.Y;
float newSize = source.Height * (scale.Y + .05f);
scale.Y += .05f;
marioPosition.Y -= (Math.Abs(previousSize - newSize)/2)
}
if (Input.IsKeyPressed(Keys.L))
{
float previousSize = source.Height * scale.Y;
float newSize = source.Height * (scale.Y - .05f);
scale.Y -= .05f;
marioPosition.Y += (Math.Abs(previousSize - newSize)/2)
}
//--------------------------------------------------------------
if (Input.IsKeyPressed(Keys.D))
rotation += MathHelper.ToRadians(5);
if (Input.IsKeyPressed(Keys.Q))
rotation -= MathHelper.ToRadians(5);
Input.Update(gameTime);
}
感谢大家!