XNA中的RPG风格运动

Spe*_*rJL 1 c# xna

我正在尝试在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)

(如果你使用固定的游戏时间,你实际上并不需要经过的时间相乘,但我通常把它放在那里,因为我更喜欢以每秒的单位来衡量.)

Tile Motion

这与"平滑"动作完全不同.现在您已经获得了基本速度,现在您只需要在移动一个完整的磁贴后停止.有很多方法可以解决这个问题,但我会在这里草拟一个简单的方法.

保持一个"距离"变量来表示角色到目前为止在他的运动中走了多远,与方向/轴无关:

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)

这将是一个良好的开端,但您仍需要做两件事:

  1. 当你完成移动(你刚刚去过的那个)时,抓住最近的瓷砖.如果不这样做,角色将从瓦片网格开始"慢慢"开始.为此,我建议您获取角色的中心坐标(坐标+平铺大小/ 2)并将其转换为平铺坐标,然后将其转换回"真实"坐标浮动.还有许多其他方法.

  2. 确保在运动时禁用按键.如果不这样做,角色可以通过中断运动中途自由地"关闭"平铺网格.你可以保留一个布尔值,inMotion或者更简洁的测试,如果velocity不是Vector2.Zero(那么你知道你在运动).

如果你想允许在中途中断运动并且仍然保持同步到网格,它会更加先进,但这应该给你一个良好的开端.