为什么毫秒计数器在requestAnimationFrame()中继续运行?

问题描述 投票:1回答:2

[我使用强大的requestAnimationFrame(callback)功能,正在用JavaScript制作游戏。

[今天,我了解到自打开该页面以来,传递给requestAnimationFrame()的回调获得了高分辨率的时间。我们称它为ms

function paint(ms) {
    // draw my game
    requestAnimationFrame(paint);
}

requestAnimationFrame(paint);

很棒,但是有一件事我不太明白。

功能requestAnimationFrame()当我们转到另一个选项卡时不执行任何操作,因此渲染暂停。另一方面,离开时传递给回调的时间仍然继续。因此,我不确定如何使用该值。如果它与渲染引擎成比例地工作,我可以使用ms来计算游戏的逻辑时间,因为依靠requestAnimationFrame()作为稳定的60 FPS听起来并不是最好的主意。

我想念什么吗?如果ms参数在离开标签页时继续计数,目的是什么?

javascript requestanimationframe
2个回答
0
投票

这只是一个时间戳,它实际上不算什么。实际上,它实际上与performance.now()相同,后者给出自页面处于活动状态以来的时间。至于原因,这就是DOMHighResTimeStamp's origin的定义方式。

我们通常使用它来了解自某个先前事件发生以来已经过了多长时间,也就是说,我们存储一个start_time,然后检查当前时间戳,无论实际帧如何,我们都可以获取动画的增量时间-费率。

顺便说一句,不,依靠requestAnimationFrame以任何固定的帧速率确实不是一个好主意,requestAnimationFrame不受规格的任何帧速率限制,实际上建议将其对齐屏幕刷新率(尽管只有闪烁)。

因此,实际上,您需要依靠这样的时间戳才能在不同设置之间保持一致的速度。在每帧上执行简单的pos++可使动画在120Hz监视器上的运行速度比60Hz监视器(至少在Chrome中)快两倍。

这只会使您的想法更复杂,以至于无法理解如何实现:当窗口移至120Hz监视器时,您的绘画计时器会快两倍吗?

此时间戳也可能有助于追上较长的帧,这不是因为系统出现打ic,您不一定希望动画持续更长的时间。同样,并非所有情况都希望窗口模糊时动画逻辑停止。假设我有一个带有由rAF驱动的背景动画的标题,即使不在屏幕上,我也不希望它在屏幕外时显示pause

如果您希望游戏逻辑在窗口模糊时暂停,请听onvisibilitychange并保存当前时间戳(由于我们不在rAF之外,请使用onvisibilitychange


0
投票

添加到Kaiido的答案中。在应用程序中限制时间增量也很常见。例如,应用中帧速率独立计算的一种常见方法是计算帧之间的时间

performance.now()

但是,如果let previousTime = 0; function loop(currentTime) { const deltaTime = currenTime - previousTime; previousTime = currentTime; // use deltaTime in various calculations posX = posX + velX * deltaTime; requestAnimationFrame(loop); } requestAnimationFrame(loop); 太大,有时碰撞和其他数学运算可能会中断,因此游戏经常会添加限制器

deltaTime

这主要消除了检查 // don't let deltaTime be more than a 1/10 of a second const deltaTime = Math.min(currenTime - previousTime, 1000 / 10); 的需要。特别是如果您保留自己的动画/游戏时钟。

onvisiblitiychange

现在,如果播放器隐藏选项卡,不仅不会跳动,也不会跳动时钟,但是如果我们想暂停,我们可以将let previousTime = 0; let clock = 0; let clockRate = 1; function loop(currentTime) { const deltaTime = Math.min(currenTime - previousTime, 1000 / 10) * clockRate; previousTime = currentTime; clock += deltaTime; // update our own clock requestAnimationFrame(loop); } requestAnimationFrame(loop); 设置为0。

为什么要使用自己的时钟?它使您可以轻松降低或加快所有取决于该时钟的计算的时间(请参见上面的clockRate)。同样,许多应用(游戏)具有多个时钟。他们将为每个时钟计算不同的deltaTime。例如,即使应用程序/游戏已暂停,所有需要暂停的对象的时钟还是时钟都需要继续前进。另一个可能是玩家的时钟与敌人的时钟,因此当玩家使用其“慢时间超级力量”时,敌人的动作变慢,但玩家的动作保持相同的速度。

© www.soinside.com 2019 - 2024. All rights reserved.