2013-04-08 76 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