2013-07-29 87 views
1

我目前正在研究一個遊戲,其中有幾個類,每個類都處理自己的遊戲對象。對於這些類實際上代表遊戲中的某些東西,他們需要使用另一個類是animation_manager。 animation_manager處理屏幕上對象的加載,繪製和移動,並在啓動時創建。我應該使用公共指針嗎?

將管理器傳遞給處理遊戲對象的類最聰明的方法是什麼?

它應該由公共指針完成,通過將它分配給每個遊戲對象繼承的對象類中的靜態指針,或者我應該只是將它作爲指向gameobjects/object類構造函數的指針傳遞給它?

我使用C++ 03所以沒有新的花哨修正:P

編輯1:

已經有很多很好的建議,我已經麻木了。 現在我不會使用弱指針,因爲我不需要對象處理程序來處理指針的刪除,因爲它將從程序的開始到結束存在。 單身人士不適合我的需求,因爲我不希望任何職業人士有權訪問它。

讀到回覆時想到的一件事是:在所有處理類繼承的Object class中爲anim_handler製作static reference是一個好主意嗎?

+0

靜態引用的問題是它必須「靜態」初始化,並且作爲引用,它只能被初始化爲引用已定義的對象。因此,例如,如果您不能使用「new」實例化anim_handler對象,並且您可能會在祖先類和具體對象之間產生一個非常緊湊和相當不舒服的界限。你可以通過使用指針來克服這個限制,但是任何對象都可以對該指針執行「刪除」,或者只是修改它。如果你要走這條路線,我會建議使用智能指針。 – Albert

回答

0

在我看來,這個問題沒有明確的答案,而是多種方式,每個方法都有自己的觀點。 萬一別人有,我要一一列舉了下面的同一個問題:

Shared_Pointer: 此方法將跟蹤指向的地址和使用的指針的數量,如果該計數降爲零,那麼它將釋放內存。在C++ 11和boost庫中可用。 共享指針可以像普通指針一樣傳遞給其他對象。 的指針或引用可以被構建時,它被傳遞給對象:

通過ogni42

構造方法所傳遞建議。使用參考的好處在於程序員不能意外地在指針上使用delete

首選Onur。

使用單身 Singletons的是一個獨特的extern類,其保持一個指針,其可以通過一個函數進行訪問的對象。

這是由Albert提出

全局變量 只需全局聲明的變量。我個人不推薦這些,因爲他們可以變得一團糟,因爲他們成爲可用甚至代碼,你不會需要他們進來。

通過煎餅先生建議

靜態變量 這是我結束使用。我做到了這樣,只有繼承自我的Object類的對象才能訪問anim_handler。我這樣做的方式是聲明Object anim_handler的一個朋友,然後我使用靜態變量來檢索處理程序protected

不管怎樣,感謝大家的支持!我非常欣賞它,甚至還學到了新的東西! :)

0

您可以將此共享管理器對象保存在共享指針中,該指針被添加到C++ 11(或者您可以使用Boost庫)標準爲shared_ptr

它有一個引用計數機制,使您不必擔心相關對象的所有權和內存管理。

每個gameobject可以保留共享指針成員到您的animation_manager

+0

對不起。我應該提到我在C++ 11出來之前就開始寫這篇文章。我仍然在使用C++ 03。說到內存管理我得到了控制權。在解構animation_manger之前,每個objecthandler都將被刪除。 – Hjorthenify

+1

也可以參考'weak_ptr'。這樣,管理人員就不會持有真實的參考資料,並且可以對物體已被銷燬的情況作出適當的反應。這可以允許更自然的所有權管理。 – nijansen

+0

@Hjorthenify,它也在Boost。 –

0

我寧願傳遞的構造函數。

這樣你就可以建立一個不變的(即管理者總是存在),而後來設置一個字段並不能保證它總是完成。

就像剛剛發佈的托馬斯,你應該使用shared_ptr或類似的東西(如果不使用C++ 11)。

我儘量不要使用靜態字段(常量除外),因爲它會阻止您爲每個gameobject使用不同的管理器對象。 (想想一個調試/日誌記錄管理器類,或其他包裝管理器)。

+0

那麼管理器對於所有類都將保持不變,並且在運行時不會改變,所以不會在某種程度上變得更聰明,只是保持一個類的共享範圍很寬? 至於'shared_ptr'它們真的有必要嗎? – Hjorthenify

+0

你在說什麼是一個靜態指針,它可以被添加到所有你的gameobjects處理類的祖先類中。你仍然可以找到某種「好」的方式來初始化它,並避免任何對象修改它。如果我正確理解你的情況,我會按照我在答案中寫到的單例模式進行:最好不要讓用戶反對修改對animation_manager的引用的自由... – Albert

+0

全局訪問的單例是不好的,就像所有的全局可訪問的中午常量是。就像我在回答中所述:如何爲某些gameobjects實現「特殊」管理器?看看這些文章,瞭解爲什麼應該避免全球訪問單身人士:http://misko.hevery.com/2008/08/25/root-cause-of-singletons/。 – Onur

0

如果你的animator_manager是一個獨特的對象,另一種方法可能是將其定義爲signleton,最終不需要在gameobjects處理類中存儲對它的任何引用,並使用某種靜態方法,如animation_manager :: getInstance )來使用它。

通過減少對getInstance()方法的調用,可以輕鬆降低性能影響,但它確實取決於您的設計,無法確定它適合。

