2012-03-25 109 views
3

在我的應用程序中,我根據窗口大小更新了CSS大小(CSS,不是html)的畫布。RequestAnimationFrame調用時間根據我的畫布大小而變化

我有一個主gameplayLoop它看起來像這樣:

run = function(){ 

    console.log(timerDiff(frameTime)); 

    game.inputManage(); 
    game.logics(); 
    game.graphics.animate(); 
    game.graphics.render(); 

    frameTime = timerInit(); 

    requestAnimFrame(run); 

} 

我requestAnimFrame功能是一個由保羅·愛爾蘭:

window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame  || 
      window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame || 
      window.oRequestAnimationFrame  || 
      window.msRequestAnimationFrame  || 
      function(callback){ 
      window.setTimeout(callback, 1000/60); 
      }; 
})(); 

所以基本上這個問題是計時器,我記錄哪些測量requestAnimFrame調用和有效函數調用之間的時間完全改變。 如果我的瀏覽器處於全屏狀態,我會得到像50/60毫秒,如果我有一個小窗口,我可以達到10毫秒。

由於requestAnimFrame調用應該不斷地調用60fps rythm下的函數(我想這大概是30ms),我不應該有這種結果,因爲定時器的創建和它的檢查,除了requestAnimFrame

我也有一些反覆發生的微凍(少於一秒),每2/3秒發生一次。但計時器沒有檢測時間的任何變化(如甚至和JavaScript的時間計數器被阻塞)

我的定時器功能是這樣的,但它並不真正的問題在這裏

timerInit = function() 
{ 
    return new Date(); 
} 

timerDiff = function(datePrev) 
{ 
    return new Date().getTime() - datePrev.getTime(); 
} 
+1

您的整個方法都有缺陷,'requestAnimationFrame'沒有預煮好的幀率,只要調用它就會「請求」下一個「動畫幀」。 – circusbred 2012-03-25 13:31:51

+1

默認情況下,requestAnimationFrame在Chrome中被鎖定爲垂直同步。我認爲這也是Firefox的情況。所以在大多數情況下,'requestAnimationFrame'的結果是60fps(當然,假設你的代碼可以跟上)。 – 2012-03-25 13:35:44

+0

好問題。我的遊戲每隔3秒也會「凍結」,我也在使用'requestAnimationFrame'。我天真地認爲這是垃圾收集器,即使我基本上沒有分配任何對象。 – 2012-03-25 13:37:17

回答

6

好,該標準基本上說,​​將「盡力」以「一致」的幀率運行。這並不能保證60fps;它只是表示它將盡可能快地進行動畫製作。

不幸的是,我的經歷與你的一樣暗淡。我最終回到setTimeout。它的速度大致相同,圖形更新是準確的,不會像​​那樣跳過一拍。當然,它不是60fps,但至少你可以知道發生了什麼。

我相信只有瀏覽器開發人員優化新功能時,性能纔會有所提高,但暫時可以考慮回到timeouts

編輯:我想提醒人們,這是一年前回答,時代已經改變了:)

+0

好吧,我試過了。它似乎有助於Firefox和IE瀏覽器,但不是鉻。因此:delta(我的函數持續的時間)總是類似於10 ms,但如果我測量setTimeout和有效函數首次亮度之間的時間,我會隨機選擇5到60毫秒之間的值,具體取決於屏幕尺寸。 我真的不明白如何一個畫布大小可以改變setTimeout通話時間... – Malharhak 2012-03-25 13:42:43

+0

@Malharhak我最好的猜測是,瀏覽器認爲它將需要重繪更多的像素。另外,33(或30fps)的「超時」時間段對我來說似乎很好。 1000/60約爲16毫秒,這相當快。 – 2012-03-25 14:42:26

+0

所以我嘗試了一些我的渲染模式:如果我的畫布處於動態分辨率(它的像素寬度和高度隨着窗口變化),它的效果很好。但是,當它處於「css」模式時,我的畫布具有800 * 600的分辨率,但被CSS調整大小,這使得我的遊戲如上所述變得遲鈍。 很奇怪 – Malharhak 2012-03-25 15:13:45

4

「所以基本上問題是,我登錄它測量之間的時間計時器requestAnimFrame調用和有效函數調用完全改變...「

當然,它確實,這就是爲什麼你需要測量它,並基於這個時間差值來計算你的下一幀。

讓我們假設你想在1秒內用60fps動畫製作div的'left'css屬性從0px到120px。

  • 使用的setTimeout,因爲你設置的幀數,你知道多少,你必須增加 '左' 屬性:120像素/ 60frames = 2px的/幀使用requestAnimationFrame

  • ,當下一幀會發生時,你沒有意識到,直到它發生;然後你測量這個和前一幀之間的時間差,你計算出你必須增加css'left value'的值;如果幀在500ms後發生,增量距離=(120px * 500ms)/ 1000ms = 60px;該IDEEA是,在動畫的開始,你不能有一個固定的預定值,並在每個幀遞增,您需要根據時間差來動態計算它

所以,即使動畫將不會達到廣告的60fps,如果跳過了幀,每一幀沒有跳過的幀都會得出準確的更新情況。

你必須小心翼翼地決定動畫何時結束。