得到一个平滑的动画的画布游戏 [英] get a smooth animation for a canvas game

查看:154
本文介绍了得到一个平滑的动画的画布游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获得更好的动画,即使在浏览器忙碌或空闲时,对于具有不同硬件容量的不同设备,也可以获得更好的动画。

How to get a better animation, dinamically, even when browser is busy or idle, for different devices which have different hardware capacity.

仍然无法找到正确的方法让游戏显示更好的动画。

I have tried many ways and still cannot find the right way to make the game to display a better animation.

这是我试过的:

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 is the interval value to update the game, but when browser is busy this interval is not good, and it needs to lower. How to get a better animation dinamically, even when browser is idle or busy ?

我认为间隔值是问题,因为如果间隔较低,那么游戏动画非常快,如果这个值是18,那么游戏动画是好的,但是当浏览器忙时,我不知道如何改变它dinamically。

I suppose that the interval value is the problem, because if interval is lower then game animation is very fast, if this value is 18 then game animation is good but not when browser is busy, and I do not have idea how to change it dinamically.

推荐答案

要获得流畅的动画,您必须:

•在屏幕上同步。

•计算游戏中消耗的时间。

•Animate只使用此游戏时间。

To get a smooth animation, you must :
• Synchronise on the screen.
• Compute the time elapsed within your game.
• Animate only using this game time.

使用requestAnimationFrame(rAF)与屏幕同步。

当您写: / p>

Synchronizing with the screen is done by using requestAnimationFrame (rAF).
When you write :

requestAnimationFrame( myCalbBack ) ;  

您正在注册 myCalbBack em>一次,下一次屏幕可以绘制。

(如果你知道双缓冲(画布总是双缓冲),这一次是下一次GPU将用显示缓冲区交换绘图缓冲区。)

You are registering myCalbBack to be called once, the next time the screen is available to draw on.
( If you know about double buffering (canvas are always double-buffered), this time is the next time the GPU will swap the draw buffer with the display buffer. )

如果,另一方面,如果你不使用rAF而是使用间隔/超时来安排绘图,将发生的是,绘制将不会实际显示直到下一次显示刷新。这可能发生(在60Hz显示器上)从现在到16.6ms之后的任何时间。

If, on the other hand, you don't use rAF but a interval/timeout to schedule the draws, what will happen is that the draws won't get actually displayed until next display refresh. Which might happen (on a 60Hz display) any time from right now to 16.6 ms later.

下面是20ms间隔和16ms屏幕,您可以看到实际显示的图像将交替16ms远或2 * 16ms远 - 从不20 - 。你只是不能知道,从间隔回调,当实际绘制将显示。由于rAF和间隔都不是100%准确,你甚至可以有一个3帧增量。

Below with a 20ms interval and a 16 ms screen, you can see that the images actually displayed will be alternatively 16ms away OR 2*16ms away - never 20, for sure-. You just can't know, from the interval callback, when the actual draw will show. Since both rAF and Intervals are not 100% accurate, you can even have a 3 frames delta.

>

现在你正在与屏幕同步,这里有一个坏消息:requestAnimationFrame不会定期计时。由于各种原因,两个帧之间的经过时间可能改变1ms或2,或甚至更多。因此,如果你使用每个框架的固定运动,你将在不同的时间移动相同的距离:速度总是改变。

So now that you are on sync with the screen, here's a bad news : the requestAnimationFrame does not tick exactly regularly. For various reasons the elapsed time in between two frames might change of 1ms or 2, or even more. So if you are using a fixed movement each frame, you'll move by the same distance during a different time : the speed is always changing.

(解说:每个rAF为+10像素,

16.6显示 - >> rAF时间为14,15,16或17 ms < br>
- >视速度从0.58到0.71像素/ ms不等。)

(expl : +10 px on each rAF,
16.6 display -->> rAF time of 14, 15, 16 or 17 ms
--> the apparent speed varies from 0.58 to 0.71 px/ms. )

答案是测量时间...并使用它! br>
希望requestAnimationFrame为您提供当前时间,以便您甚至不必使用Date.now()。次要好处是,此时间对于具有精确计时器的浏览器(Chrome桌面)将非常准确。

下面的代码显示了如何知道自上一帧以来经过的时间,并计算应用时间: / p>

Answer is to measure time... And use it !
Hopefully requestAnimationFrame provides you the current time so you don't even have to use Date.now(). Secondary benefit is that this time will be very accurate on Browsers having an accurate timer (Chrome desktop).
The code below shows how you could know the time elapsed since last frame, and compute an application time :

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);

现在最后一步是在所有公式中使用时间。

Now last step is to always use time inside all you formulas. So instead of doing

x += xSpeed ;

您必须:

x += dt * xSpeed ;

现在,不仅帧之间的小变化会被考虑,在任何设备的屏幕(20Hz,50Hz,60 Hz,...)以相同的表观速度。

And now not only the small variations in between frames will be taken into account, but your game will run at the same apparent speed whatever the device's screen (20Hz, 50Hz, 60 Hz, ...).

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

I did a small demo where you can choose both the sync and if using fixed time, you'll be able to judge of the differences :

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

这篇关于得到一个平滑的动画的画布游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