I'm building an HTML5 canvas game that's using requestAnimationFrame to render each frame in the canvas. To move animations at a rate based on seconds, not framerate, I am building a deltaTime function similar to that used in Unity:

var startTime = new Date().getTime();
var lastTime = null;

function deltaTime()
{
    if (lastTime == null)
    {
        lastTime = new Date().getTime();
    }
    var dt = new Date().getTime() - lastTime;
    lastTime = new Date().getTime();
    return dt;
}

However, when I multiply this value by the animation speed, it causes a choppy result instead of a smooth animation. It appears that millisecond accuracy is not enough. How can I improve this function to produce a smooth result?

有帮助吗?

解决方案

Check out the newer version of requestAnimationFrame that sends in an elapsed time that is accurate to the sub-millisecond

http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision

But that may not be the cause of your choppiness.

Using requestAnimationFrame (aka RAF) with a delta-time causes the object being animated to appear in an accurate location.

If you're animating the sun across the sky, then RAF+deltaTime will insure that whenever the sun is drawn, it will be drawn at the correct spot in the sky. It will insure accuracy at the cost of choppy sun movement.

RAF+deltaTime sacrifices smooth animation for positioning accuracy.

You don't give a code example, but the solution is to make sure your code is efficient enough to fully draw within the RAF timespan.

Alternatively, you can make the amount of movement smaller so a skipped frame will not be very noticeable to the user.

其他提示

requestAnimationFrame is highly optimized because it updates the display when the system is most ready to do so. That means if you want to avoid janky animations, you need to make the animation happen inside an requestAnimationFrame loop. I'm not sure if your code is doing that, but here's how you can set the frame rate to 15 fps using requestAnimationFrame:

var fps = 15,
    startTime = 0,
    frameDuration = 1000 / fps;

//Start the game loop
update();
function update() {
  requestAnimationFrame(update, canvas);
  //Check whether the current time matches the start time
  if (Date.now() >= startTime || startTime === 0){

      //... run the game code ...

      //Set the new start time for the next frame, 
      //which will be 66 milliseconds ahead of the current time
      startTime = Date.now() + frameDuration;
  }
}

But the biggest bottleneck to the display is usually the rendering: If you can use WebGL it's so much faster than canvas. A good rendering framework like PixiJs can help you optimize this:

https://github.com/GoodBoyDigital/pixi.js/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top