繁体   English   中英

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

[英]What's the best way to move a sprite faster than the update rate in a simple 2d game?

目前,我有一个精灵,我任意设置为每秒移动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
    }
}

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

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

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

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

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

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

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;
}

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

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

尽管不是非常推荐,但是你要求的方法是将游戏的更新频率提高到比通常的30或60 fps更高的值,但每N帧只画一次屏幕。 您可以通过让图形引擎忽略Draw调用直到计数或计时器达到所需的值来实现。

当然,除非特别需要,否则应避免使用此解决方案,因为随着更新元素数量的增加,性能会迅速降低。

例如, Proun (不是XNA游戏)完全按照你的理由使用这个技巧

默认情况下, IsFixedTimeStep = trueXNA以类似的方式运行 ,如果Update花费太长时间,则跳过对Draw的调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM