我正在创建一个HTML5画布游戏,使用requestAnimationFrame
渲染画布中的每一帧。为了基于秒而不是帧率移动动画,我正在构建一个类似于Unity中使用的deltaTime函数:
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;
}
然而,当我将这个值乘以动画速度时,它会导致一个不稳定的结果,而不是一个平滑的动画。看来毫秒级的精度是不够的。我如何改进这个函数以产生一个平滑的结果?
查看更新版本的requestAnimationFrame,它发送精确到亚毫秒级的运行时间
http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision但这可能不是你不高兴的原因。
使用带有delta-time的requestAnimationFrame(又名RAF)会导致被动画的对象出现在精确位置。如果你在天空中绘制太阳动画,那么RAF+deltaTime将确保无论何时绘制太阳,它都将绘制在天空中的正确位置。它将以太阳波动为代价来保证精度。
RAF+deltaTime为了定位精度牺牲了平滑的动画。
你没有给出一个代码示例,但解决方案是确保你的代码足够有效,可以在RAF时间范围内完全绘制。
或者,你可以让移动量更小,这样跳过的帧对用户来说就不会很明显了。
requestAnimationFrame
是高度优化的,因为它在系统最准备好更新显示时更新。这意味着,如果你想要避免janky动画,你需要让动画发生在requestAnimationFrame
循环中。我不确定您的代码是否正在这样做,但这里是如何使用requestAnimationFrame
将帧率设置为15 fps:
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;
}
}
但是显示的最大瓶颈通常是渲染:如果你可以使用WebGL,它比画布快得多。像PixiJs这样好的渲染框架可以帮助你优化这一点:
https://github.com/GoodBoyDigital/pixi.js/