我想创建一个带引力的简单动画(http://jsfiddle.net/2pcr9/4/在chrome和firefox中测试过)。我在使用画布的Javascript中这样做。使用(:46):
使用可变时间步长计算重力和速度this.realDelta = (now - this.prevTime) / 1000;
this.realTime += this.realDelta;
每个球都有这个代码来计算速度和位置(:148):
this.vy += this.gravity * time.delta;
this.x += this.vx * time.delta;
this.y += this.vy * time.delta;
现在,当您查看窗口时,此原型可以正常工作。
但是如果你隐藏当前窗口(切换到浏览器的另一个标签页),window.requestAnimationFrame就会停止。如果等待5秒钟,然后打开窗口,window.requestAnimationFrame将恢复。问题是realDelta现在是5秒,并且速度太大了。
我可以添加一个检查,不允许realDelta大于秒(:46):
this.realDelta = (now - this.prevTime) / 1000;
if (this.realDelta > 1) {
this.realDelta = 1;
}
this.realTime += this.realDelta;
但这并没有真正解决问题。
现在我不明白如何解决这个问题。我应该检查窗口是否隐藏并暂停计时器(并在窗口再次可见时恢复计时器)。或者我的速度计算有错误吗?其他html5游戏如何解决这个'dt'问题太大了?
由于
答案 0 :(得分:2)
在您的绘图功能中,您可以通过多次运行您的功能来补偿错过的帧以赶上:
var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
requestAnimFrame(draw, TIME_INTERVAL);
function draw() {
timeElapsed += now - this.prevTime;
this.prevTime = now;
while(timeElapsed > TIME_INTERVAL)
{
timeElapsed -= TIME_INTERVAL;
// Run Draw
}
requestAnimFrame(draw, TIME_INTERVAL);
}
当然,如果用户选项卡的时间太长,他们可能会重新进行大量计算。如果RequestAnimFrame不可用,您还可以考虑运行备份:
var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
var backup = setInterval(draw, TIME_INTERVAL*5);
requestAnimFrame(draw, TIME_INTERVAL);
function draw() {
clearInterval(backup);
timeElapsed += now - this.prevTime;
this.prevTime = now;
while(timeElapsed > TIME_INTERVAL)
{
timeElapsed -= TIME_INTERVAL;
// Run Draw
}
backup = setInterval(draw, TIME_INTERVAL*5);
requestAnimFrame(draw, TIME_INTERVAL);
}
答案 1 :(得分:1)
使用这些jQuery事件来开始/停止帧计算:
(你可以试试没有jQuery - 直接的javascript,但X-browser的东西会让你发疯!)
$(window).blur(function(e) {
// User has changed tabs away from your window
// So freeze your incrementing until the user returns
});
$(window).focus(function(e) {
// User has returned to your tab
// So begin your incrementing again
});
唯一的问题是在某些浏览器中这些事件被多次触发,因此您可能还想设置一个开/关标志,以便您只对第一次触发做出反应。