你需要比现在更多的地方。
首先,正如您已经意识到的那样,直接设置位置是即时的。解决方案?
速度
而不是直接设置Position
,设置一个velocity
:
Vector2 velocity = Vector2.Zero;
还要定义某种移动速度:
const float speed = 10.0f;
velocity
改为在您的按键中修改:
if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
velocity.X = new Vector2(speed, 0.0f);
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
velocity.X = new Vector2(-speed, 0.0f);
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Up) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
velocity.Y = new Vector2(0.0f, -speed);
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Down) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
velocity.Y = new Vector2(0.0f, speed);
}
现在,每一帧,只需更新Position
以使速度在其上积极工作:
//assuming you're using GameTime gameTime for the timing values
Position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
(如果你使用固定的游戏时间,你并不需要乘以经过的时间,但我通常把它放在那里,因为我更喜欢以每秒为单位进行测量。)
瓷砖运动
这是与“平滑”运动完全不同的问题。现在你已经有了基本的速度,你现在需要的就是在移动一个完整的瓷砖后停止。有很多方法可以解决这个问题,但我将在这里勾勒出一个简单的方法。
保留一个“距离”变量来表示角色在他的运动中走了多远,与方向/轴无关:
float distance = 0.0f;
随着您的Position
更改增加它,并在之后立即进行“旅行足够远”测试:
//assuming you're using GameTime gameTime for the timing values
Position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
//increment total distance indepedent of direction/axis
distance += Math.Abs(velocity.X) + Math.Abs(velocity.Y);
//test if we've travelled far enough
if (distance >= tileSize)
{
//reset distance
distance = 0.0f;
//stop
velocity = Vector2.Zero;
//TODO: SNAP TO TILE
}
这将是一个好的开始,但您仍然需要做两件事:
完成移动后捕捉到最近的图块(您刚刚前往的图块)。如果你不这样做,角色将开始缓慢地从瓷砖网格中“脱离”。为此,我建议获取角色的中心坐标(坐标 + 平铺大小 / 2)并将它们转换为平铺坐标,然后将其转换回“真实”坐标浮动。也有许多其他方法。
确保在运动时禁用按键。如果你不这样做,角色可以通过中断运动中途自由地“离开”平铺网格。你可以保留一个布尔值inMotion
,或者更简洁地说,测试是否velocity
不是Vector2.Zero
(然后你知道你在运动)。
如果您希望在中途中断运动并仍保持与网格同步,它会变得更先进一些,但这应该会给您一个良好的开端。