Javascript基于时间的动画和requestAnimationFrame

时间:2014-03-27 21:13:35

标签: javascript animation

我一直在玩canvas和动画,专门针对HTML5游戏,并快速了解了仅使用requestAnimationFrame (rFA)的限制,并转而使用基于时间的动画。

无论显示器刷新率或FPS如何,我都希望保持不变的游戏性,但我不确定如何最好地处理动画。我已经阅读了各种各样的实现,但没有找到任何最佳实践可以这么说。我应该使用两者的组合吗?

到目前为止,我已经考虑了几个选项:

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

    var animate = function() {
         draw();
         requestAnimationFrame(animate);
    }
    
  • 仅基于时间(并非总是一致):

    var animate = function() {
        now = Date.now();
        delta = now - last;
        last = now;
    
        draw(delta);
        window.setTimeout(animate, 1000/60)
    }
    
  • 使用rFAsetInterval上设置FPS(并非总是一致):

    setInterval(function () {
        draw();
        requestAnimationFrame();
    }, 1000/fps);
    
  • rFA试图逼迫fps(看起来不是很强大,变量delta会更好):

    var delta = 1000 / fps;
    var animate = function() {
       now = Date.now();
       if (now - last >= delta) {
           last = now;
        }
    
        draw(delta);
        requestAnimationFrame(animate);
    }
    
  • 基于时间的rFA(一些奇怪的结果):

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

忽略浏览器支持的缺乏和Date.now()的使用,我只是想展示我的思维流程。我认为最后一个选项是可取的,但最后两个选项可能会遇到更新太多和丢失冲突等问题,以及更新花费太长时间以致动画失去所有控制权。

当用户使用rFA标签时,只有动画会暂停,使用基于时间的功能调用rFA意味着游戏/动画将继续在后台运行,这不是理想的

处理动画的最佳方法是什么,试图保持一致的结果,无论fps如何,以上所有可能都很糟糕,我为长篇文章道歉(这是我到目前为止所尝试的并且仍然很丢失)?考虑到上述问题会更好吗?

3 个答案:

答案 0 :(得分:1)

如果您有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();

答案 1 :(得分:0)

我建议您查看HTML 5 - Game Development course on Udacity。我不记得从课程中实现这个问题(但肯定有一个),但我从游戏玩法的角度来看,只是使用rAF(就像你的第一个子弹)是最有趣的,即使游戏速度慢因速度较慢的计算机需要处理太多而导致数据丢失。

答案 2 :(得分:0)

我认为你在最后一个方面处于正确的轨道上,因为它应该在不同帧率下运行的设备之间提供最大的一致性,但是如果它太高而无法避免大的话,你肯定想要降低delta值跳转:

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

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

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