2010-01-25 158 views
2

我有一個用C++編寫的遊戲引擎設計,其中平臺無關的遊戲對象包含在平臺特定的應用程序對象中。在獨立於平臺的設計中傳遞特定於平臺的數據?

我試圖解決的問題是我需要從應用程序傳遞特定於操作系統的數據到遊戲的情況。在這種情況下,我需要將Windows的DirectX主要HWND或其他平臺的OpenGL上下文傳遞給我正在使用的渲染器。不幸的是,我無法控制渲染器,它可以預期特定於平臺的數據。

我意識到我可以初始化應用程序方面的渲染器,但我寧願讓遊戲決定何時何地做這件事。一般來說,我可以控制應用程序方面,而不是遊戲方面。遊戲作者可能會選擇使用不同的渲染器。

我也喜歡有一種「物業經理」的想法,我可以通過字符串傳遞數據,但我不太喜歡這個想法。

任何想法?

+0

如果遊戲對象是平臺獨立的,那麼爲什麼它需要通過平臺相關變量? – 2010-01-25 15:10:41

+0

好問題!長話短說,我們可以控制應用程序類,但不能控制渲染器或遊戲類。 這只是我們目前正在探索的內容。 – djcouchycouch 2010-01-25 15:27:21

回答

3

請記住,您只需要在編譯時瞭解目標平臺。有了這些信息,您就可以爲正確的平臺「換入和換出」組件。

在一個好的設計中,遊戲應該是而不是需要關於它的平臺的任何信息;它只應該掌握邏輯和相關組件。

您的'引擎'類應該擔心該平臺。

遊戲類只能通過公共函數與引擎對象進行交互,這些公共函數並非特定於平臺;您可以爲每個平臺提供多個Engine對象版本,並在編譯時選擇使用哪一個。

例如,您可以有一個表示遊戲紋理的紋理「引擎」類。如果您支持OS X和Windows,則可以使用「Texture.h」,其中包含「Windows/Texture.h」或「OSX/Texture.h」,具體取決於您正在編譯的平臺。這兩個頭文件將定義一個具有相同接口的Texture類(即它們都具有相同的參數的相同公共函數),但它們的實現將是特定於平臺的。

爲了澄清,遊戲應告訴應用程序初始化渲染器;遊戲邏輯和實現細節之間應該有嚴格的界限。渲染器是實現細節,而不是遊戲邏輯的一部分。遊戲類應該對系統一無所知,而只涉及遊戲世界。

1

查看模板模式(在抽象基類中使用可以在派生類中配置的純虛函數)。

http://en.wikipedia.org/wiki/Template_pattern

如果你喜歡一個更可控的(和更少的面向對象)的方式,遊戲的部分應該調用的應用程序部分配置的回調函數,以執行特定於平臺的配置。

例如爲:

// in Application: 
static void SetWindowHandle(GameEngine const& p_game_engine, void* p_callback_data) 
{ 
    p_game_engine.DoSomethingWithHandle(static_cast<ApplicationManager*>(p_callback_data)->GetHWND()); 
} 

void Initialize() { 
    this->m_game_engine.Initialize(this, &Application::SetWindowHandle); 
} 

// ... 
// in Game Engine: 
// ... 

typedef void (*TSetWindowsHandleCallback)(GameEngine const*, void*); 

void* m_application_data; 
TSetWindowsHandleCallback m_windows_handle_callback; 

void Initialize(void *p_application_data, TSetWindowsHandleCallback p_callback) 
{ 
    this->m_application_data = p_application_data; 
    this->m_windows_handle_callback = p_callback; 
} 

void SetWindowsHandle() 
{ 
    this->m_windows_handle_callback(*this, m_application_data); 
} 
+0

+1,但我更喜歡dauphic的方法,因爲使用派生類可以一次封裝多個特定於平臺的行爲。實際上,基類中的每個公共方法==「可配置的回調函數」。 – 2010-01-25 15:16:04

1

怎麼樣得到一個SystemContext類傳入?你會有一個Win32Context,LinuxContext等。這是OGRE處理它的方式(RenderContext就是這種情況)。

Renderer類需要一個SystemContext指針。

在內部,DirectXRenderer(Renderer的後代)dynamic_casts(一次)指向Win32Context的指針,並從中挑選出所有依賴於平臺的數據。

0

我喜歡做的是讓一個基類與所有通用數據成員實現共享。然後我有一個本地類,它包含基類本身包含的特定於平臺的信息。這需要一個特定的目錄結構。例如,你有:

code 
    renderer 
    context.h 
    platforms 
    win32 
     renderer 
     context_native.h 
    osx 
     renderer 
     context_native.h 

code/renderer/context.h 
class RenderContextBase { /* shared members */ }; 
#include "renderer/context_native.h" 

code/platform/win32/renderer/context_native.h 
class RenderContext : public RenderContextBase { /*win32 specific */ }; 

code/platform/osx/renderer/context_native.h 
class RenderContext : public RenderContextBase { /*osx specific */ }; 

使用你的編譯器「附加包含目錄」,你只需添加取決於平臺上正確的目錄。例如,在win32上,添加「code/platform/win32」作爲附加目錄。當包含renderer/renderer_native.h時,它將不會在「默認」位置找到,並會嘗試使用其他目錄。

從代碼中的任何地方RenderContext是本地實現。你不需要有一個指向基類和新的本地類的指針,因爲你真的有1個實現。當你真的有一個給定平臺的實現時,這可以避免有基本的虛擬功能。