2009-05-28 50 views
4

我使用Visual C++ 2008 Express和Ogre3D sdk編寫遊戲。異步屏幕更新爲遊戲玩法邏輯,C++

我的核心遊戲邏輯被設計爲以100次/秒的速度運行。爲了簡單起見,我會說這是一種名爲'gamelogic()'的方法。這不是基於時間的,這意味着如果我想將遊戲時間提前1秒,我必須將「gamelogic()」調用100次。 'gamelogic()'與遊戲的屏幕渲染相比是輕量級的。

Ogre有一個「偵聽器」邏輯,告知您的代碼何時繪製框架以及何時完成繪製框架。如果我在幀渲染之前調用「gamelogic()」,那麼遊戲將受到屏幕渲染速度的很大影響,屏幕渲染速度可能從5fps到120fps不等。

想到的最簡單的解決方法是:計算自去年渲染的幀中的時間和呼叫「gamelogic()」下一幀之前很多次:100 * timeElapsedInSeconds

不過,我pressume了「正確「的方式是使用多線程;有一個單獨的線程運行'gamelogic()'100次/秒。

問題是,我該如何做到這一點?當兩個獨立的線程發生衝突時,可以做些什麼:gamelogic改變屏幕內容(3d對象座標),同時Ogre同時呈現屏幕。

許多在此先感謝。

回答

6

如果這是您的第一個遊戲應用程序,使用多線程來實現您的結果可能比您應該在第一場比賽中真正應對更多的工作。在不同線程中同步遊戲循環和渲染循環並不是一個容易解決的問題。

正如您正確指出的那樣,渲染時間會極大地影響遊戲的「速度」。我建議你不要讓你的遊戲邏輯依賴於設定的時間片(即1/100秒)。使其依賴於當前的幀時間(好吧,最後一幀時間,因爲你不知道你的當前幀需要多長時間來渲染)。

通常我會寫類似下面(我寫的是大大簡化):

float Frametime = 1.0f/30.0f; 
while(1) { 
    game_loop(Frametime);  // maniuplate objects, etc. 
    render_loop();    // render the frame 
    calculate_new_frametime(); 
} 

哪裏FRAMETIME是calculcated幀時間,當前幀了。當你處理你的遊戲循環時,你正在使用前一幀的幀時間(因此將初始值設置爲合理的值,如1/30或1/15秒)。在以前的frametime上運行它足以讓您獲得所需的結果。使用該時間框架運行你的遊戲循環,然後渲染你的東西。您可能必須更改遊戲循環中的邏輯,以避免假定固定的時間間隔,但通常這些修復很容易。

異步遊戲/渲染循環可能是你最終需要的東西,但這是一個難以解決的問題。它涉及到拍攝對象及其相關數據的快照,將這些快照放入緩衝區,然後將緩衝區傳遞給渲染引擎。該內存緩衝區必須在關鍵部分正確分區,以避免在渲染循環正在讀取時將遊戲循環寫入它。在傳遞到渲染循環之前,您必須小心確保將所有相關數據複製到緩衝區中。此外,您必須編寫邏輯來停止遊戲或渲染循環,同時等待其中一個或另一個完成。

這種複雜性也是爲什麼我建議在多個串行的方式先寫它(除非你有經驗,你可能)。原因在於,首先使用「簡單」方法將迫使您瞭解代碼的工作方式,渲染引擎的工作方式,渲染引擎需要的數據類型等。多線程知識在複雜遊戲開發中非常明確這些天,但知道如何做得好,需要深入瞭解遊戲系統如何相互作用。

+1

遊戲從固定渲染率假設,以追蹤框倍切換前一段時間 - 他們習慣了依賴知道處理器在8赫茲運行。當他們推出16Hz的機器時,他們包括一個'turbo按鈕'將處理器從16Hz切換到8Hz,這樣遊戲仍然可以以正確的速度運行。有趣的事實。 – Kieveli 2009-05-28 14:21:46

0

雙緩衝的渲染能力的對象是你可以探索的途徑。意思是,渲染組件正在使用1個緩衝區,當所有遊戲動作已經更新了第二緩衝區中的相關對象時,該緩衝區將被更新。

但我個人不喜歡它,我(和具有的頻率)使用馬克的做法。

1

這裏沒有一大堆的好處到你的核心遊戲邏輯運行速度比玩家可以做出迴應。關於唯一一次真正有用的是物理模擬,在快速,固定的時間步長運行可以使模擬的行爲更加一致。

除此之外,只是每幀更新您的遊戲循環一次,並通過在可變的時間增量,而不是依賴於固定的。您從多線程中獲得的好處與成本相比是微不足道的,特別是如果這是您的第一場比賽。