在简单的2D游戏中,移动精灵的最佳方式是什么?

Nib*_*Pig 2 c# xna

目前,我有一个精灵,我任意设置为每秒移动1个像素.代码基本上是这样的(代码根本没有优化,我可以做得更好,但这是我试图首先解决的原则:):

private const long MOVEMENT_SPEED = 10000000; // Ticks in 1 second
private long movementTimeSpan = MOVEMENT_SPEED;


protected void PerformMovement(GameTime gameTime)
{
    movementTimeSpan -= gameTime.ElapsedGameTime.Ticks;

    if (movementTimeSpan <= 0)
    {
       // Do the movement of 1 pixel in here, and set movementTimeSpan back to MOVEMENT_SPEED
    }
}
Run Code Online (Sandbox Code Playgroud)

按照您的预期在循环中调用执行移动,它等同于每秒更新大约10次.因此,如果我降低MOVEMENT_SPEED,我的精灵会加速,但它永远不会超过每秒10个像素.对于射弹和其他东西,我显然希望它比这更快地更新.

如果我将运动改变为2像素或更多,则会产生计算碰撞等问题,但这些可能有可能克服.

另一种方法是将x和y存储为float而不是int,并将值增加为经过的tick数的一部分.我不确定这是否会创造顺畅的运动,因为仍然需要进行一些舍入.

所以我的问题是,有没有人知道标准方式?

我应该将数量增加到多于1个像素并将我的碰撞检测更新为递归,我应该将X,Y存储为浮点数并以经过时间的百分比移动,还是有第三种更好的方法?

小智 8

标准的方法是不倒计时移动,而是相反:

private const float MOVEMENT_SPEED = 10.0f; //pixels per second
private float time;

protected void PerformMovement(GameTime gameTime)
{
    time = (float)gameTime.ElapsedGameTime.TotalSeconds;

    character.X += MOVEMENT_SPEED * time;
}
Run Code Online (Sandbox Code Playgroud)

根据经过的时间进行移动.通常使用浮动的原因是获得运动的小数值.定点是另一种常见的分数表示,但使用ints代替.

至于碰撞,碰撞可能非常棘手,但一般来说,每个运动像素并不是绝对需要做一次(正如你提出的递归); 这太过分了,很快就会导致糟糕的表现.如果您目前在使用2像素运动时遇到问题,我会重新评估您是如何进行碰撞的.一般来说,当你快速移动到超薄墙壁上跳跃,甚至越过墙壁的"错误侧"时,根据你的碰撞设置方式,它会成为问题.这被称为"隧道".有很多方法可以解决这个问题.看这里,向下滚动到"防止隧道".正如文章所述,许多人只是将速度限制在一个安全的价值.但另一种常见的方法是以比当前传入的更短的时间步长"逐步"遍历算法.例如,如果当前经过的时间为0.1,则可以在循环内逐步减去0.01并检查每个小步骤.