简体   繁体   English

使用requestAnimationFrame在画布上执行更新/绘制循环的正确方法

[英]Proper way to perform update/draw loops on a canvas with requestAnimationFrame

I'm making a little game using <canvas> with JS/Coffeescript. 我正在使用<canvas>和JS / Coffeescript进行小游戏。

As of now, my draw loop is done using requestAnimationFrame: 到目前为止,我的绘制循环已使用requestAnimationFrame完成:

draw: () =>
    # Various drawing code.
    requestAnimFrame(@draw, @canvas)

While my update loop is on a simple setInterval : 虽然我的更新循环位于简单的setInterval

setInterval(() => @update Date.now(), 1000/FPS)

I separated them so that the drawing doesn't get clogged up with unrelated update code, thinking this is probably the proper way. 我将它们分开,以使图形不会被无关的更新代码所阻塞,认为这可能是正确的方法。

But is it? 但是吗? Does it make sense? 是否有意义? How do I ensure smooth animations at minimal cost to systems? 如何以最小的系统成本确保流畅的动画效果?

Using both requestAnimationFrame (rAF) and setInterval will only create an extra overhead. 同时使用requestAnimationFrame (rAF)和setInterval只会产生额外的开销。

This is because JavaScript is single-threaded and has to execute scopes one by one. 这是因为JavaScript是单线程的,必须一一执行范围。 If JS engine is inside the scope for rAF then the execution of the scope for setInterval is queued up as an event that is executed after rAF has exited current scope - or vice verse. 如果JS引擎在rAF的作用域之内,则setInterval的作用域的执行会排队作为一个事件,该事件 rAF退出当前作用域执行-反之亦然。 And the code can still get clogged up/stacked (due to setInterval ). 而且代码仍然可以被阻塞/堆叠(由于setInterval )。

So no benefit there, quite the contrary as there is more code to execute (more is sometimes less, but not in this case) incl. 因此,这样做没有任何好处,恰恰相反,因为有更多的代码要执行(更多的代码有时更少,但在这种情况下则不是)。 internal stack pushing and popping, creation and queuing of event, extra code to parse etc. - perhaps at a microscopic level, but it your code is expensive then it may matter. 内部堆栈推入和弹出,事件的创建和排队,额外的代码以进行解析等-也许是微观的,但是您的代码很昂贵,因此可能会很重要。 That being said, consider using 30 fps instead of 60 fps, which is plenty in most cases and it about doubles your budget. 话虽如此,请考虑使用30 fps而不是60 fps,这在大多数情况下已经足够了,并且会使预算翻倍。

With rAF you have a "time budget" typically about 16.7 ms. 使用rAF,您的“时间预算”通常约为16.7毫秒。 No matter what you do you will have to get your code needed to create a single frame to execute within that time frame. 无论您做什么,都将需要获得创建单个框架以在该时间框架内执行所需的代码。 If not a frame (or more) will be skipped. 否则,将跳过一帧(或更多)。

The key is to optimize the code and how you put together your scene, literally as well as abstract. 关键是优化代码以及从字面上以及从抽象角度出发如何组合场景。 Cache everything you can (memory is your friend), update only what is needed and so forth. 缓存所有可能的内容(内存是您的朋友),仅更新所需的内容,依此类推。 There is no generic answer for this as it depends from case to case what is the optimal way of doing things. 没有通用的答案,因为这取决于具体情况,什么是最佳的处理方式。

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

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