+0

使用單例會對性能產生什麼影響?函數調用的數量增加或什麼? – Hjorthenify

+0

那麼,我會談論一個單身人士(如果你需要不止一個,我會建議改變策略)。無論如何,這真的取決於:如果對假設的animation_manager :: getInstance()的調用保持在必要的範圍內(只需緩存返回的值),性能影響可以忽略不計。如果你的animation_manager是一個服務於你應用程序中所有對象的對象,並且你認爲你永遠不需要更多的實例,我相信它可以適用。 – Albert

+0

永遠不會有一個以上的經理實例。單身人士將是一個解決方案,但是是否有可能僅使從「對象」繼承的類能夠訪問它?我不希望任何班級不應該能夠加載動畫能夠這樣做。 – Hjorthenify

0

你應該給它作爲參考(如果可能的話,對const的引用),而不是指針。只有當你有一個動畫管理器的類層次結構時,一個指針(如果可能的話const爲const)纔有意義。在後一種情況下,你應該考慮使用boost的shared_ptr。如果以後轉移到C++ 11,對C++ 11的shared_ptr的更改很少。

從設計角度來看,您可能還會考慮使用觀察者模式,因此動畫管理器可以自行決定何時適合渲染而不需要太多的樣板代碼。

+0

我喜歡使用引用的想法,但shared_ptr似乎有點過分用於我的需要。 – Hjorthenify

+0

訪問時,'shared_ptr'幾乎沒有開銷,但可以幫助您管理釋放和引用計數。由於boost/C++ 11,我會盡可能避免使用原始指針,除了一些精確的庫外,我幾乎可以避免它們。 – ogni42

+0

我如何編程一個shared_ptr而不使用boost?我的意思是如何在不允許使用delete關鍵字的情況下添加對基礎ptr的訪問? – Hjorthenify

0

當作爲一名優秀的軟件架構師思考時,傳遞引用是最有利的方式,因爲它可以使測試和嘲笑變得更簡單。

但是,在我看來,遊戲(引擎)是一種軟件的特殊情況,在這種情況下,「好模式」有時會起反作用。在任何地方你都需要一些經理職位的情況下,你幾乎總會遇到這種情況。

您可能想看看上帝對象的反模式,以使所有常用管理器可用於全局。我使用「應用程序」 -instance,其中包含一些引導代碼,並引用最常見的管理類,像這樣的一個全局訪問的實例:

// application.h 
class CApplication { 
    void init(int argc, char **argv); // init managers & co here 
    void shutdown(); 
    void run(); 

    CMemoryManager * memory; 
    CSystemManager * system; 
    CAudioManager * sound; 
    CInputManager * input; 
}; 

// globals.h 
CApplication * app; 


// main.c 
#include "globals.h" 
int main(int argc, char ** argv) { 
    app = new CApplication(); 
    app->init(argc, argv); 
    app->run(); 
    app->shutdown(); 
    return 0; 
} 

// some_other_file.cpp 
#include "globals.h" 

void doSomething() { 
    // ... 
    app->input->keyDown(...); 
    // ... 
} 

不良作風(!)?大概。它工作嗎?對我來說它的確如此。反饋也歡迎評論!

+0

我不認爲它可能被定義爲不好的風格或不好的解決方案。大多數複雜的應用程序都基於某種管​​理對象的大型上下文和子系統,這是因爲實現的功能基於子系統之間非常緊密的關係。很多時候,設計者往往花費很大力氣試圖實現軟件子系統之間的隔離,只是意識到如果隔離太大,系統根本無法工作。 :) – Albert

0

我正在添加另一個答案,因爲與previuos相比,這是一個完全不同的方法。首先,我應該澄清一點,我沒有在遊戲編程方面的經驗! :) 無論如何,正如我在之前的評論中所暗示的那樣,也許我會採取不同的路線。 Immagine,你有一個「遊戲場」與牆壁和其他靜態元素,以及一些「演員」,如怪物,玩家改變自我等...... 我可能會寫一個祖先「演員」,subcalssing「玩家「和」敵人「等級,然後將」敵人「分爲」龍「,」殭屍「,」鱷魚「等等。也許演員可以有一些共同屬性,如「位置」,「速度」,「強度」,「能量」,「方向」,「目的地」和狀態,如「移動」,「睡覺」,「吃球員」,‘被eated’...... 一個典型的遊戲迭代,可能是這樣的:

1)從玩家

2)調用播放器的演員對象的方法獲取輸入,這樣的:

player->move(east, fast); 

3)週期低谷的演員名單來更新自己的狀態,說:

for (int i(0); i < enemies.size(); i++) { 
    // Checks the player position in the gamefield and setup a strategy to eat him 
    enemies[i]->updateStatus(player, gamingField); 
} 

4)週期低谷演員名單和移動:

animator->animate(player); 
for (int i(0); i < enemies.size(); i++) { 
    animator->animate(enemies[i]); 
} 

5)檢查,如果一些有趣的事情發生(球員已被鱷魚吃掉)

我的意思是:這是一個完全不同的方法,但我認爲隔離演員邏輯可能是一個好主意,你可以完全避免原始問題。

+0

這實際上有點相同的方式,我想要做到這一點,但不是循環遍歷所有這些,我想添加他們tp quoue(想想windows消息處理程序),然後動畫處理程序用它來找到需要的更新。 – Hjorthenify

相關問題