javascript - 为 Canvas 游戏获得流畅的动画

标签 javascript html canvas requestanimationframe

如何动态地为具有不同硬件容量的不同设备获得更好的动画,即使在浏览器繁忙或空闲时也是如此。

我尝试了很多方法,仍然找不到合适的方法让游戏显示更好的动画。

这是我尝试过的:

var now;
var then = Date.now();
var delta;

window.gamedraw = function(){

   now = Date.now();
   delta = now - then;

   if(delta > 18){
        then = now - (delta % 18);
        game_update();
   }

}

window.gameloop = setInterval(window.gamedraw,1);

18是更新游戏的间隔值,但是当浏览器繁忙时这个间隔不好,需要降低。如何动态地获得更好的动画,即使在浏览器空闲或忙碌时也是如此?

我认为间隔值是问题所在,因为如果间隔较低则游戏动画非常快,如果该值是 18 则游戏动画很好但当浏览器繁忙时则不是,我不知道如何动态地改变它。

最佳答案

要获得流畅的动画,您必须:
• 在屏幕上同步。
• 计算游戏中耗时。
• 只使用这段游戏时间制作动画。

通过使用 requestAnimationFrame (rAF) 与屏幕同步。
当你写的时候:

requestAnimationFrame( myCalbBack ) ;  

您正在注册 myCalbBack 被调用一次,下次屏幕可供绘制时。
(如果你知道双缓冲( Canvas 总是双缓冲的),这次是 GPU 下一次将绘图缓冲区与显示缓冲区交换。)

另一方面,如果您不使用 rAF 而是使用间隔/超时来安排抽奖,将会发生的情况是抽奖不会真正显示直到下一次显示刷新 .从现在到 16.6 毫秒后的任何时间都可能发生(在 60Hz 显示器上)。

下面是 20 毫秒的间隔和 16 毫秒的屏幕,您可以看到实际显示的图像将在 16 毫秒或 2 * 16 毫秒之外交替出现 - 当然不会是 20 毫秒。您只是无法从间隔回调中知道实际抽奖何时显示。由于 rAF 和间隔都不是 100% 准确,您甚至可以有 3 帧增量。

enter image description here

现在您已经与屏幕同步了,这里有一个坏消息:requestAnimationFrame 并没有完全规律地跳动。由于各种原因,两帧之间耗时可能会变化 1 毫秒或 2 毫秒,甚至更多。因此,如果您每帧使用固定移动,您将在不同的时间移动相同的距离:速度总是在变化。

(说明:每个 rAF +10 像素,
16.6 显示 -->> rAF 时间为 14、15、16 或 17 毫秒
--> 表观速度从 0.58 到 0.71 px/ms 不等。 )

答案是测量时间...并使用它!
希望 requestAnimationFrame 为您提供当前时间,这样您甚至不必使用 Date.now()。第二个好处是,在具有准确计时器(Chrome 桌面)的浏览器上,这个时间将非常准确。
下面的代码显示了如何知道自上一帧以来耗时,并计算应用程序时间:

function animate(time) {
  // register to be called again on next frame.
  requestAnimationFrame(animate);
  // compute time elapsed since last frame.
  var dt = time-lastTime;
  if (dt<10) return;
  if (dt >100) dt=16;  // consider only 1 frame elapsed if unfocused.
  lastTime=time;
  applicationTime+=dt;
  //
  update(dt);  
  draw();
}

var lastTime = 0;
var applicationTime = 0;
requestAnimationFrame(animate);

现在最后一步是始终在所有公式中使用时间。所以不要做

x += xSpeed ;

你必须做:

x += dt * xSpeed ;

现在不仅会考虑帧之间的微小变化,而且无论设备屏幕如何(20Hz、50Hz、60Hz 等),您的游戏都将以相同的表观速度运行。

我做了一个小演示,您可以在其中选择同步,如果使用固定时间,您将能够判断差异:

http://jsbin.com/wesaremune/1/

关于javascript - 为 Canvas 游戏获得流畅的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28256197/

相关文章:

javascript - 从父页面调用 iframe 中的 JavaScript 代码

html - 使用本地 HTML 导入 XML

javascript - Canvas 绘制图像失败

javascript - jQuery 滚动到() "unrecognized expression"

php - 如何在单个div中显示两行div

elasticsearch - Canvas中的Elasticsearch SQL查询:它不能像SQL一样工作?

javascript - 在 HTML Canvas 上禁用右键单击上下文菜单?

javascript - 同步连接到 Node js中的套接字

javascript - 通过 JavaScript 进行 Android 模拟器日志记录

javascript - 带 SPA 的 Google Analytics(Angular.js)