Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/475.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript基于时间的动画和requestAnimationFrame_Javascript_Animation - Fatal编程技术网

Javascript基于时间的动画和requestAnimationFrame

Javascript基于时间的动画和requestAnimationFrame,javascript,animation,Javascript,Animation,我一直在玩canvas和动画,特别是HTML5游戏,很快就认识到只使用requestAnimationFrame(rFA)的局限性,并开始使用基于时间的动画 我想保持恒定的游戏性,无论显示器刷新率或FPS,但我不确定如何最好地处理动画。我已经阅读了各种实现,但没有找到任何最佳实践。我应该同时使用这两者吗 到目前为止,我已经考虑了几种选择: rFa仅限(fps更改时更改结果): 仅基于时间(并非始终一致): 使用setInterval在rFA上设置FPS(不总是一致): rFA试图强制fp

我一直在玩
canvas
和动画,特别是HTML5游戏,很快就认识到只使用
requestAnimationFrame(rFA)
的局限性,并开始使用基于时间的动画

我想保持恒定的游戏性,无论显示器刷新率或FPS,但我不确定如何最好地处理动画。我已经阅读了各种实现,但没有找到任何最佳实践。我应该同时使用这两者吗

到目前为止,我已经考虑了几种选择:

  • rFa
    仅限(fps更改时更改结果):

  • 仅基于时间(并非始终一致):

  • 使用
    setInterval
    rFA
    上设置FPS(不总是一致):

  • rFA
    试图强制fps(似乎不太可靠,可变增量效果更好):

  • 基于时间的
    rFA
    (一些奇怪的结果):

忽略缺少浏览器支持和Date.now()的使用,我只想展示一下我的思维流程。我认为最后一个选项更可取,但最后两个选项可能会遇到更新过远、缺少碰撞等问题,以及更新时间过长导致动画失去所有控制的问题

此外,当用户使用
rFA
进行制表时,仅动画将暂停,使用基于时间的函数调用
rFA
意味着游戏/动画将继续在不理想的背景下运行


处理动画的最佳方法是什么?不管fps如何,试图保持一致的结果,以上所有内容都可能不好,我为这篇长文章道歉(这正是我迄今为止尝试过的,但仍然很迷茫)?如果考虑到上述问题,效果会更好?

我建议您看看。我不记得这个问题在课程中的实现(但肯定有一个),但从游戏性的角度来看,我的观点是使用rAF(就像你的第一颗子弹)是最有趣的,即使由于较慢的计算机上需要太多的处理而导致游戏速度减慢。

我认为您使用上一个游戏的方法是正确的,因为它应该在以不同帧速率运行的设备之间提供最大的一致性,但如果增量太高,您肯定希望强制降低增量值以避免大的跳跃:

var animate = function () {
    now = Date.now();
    delta = now - last;
    last = now;

    if(delta > 20) {
        delta = 20;
    }

    draw(delta);
    requestAnimationFrame(animate);
};

如果您有可用的
requestAnimationFrame
,我不会反对它,只会从它的回调调用
draw()
。当然,您应该始终使用增量计时

这里有一个复杂的
raF
变体,在帧速率过低的情况下,可以回退到
setTimeout
进行游戏逻辑更新:

var maximalUpdateDelay = 25; // ms
var updateTimeout, now;
function animate() {
    updateTimeout = setTimeout(animate, maximalUpdateDelay);
    var delta = -now + (now = Date.now());
    update(now, delta);
}
function main() {
    clearTimeout(updateTimeout);
    animate(); // update the scene
    draw(); // render the scene
    requestAnimationFrame(main);
}
main();

谢谢,我会检查课程的。该解决方案的问题在于,在120Hz的监视器上,游戏的运行速度将是较慢机器的两倍,可能低于预期的60 fps,这意味着游戏的技能水平将发生变化(较慢=更容易反应等)理想情况下,它应该尽可能一致。
draw
animate
之间有什么区别?他们是干什么的?我想我可以给他们起个更聪明的名字<代码>动画只是下一帧渲染时循环使用的主要功能<代码>绘制将花费时间增量,计算任何对象的新位置/状态,并在每个对象的适当上下文上调用函数<代码>绘制本质上是更新和渲染。啊,我明白了,实际上是有意义的。我只是被“在rFA上用setInterval设置FPS”代码弄糊涂了,这是不正确的。事实上,基于时间的rFA应该可以工作,你得到了什么“奇怪的结果”呢?也许不是抱歉,只是想展示一下这个概念。当fps较低,delta较高时,碰撞检测可能会明显失败,可能正因为如此,物体失去控制(例如错误的轨迹)。更改选项卡也一样,不会真正暂停,只是将delta设置得非常高。正如imcg建议的那样,设置最大增量在这里会有所帮助。另一种解决方案可能是为对象更新单独设置一个循环,独立于动画循环,这样即使帧渲染速度较慢,对象也会定期重新定位?是的,这可能是个好主意。在高fps设备上,在绘制之前进行更新就足够了,如果增量太高,您可能会在绘制之间插入额外的计算,并使用
setTimeout
。限制增量值会导致奇怪的同步问题,不是吗?好的,所有内容都应该使用相同的增量时间进行同步。这样做的目的是防止gc等在帧速率上的小幅度下降导致事情在一个步骤中移动过多。为什么会“太多”?而不是保持一个恒定的速度,整个游戏的速度将下降为单一的帧-这感觉比短帧速率下降更笨重。当然,如果帧速率在较长时间内处于较低水平,为了让游戏运行更平稳,你可能需要降低游戏的整体速度。当一次发生太多事情时,往往只是奇怪的帧延迟,然后事情很快恢复正常。使用这种方法,你会有一个小的减速,而没有夹钳,你可以很容易地看到一个精灵突然从屏幕上跳过去(甚至跳下),这充其量是非常刺耳的,最坏的情况下会破坏游戏。
setInterval(function () {
    draw();
    requestAnimationFrame();
}, 1000/fps);
var delta = 1000 / fps;
var animate = function() {
   now = Date.now();
   if (now - last >= delta) {
       last = now;
    }

    draw(delta);
    requestAnimationFrame(animate);
}
var animate = function () {
    now = Date.now();
    delta = now - last;
    last = now;

    draw(delta);
    requestAnimationFrame(animate);
}
var animate = function () {
    now = Date.now();
    delta = now - last;
    last = now;

    if(delta > 20) {
        delta = 20;
    }

    draw(delta);
    requestAnimationFrame(animate);
};
var maximalUpdateDelay = 25; // ms
var updateTimeout, now;
function animate() {
    updateTimeout = setTimeout(animate, maximalUpdateDelay);
    var delta = -now + (now = Date.now());
    update(now, delta);
}
function main() {
    clearTimeout(updateTimeout);
    animate(); // update the scene
    draw(); // render the scene
    requestAnimationFrame(main);
}
main();