我正在尝试在XNA中制作一个RPG游戏,我对这个机芯有问题.我想创建类似于RPG制造商的动作,在那里你可以顺利地从一个瓷砖走到另一个瓷砖,当你停止走路时,它会卡在瓷砖的中间.我该怎么做呢?我有这个,但它立刻从一个方块移动到另一个方块,之间没有任何东西.
if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
Position.X += 30;
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
Position.X -= 30;
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Up) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
Position.Y -= 30;
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Down) == true && mPreviousKeyboardState != aCurrentKeyboardState)
{
Position.Y += 30;
}
Run Code Online (Sandbox Code Playgroud)
小智 10
你需要比现在更多的地方.
首先,正如您已经意识到的那样,直接设置位置是即时的.解决方案?
而不是直接设置Position
,设置velocity
:
Vector2 velocity = Vector2.Zero;
Run Code Online (Sandbox Code Playgroud)
还定义了某种移动速度:
const float speed = 10.0f;
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
现在,每一帧,只需更新,Position
以使速度在其上积极工作:
//assuming you're using GameTime gameTime for the timing values
Position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
Run Code Online (Sandbox Code Playgroud)
(如果你使用固定的游戏时间,你实际上并不需要经过的时间相乘,但我通常把它放在那里,因为我更喜欢以每秒的单位来衡量.)
这与"平滑"动作完全不同.现在您已经获得了基本速度,现在您只需要在移动一个完整的磁贴后停止.有很多方法可以解决这个问题,但我会在这里草拟一个简单的方法.
保持一个"距离"变量来表示角色到目前为止在他的运动中走了多远,与方向/轴无关:
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
}
Run Code Online (Sandbox Code Playgroud)
这将是一个良好的开端,但您仍需要做两件事:
当你完成移动(你刚刚去过的那个)时,抓住最近的瓷砖.如果不这样做,角色将从瓦片网格开始"慢慢"开始.为此,我建议您获取角色的中心坐标(坐标+平铺大小/ 2)并将其转换为平铺坐标,然后将其转换回"真实"坐标浮动.还有许多其他方法.
确保在运动时禁用按键.如果不这样做,角色可以通过中断运动中途自由地"关闭"平铺网格.你可以保留一个布尔值,inMotion
或者更简洁的测试,如果velocity
不是Vector2.Zero
(那么你知道你在运动).
如果你想允许在中途中断运动并且仍然保持同步到网格,它会更加先进,但这应该给你一个良好的开端.