共计 3358 个字符,预计需要花费 9 分钟才能阅读完成。
帧率独立游戏是以相同速度运行的游戏,无论帧率如何。例如,游戏在慢速计算机上可能以 30 FPS(每秒帧数)运行,而在快速计算机上以 60 FPS 的速度运行。与帧速率无关的游戏在两台计算机上以相同的速度进行(对象似乎以相同的速度移动)。另一方面,依赖于帧率的游戏在慢速计算机上以一半的速度进行,这是一种慢动作效果。
制作帧率独立游戏对于确保您的游戏对每个人来说都是愉快和可玩的非常重要,无论他们拥有哪种类型的计算机。当帧率下降时,游戏速度会变慢,这会严重影响游戏玩法,使玩家感到沮丧并退出!此外,某些系统的显示器具有不同的刷新率,例如 120 Hz,因此帧率独立性对于确保游戏在这些设备上不会加速并变得不可能快非常重要。
本教程介绍如何使游戏帧速率独立。同样的技术还可以实现时间缩放,从而允许故意的慢动作效果和轻松的暂停。
dt 系统表达式
帧率独立性的关键是系统表达式。代表增量时间。Delta 表示数量的变化,因此 delta-time 表示时间的变化。这是自上次滴答以来的时间(以秒为单位)。dtdt
例如,在 100 fps 时为 0.01(百分之一秒),在 10 fps 时为 0.1(十分之一秒)。在实践中,逐个刻度变化,因此它不太可能在很长一段时间内完全相同的值。dtdtdt
请注意,如果每个价格变动都添加到变量中,则它每秒增加 1,因为在 1 秒的时间内所有价格变动之间的时间必须相加为 1!下面是一个示例来说明这一点。dt
https://construct-static.com/articles/downloads/1172/sum-of-dt.c3p
如何使用 dt
通常,帧率相关的运动是通过如下事件完成的:
每刻度(每帧一次),对象向右移动一个像素。请注意,在 30 FPS 时,这意味着每秒 30 像素,而在 60 FPS 时,这意味着每秒 60 像素。这些是不同的速度,具体取决于帧速率。
请记住,从上面的示例中,每秒加起来总是为 1。因此,如果我们将事件更改为以下内容:dt
… 在任何帧速率下,对象都将以每秒 60 像素的速度向右移动。由于每秒加起来为 1,因此每秒加起来最多为 60。这意味着在 30 FPS 和 60 FPS 时,我们的对象每秒向右移动 60 个像素 – 无论帧速率如何,速度相同。dt60 * dt
到处使用 dt
每当您以稳定的速度移动对象时,您都需要以这种方式使用以实现帧速率独立性。例如,Sprite 的“向前移动”动作需要一定数量的像素来向前移动对象。如果不断向前移动对象,则可以将其向前移动像素,以在当前角度下以每秒 60 像素的速度移动。dt60 * dt
行为已使用 dt
Construct 的所有行为都用于其内部运动计算。这意味着任何由 Platform、8 Direction 和 Physics 等行为移动的东西都不需要任何特殊处理 – 它们已经这样做了!dt
时间刻度
Construct 中一个非常酷的功能是时间缩放。这使您可以更改游戏中时间流逝的速率,也称为时间刻度。您可以使用系统的“设置时间刻度”操作来设置时间刻度。时间刻度 1 表示正常速度,0.5 表示速度的一半,2.0 表示速度的两倍,以此类推。如果您将游戏的时间刻度设置为 0.1,它会慢 10 倍,但仍然很流畅 – 这是一个不错的慢动作效果!
Timescaling 的工作原理是更改 返回的值。这意味着行为会受到影响,并且任何使用 . 如果您在运动计算中不使用(如上面的第一个事件),则运动不受时间尺度的影响!因此,要使用时间缩放,您只需在所有动作中正确使用即可。dtdtdtdt
暂停
您可以将时间刻度设置为 0。这将停止所有运动。这是一种暂停游戏的简单方法。将其设置回 1,游戏将继续。
你可能会注意到,你仍然可以使用游戏控件来做一些事情,比如射击。您可以通过将主要游戏事件放在一个组中来解决这个问题,并在暂停和取消暂停时激活 / 停用该组。
这也是测试您是否正确使用的好方法。如果您正确使用它,将时间刻度设置为 0 将停止游戏中的一切。如果您没有正确使用它,即使游戏应该暂停,某些物体也可能继续移动!在这种情况下,您可以检查这些对象的移动方式,并确保正确使用。dtdt
其他种类的运动
重要的是要意识到这必须用于各种运动。这包括旋转和加速度。dt
旋转
与之前类似,以下事件每刻度将小猪旋转 1 度:
这是 30 FPS 时每秒 30 度,60 FPS 时每秒 60 度 – 同样,不同的帧速率有不同的速度。以同样的方式使用可以再次解决问题。这样,无论帧速率如何,小猪都会以每秒 60 度的速度旋转:dt
加速度
加速也相当简单。通常,这仅在您通过事件进行自定义移动时适用。
如果您有速度变量,则您的对象将以每刻度的像素数移动。因此,对象的速度变量包含以像素 / 秒为单位的速度。Object.Speed * dt
假设您希望在一秒钟内将对象加速 100 像素 / 秒。您只需在每次滴答时向对象的速度变量添加,它就会以独立于帧速率的方式加速。换言之,您可以使用两者来调整对象的位置,以及调整对象的速度。100 * dtdt
勒普
如果从两个固定位置开始,只需确保因子(in)像任何其他移动值一样增加。一个更复杂的情况是从 lerp 的最后一个结果中获取,例如 xlerp(a, b, x)dt
将 X 设置为 lerp(Self.X, TargetX, factor)
在这种情况下,正确的形式是使用:
lerp(a, b, 1 – f ^ dt)
… 其中介于 0 和 1 之间,例如 0.5。通常使用,但这并不完全准确,并且有一些其他缺陷。博客文章中更详细地解释了所涉及的数学 flerp(a, b, f * dt) 将 lerp 与增量时间一起使用.
常见错误
切勿在每 X 秒条件下使用!无论帧速率如何,像 Every 1 秒这样的事件将每 1 秒运行一次,因此已经与帧速率无关。该条件测量时间,而不是帧。如果你做了一个像每 60 * dt 秒这样的事件,你就无意中使条件帧率相关 – 这与你想要实现的目标相反!这种情况将以 10 FPS 每 6 秒运行一次(当 dt = 0.1 时),或以 100 FPS 每 0.6 秒运行一次(当 dt = 0.01 时); 如果仅使用“每 6 秒”,则无论帧速率如何,它都已每 6 秒运行一次。dt
高级注意事项
最小帧率
在非常低的帧速率下,可能会变得非常大。例如,在 5 FPS 时,为 0.2。因此,以每秒 500 像素的速度移动的物体就是每刻度移动 100 像素。这可能导致它“传送”穿过墙壁或错过与其他物体的碰撞。dtdt
游戏通常在如此低的帧速率下无法播放,但如果它们像这样变得不稳定,那就更糟了。为了帮助游戏即使在非常低的帧速率下也能保持可靠性,Construct 不允许大于 1/30(约 0.033)。换句话说,低于 30 FPS 时,保持在 0.033。这也意味着在 30 FPS 以下,游戏开始进入慢动作效果(之前描述为帧率依赖游戏的问题之一),但这通常比“传送物体”问题更好。dtdt
如果要将不同的限制设置为 1/30,可以使用系统操作“设置最小帧速率”。
随机变化
正如物理学所提到的,通常具有微小而随机的变化,通常是由于计算机中的不完美计时器。与物理一样,这也可能导致游戏中出现轻微的随机变化。然而,通常这种影响可以忽略不计,而且比物理学要不明显得多。建议您始终在游戏中使用,除非需要精确度(这种情况很少见)。dtdt
物体时间尺度
您可以通过系统的“设置对象时间刻度”操作为单个对象设置时间刻度。例如,这使您可以让游戏以慢动作运行,时间刻度为 0.3,但仍让玩家以 1 的时间刻度全速行动。这是通过将时间刻度设置为 0.3,然后使用设置对象时间刻度来设置播放器的时间刻度来实现的。系统表达式仅受游戏时间刻度的影响。对象有自己的 dt 表达式(例如),您必须使用该表达式而不是系统来处理与该对象相关的所有运动。这样,现在有两个 dt 值:一个用于游戏,另一个用于玩家。由于它们返回不同的值,因此游戏的不同部分可以以不同的速度进行。dtPlayer.dtdt
在此示例中,若要将玩家返回到游戏时间,请使用系统“还原对象时间刻度”操作。
结论
从一开始就使用 设计游戏非常重要。这改善了游戏玩法,确保在游戏的特别激烈的部分,节奏永远不会减慢。作为额外的奖励,您还可以使用时间缩放功能,轻松暂停游戏,甚至控制对象的各个时间缩放。dt
别忘了行为已经使用了 . 如果您使用行为来控制游戏中的所有运动,则根本不用担心!但是,大多数游戏都有一些事件控制的运动,记住如何使其与帧速率无关非常重要。dtdt