2016-01-16 61 views
2

我們都知道,如果某些fps很重要,或者類似這樣的話,制定正確的更新算法是多麼困難。使用while(Date.now()<interval){}與requestAnimationFrame()

無論如何,我只是想到了這個無限循環的黑客,它只是凍結了程序,直到下一幀,而且它看起來工作得很完美。

var then = Date.now() 
var fps = 40; 
var interval = 1000/fps; 
function mainloop() { 
    while (Date.now() - then < interval) {} // freezes program until next frame 
    requestAnimationFrame(mainloop); 
    then = Date.now(); 
    // update logic goes here 
} 
mainloop(); 

我還沒有在任何地方看過這個解決方案,所以我想問問它是否乾淨和正確。我知道凍結程序只是爲了等待一些東西,而這段代碼看起來很糟糕,但它似乎有效。有沒有一種更清潔的解決方案可以和我的代碼一樣工作?

+2

好吧,冷凍很少會被認爲是正確的。我認爲針對某個fps是一個不好的方法,而是儘可能渲染儘可能多的fps,並相應地調整動畫。意思是,不是針對特定的時間間隔,而是確定自上一幀渲染以來已過去了多長時間,並相應地進行了動畫處理。 – jishi

+0

問題是我需要每個幀都是相同的,我不能製作任何「更長」或「更短」的幀,並且我還需要程序以某種速度運行,因爲音樂同步等。 – BoltKey

+0

我認爲我所說的術語稱爲基於三角洲的動畫。您不必進行固定的框架更改,而是可以開始和結束,並能夠計算在某些時間點應該發生的更改。 – jishi

回答

0

在特定情況下,它可能會是更好的延緩使用setTimeout的主循環執行,就像這樣:

var nextExecution = Date.now() - then + interval; 
if (nextExecution < 0) nextExecution = 0; 
setTimeout(mainloop, nextExecution); 

這將允許它做其他的東西在等待下一幀的渲染。

0

使用while循環浪費時間是一個壞主意。這隻會浪費處理器時間,可能會做其他事情。

使用SetTimeout如jishi所建議的,是一種可能的解決方案。但是,只有在您的代碼運行時纔會進行控制。您無法真正控制瀏覽器實際繪製的時間。基本上,瀏覽器將繪製代碼更新的最後一幀。

因此,另一個可能的解決方案是使用requestAnimation。在您的繪圖代碼中,確定以您喜歡的速率出現的最後一幀。畫出該框架。例如...

var start = null; 
var fps = 40; 
var interval = 1000/fps; 
function mainloop(timeStamp) { 
    if (!start) { 
     start = timeStamp; 
    } 
    var n = (timeStamp - start)/interval; 
    // update logic goes here to paint nth frame 
    requestAnimationFrame(mainloop); 
} 
mainloop(); 
0

您可以使用setTimeout等待一段時間,但這不會很精確。然而通過改變interval你可以得到足夠精確的平均延遲。

var startTime = Date.now(); 
var fps = 40; 
var frames = 0; 
var interval = 1000/fps; 

function mainloop() { 
    frames++; 
    var timeElapsed = Date.now() - startTime, 
     averageFps = 1000 * frames/timeElapsed; 
    if(averageFps < fps && interval > 0) interval -= 0.1; 
    if(averageFps > fps) interval += 0.1; 
    setTimeout(mainloop, interval); 

    // update logic goes here 
} 
setTimeout(mainloop, interval); 

但仍有風險的計算機是無法滿足要求的FPS,如果它的速度太慢。

+0

這就是有趣的解決方案。如果在應用程序中,有些部分在CPU上很重,間隔設置爲低值,然後在代碼的簡單部分上程序運行速度過快,則會出現問題。計算最近20幀的平均fps可能會更好。 – BoltKey