2013-04-08 75 views
1

我想创建一个简单的动画与重力(http://jsfiddle.net/2pcr9/4/在铬和Firefox测试)。我正在用canvas做Javascript。重力和速度的计算使用可变时间步长(46):重力与长时间步(使用JavaScript)

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

选择一些最大(或固定)时间步长。如果实际已用时间间隔大于最大时间步长,请多次运行物理功能。 – apsillers 2013-04-08 14:01:57

+0

我对画布不太熟悉,但我想会有一些接近on_resume事件的东西。如果恢复,只需将时间设置为您使用的最后一个delta_t。你认为这样的事情是可能的? – 2013-04-08 14:49:56

回答

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); 
} 
+0

谢谢,这是一个很好的方式来处理这个问题!对不起,我无法给你一个满意的答复,我的声望很低:D – 2013-04-09 08:12:08

1

使用这些jQuery的事件来启动/停止您的框架算了一笔账:

(你可以尝试没有jQuery的 - 直的JavaScript,但X-浏览器的东西会让你发疯!)

$(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 
}); 

唯一的问题是在一些浏览器中这些事件被多次触发,因此您可能还需要设置开/关标志,以便您对第一次触发做出反应。

+0

谢谢,这是一个快速和容易的黑客修复问题 – 2013-04-09 08:09:15