2D平台游戏:为什么要使物理依赖于帧速率?


12

“ Super Meat Boy”是一个困难的平台游戏,最近出现在PC机上,需要出色的控制和像素完美的跳跃。游戏中的物理代码取决于帧速率,该帧速率被锁定为60fps;这意味着,如果您的计算机无法全速运行游戏,则物理会变得疯狂,从而(除其他事项外)使您的角色运行速度变慢并掉落地面。此外,如果关闭了vsync,游戏将运行得非常快。

有2D游戏编程经验的人可以帮助解释为什么用这种方式编码游戏吗?以恒定速率运行的物理循环不是更好的解决方案吗?(实际上,我认为游戏的某些部分使用了物理循环,因为某些实体无论帧速率如何都可以继续正常移动。另一方面,您的角色运行[fps / 60]的速度也一样快。)

我对这种实现方式感到困扰的是游戏引擎和图形渲染之间的抽象性的丧失,它依赖于特定于系统的事物,例如监视器,图形卡和CPU。如果由于某种原因,您的计算机无法处理垂直同步,或者无法以60fps的速度正常运行游戏,那么它的性能将大打折扣。为什么渲染步骤会以任何方式影响物理计算?(如今,大多数游戏会减慢游戏速度或跳过帧。)另一方面,我了解到NES和SNES上的老式平台游戏在很大程度上取决于其固定的控制和物理帧率。为什么会这样,并且有可能在不依赖帧率的情况下在这种情况下创建patformer?如果将图形渲染与引擎的其余部分分开,是否必然会降低精度?

谢谢您,如果问题令人困惑,我们深表歉意。


与您的问题相切。这是一篇很棒的文章,涵盖了您正在描述的问题,以及处理时间步长和帧速率的“正确”方法。gafferongames.com/game-physics/fix-your-timestep
NUM1

实际上,令我惊讶的是他们会这样做。我想这一定是因为它主要是为控制台而构建的,在该控制台上可以依赖帧频。令人失望!
Iain

Answers:


7

为什么?

有几种原因,请选择:他们没有更好的选择。。它实现起来更快,更容易。他们更多地专注于游戏玩法,而较少关注大多数情况下可能无法出现的边缘情况。

您在解释为什么不做方面做得很好。我确定您已经注意到有很多主题涉及该主题。除了我列出的答案之外,我不确定您会找到满意的答案。


“他们没有更好的了解”描述了为什么我对“杰克是个傻瓜”采用了这种方法。但是-自从上一帧开始,我就一直依靠我的全部逻辑来调用dt。但是-浮点坐标,它可能会导致一些奇怪的,难以复制的错误
lochok

4

SMB最初是一个主机游戏,可以安全地假定它可以在所有Xbox360上以60fps的速度运行(嗯,对于某些PAL播放器来说可以是50fps)。假设固定的时间步简化了代码。

虽然很容易按可变的时间步长缩放很多事情-'pos + = velocity * timestep',但是在处理加速度和加速度的变化率等时正确地做到这一点非常棘手。

从理论上讲,将游戏玩法和渲染解耦是一个不错的解决方案,但是很好地实现(具有良好的插值)则非常棘手,事情很容易变得混乱。这种技术在实际游戏中使用并不常见(尽管某些大型游戏可以做到这一点,特别是RTS游戏,但更多用于网络游戏同步)。

当还为固定的屏幕分辨率和固定的帧率设计时,可以做另一件事来使滚动更加平滑。您可以确保游戏以每帧像素的整数滚动-避免通过每帧像素的分数滚动来获得“子像素摆动”。


1

显而易见的解决方案是让2个循环并行运行-每1/60秒渲染一次,而游戏循环每1/60秒进行渲染。

但是根据我在Flash(AS3,我敢肯定是在其中创建了Super Meat Boy)的经验,调度程序并不总是很准确。精度也高度取决于环境。在独立的Flash播放器中,它的分辨率可能会低于毫秒。但是,当在某些Web浏览器中运行时,它的准确性变成了帧速率的准确性。

因此,使渲染和游戏逻辑循环脱钩的最接近方法是使所有运动都基于时间(并根据自上一帧以来经过的时间运行每一帧)。这可能会引入一些更复杂的数学(例如连续施加重力,而不是以设定的间隔增加物体的速度)。由于游戏可能会滞后一秒钟,然后您的播放器将一步移动200个像素,因此碰撞检测和响应可能会变得更加复杂。如果程序员正在执行基于帧的冲突检测(每个时间步检查冲突),那么他们也将不得不切换到基于时间的冲突检测。如果他们想让它感觉自然,就必须使用上述的重力方法,这会使对象的运动变成曲线(而不是直线),


2
最初的Meat Boy是Flash游戏。Super Meat Boy是一个C ++游戏。
Archagon

0

我认为要求2D PC游戏以60fps播放不再重要。甚至现在大多数2D游戏都是硬件加速的,所以就我个人而言,我不会担心fps要求。

真正的问题是,为什么您不使用基于像素的游戏,游戏却充满了作弊和捷径。

如果您正在制作基于物理学的游戏(也许是投掷鸟的话),答案是显而易见的,但是超级马里奥克隆人呢?基于时间的运动可能会很多。


以60fps播放它们并不难,但是仍然很容易找到具有50Hz,70-85Hz和120Hz固有刷新率的显示器。

0

为了避免他们使用的2D物理学中的奇怪行为?

老实说,我只能猜测。我将尝试解释:

游戏的核心是主要的游戏循环。基本上看起来像这样:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGame更新gameState:检查玩家输入,将玩家输入应用于游戏世界并运行物理模拟等。

renderGame绘制游戏并为其设置动画。

这会将物理更新耦合到渲染。如果要使其解耦,则需要使用线程并将渲染和gameUpdate线程的每个数据访问正确同步到共享数据,例如玩家位置。可以做到的。

另一个问题可能是物理模拟需要恒定的时间步长才能稳定运行。这取决于supermeatboy如何计算运动(再次,我们只能猜测他们是如何完成的;)。

天真的方法是(我在游戏中使用*叹气*):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

这被称为欧拉积分,通常被认为是一个坏主意。如果时间步长不是恒定的,则会发生计算错误,这将使模拟不稳定。物体可能会以超快或不全速的速度移动,或者从屏幕外的墙壁飞过。即使时间步长恒定,欧拉积分也会导致较小的计算错误。最好使用另一种集成方法,例如RK4或使用物理引擎。

除此之外,如果时间步长太大,在进行碰撞检测时可能会遇到问题。由于未在两个gameUpdate之间检查碰撞,因此对象可能会穿过障碍物。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.