2010-07-10 77 views
4

我正在爲OpenGL ES創建一個2D遊戲。我打電話設置爲「NO」重複使用的NSTimer在0.002(60 fps)的間隔我的遊戲循環(從函數內再次我運行的NSTimer建議):如何在新舊iPhone上獲得一致的速度?


-(void)gameLoop:(id)sender { 
    double currTime=(double)CACurrentMediaTime(); 
    m_FPS_framesThisSecond++; 
    float timeThisSecond=currTime-m_FPS_lastSecondStart; 
    if (timeThisSecond>1.0f) { 
     m_FPS=m_FPS_framesThisSecond; 
     m_FPS_framesThisSecond=0; 
     m_FPS_lastSecondStart=currTime; 
    } 

    [game update]; 
    [game render]; 

     //Continue the loop 
    [NSTimer scheduledTimerWithTimeInterval:0.002 target:self selector:@selector(gameLoop:) userInfo:nil repeats:NO]; 
} 

這將運行順利地在我的3GS上,但是當我在2G上測試時,遊戲運行速度慢得多,有時偶爾會出現空白幀。當我將間隔降低到0.033(30 fps)時。 3G上的速度太慢了。

我知道必須通過某種方式在兩臺設備上獲得持續播放。塗鴉跳躍似乎運行平穩,並在兩個手機相同的幀率。

+0

那麼,還有什麼時候離開硬件架構的骯髒的思想流派。自iOS4起,蘋果公司(官方)放棄了對iPhone 2G(原始iPhone)的支持。也許,也許你可能會考慮做同樣的事情,因爲任何未來的OpenGL ES更新將只針對3G以上(看到蘋果現在如何發佈OpenGL ES2設備功能的系統 - 儘管3G不支持ES2) 。不要告訴你,你有一個不好的問題,(事實上,我爲它+1)...只是說有時你需要考慮你的應用程序的未來。 – Jann 2010-07-10 22:33:22

+0

我肯定會忽視3GS之前的設備(我不知道有2G的任何人)。但同時,我想我應該將遊戲速度與幀率分開。無論如何,OpenGL ES2將是我的下一個努力! – Scott 2010-07-11 01:49:45

回答

2

的基本問題是:

你的遊戲需要,而不是由它多少次渲染來更新的基礎上,因爲它渲染的最後一次經過的時間量。假設您正在基於某個速度計算精靈的位置。新位置應根據渲染之間的時間進行計算,而不是假設自上次渲染以來經過0.002秒。這被稱爲FPS獨立動畫。

所以,這裏是一個簡單的例子:

// FPS dependent animation 
int x = sprite.x + sprite.velocity.x 

正確的方式做,這是使用時間從去年渲染,而更新比例。以下代碼假定0.002是時基。

// FPS independent animation 
int x = sprite.x + sprite.velocity.x * time_since_last_render/0.002 

在其中渲染需要兩倍長的設備,下次更新將盡量兩次移動的對象,因此它在同一個地方,因爲它會更快的設備上結束。

一個側面的問題,你不應該總是在將來的0.002秒內渲染下一幀。您應該看到當前幀需要渲染多長時間,從0.002中減去該值並使用它計劃下一個渲染。當然,這個數字的最小值爲零,所以在慢速設備上你不會開始調度到過去。例如,如果您的渲染函數需要完全0.002秒的渲染時間,這會使您的幀速率降低一半。

+0

謝謝!我會通過簡單地獲得當前時間減去前一幀的時間之間的差異來計算time_since_last_render嗎? – Scott 2010-07-11 01:44:21

2

實際上有兩種類型的幀速率的:

  • 顯示幀率:在該屏幕重繪
  • 邏輯幀速率:在該遊戲邏輯被更新率(遊戲速度)

我認爲你正在尋找一個恆定的邏輯幀速率,從顯示幀速率去耦,以適應手機硬件的上限能力。比較你的遊戲循環必須爲每個邏輯幀完成一個顯示幀。

查看deWiTTERS Game Loop中描述的「Constant Game Speed with Maximum FPS」算法遊戲邏輯在3G和2GS上都會以相同的速度運行,但顯示幀速率將調整爲較慢的2G CPU。雖然以上文章未涉及,但您也可以限制顯示幀速率以節省電池電量。