简体   繁体   English

Javascript基于时间的动画和requestAnimationFrame

[英]Javascript time-based animation and requestAnimationFrame

I have been playing around with canvas and animation, with HTML5 games in mind specifically and quickly learnt the limitations of just using requestAnimationFrame (rFA) and have moved to time-based animations. 我一直在研究canvas和动画,尤其是在考虑HTML5游戏的同时,很快就了解了仅使用requestAnimationFrame (rFA)的局限性,并转向了基于时间的动画。

I want to maintain constant gameplay regardless of monitor refresh rate or FPS but am unsure how best to handle the animations. 无论显示器刷新率或FPS如何,我都希望保持恒定的游戏玩法,但是不确定如何最好地处理动画。 I have read through all sorts of implementations but have not found any best practice so to speak. 我已经通读了各种实现,但可以这么说,还没有找到任何最佳实践。 Should I be using a combination of the two? 我应该同时使用两者吗?

So far I have considered several options: 到目前为止,我已经考虑了几种选择:

  • rFa only (changes results when fps changes): rFa (当fps更改时更改结果):

     var animate = function() { draw(); requestAnimationFrame(animate); } 
  • time-based only (not always consistent): 仅基于时间(并非始终一致):

     var animate = function() { now = Date.now(); delta = now - last; last = now; draw(delta); window.setTimeout(animate, 1000/60) } 
  • set FPS on rFA with setInterval (not always consistent): 使用setIntervalrFA上设置FPS(并非始终一致):

     setInterval(function () { draw(); requestAnimationFrame(); }, 1000/fps); 
  • rFA trying to force fps (does not seem very robust, variable delta would work better): 尝试强制fps的rFA (似乎不很健壮,可变增量会更好):

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

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

Ignore the lack of browser support and the use of Date.now(), I just want to demonstrate my flow of thinking. 忽略缺少浏览器支持和使用Date.now()的方法,我只想证明自己的想法。 I think that the last option is preferable, but the last two can run into problems with updating too far and missing collisions etc as well as updates taking too long that the animation looses all control. 我认为最后一个选项更可取,但是后两个选项可能会出现更新太远,缺少碰撞等问题,以及更新时间过长而动画失去所有控制权的问题。

Also when a user tabs out using rFA only the animation will pause, using a time based function to call rFA means that the game/animation will continue to run in the background which is not ideal. 同样,当用户使用rFA跳出时,动画将暂停,使用基于时间的函数调用rFA意味着游戏/动画将继续在后台运行,这并不理想。

What would be the best way to handle animations trying to keep consistent results regardless of fps, all of the above might be bad and my apologies for the long post (it is just what I have tried so far and am still pretty lost)? 什么是处理动画的最佳方法,而无论fps如何,动画都试图保持一致的结果,以上所有这些都可能不好,我很长的歉意(这是我到目前为止已经尝试过并且仍然很迷失的东西)? even better with with the above issues in mind? 考虑到上述问题甚至更好?

If you have requestAnimationFrame available, I wouldn't go against it and only call draw() from its callbacks. 如果您有requestAnimationFrame可用,我不会反对它,而只会从其回调中调用draw() Of course, you should always use delta timing. 当然,您应该始终使用增量计时。

Here's a sophisticated variation of raF with a fallback to setTimeout for the game logic updates in case the frame rate is too low: 这是raF的一种复杂变体,在帧速率太低的情况下,它会回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();

I'ld recommend taking a look at the HTML 5 - Game Development course on Udacity . 我建议您阅读有关UdacityHTML 5游戏开发课程 I don't remember the implementation of this problem from the course (but there definitely was one), but my opinion from a gameplay perspective is that just using rAF (like your first bullet) is the most fun, even if there is game slow down due to too much processing needed on slower computers. 我从课程中不记得这个问题的实现(但是肯定有一个),但是从游戏性的角度来看,我认为即使在游戏速度较慢的情况下,仅使用rAF(例如第一个子弹)也是最有趣的下降的原因是速度较慢的计算机需要太多处理。

I think you're on the right track with the last one because it should give you the most consistency across devices running at different frame rates, but you definitely want to force your delta value down if it gets too high to avoid big jumps: 我认为您在最后一个方向上是正确的,因为它应该为以不同帧速率运行的设备提供最大的一致性,但是您绝对希望将其delta值调得太低,以免发生大跳动:

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM