2013-10-14 170 views
0

我理解指針和引用的基礎知識,但我所面臨的最大問題是在決定何時應該使用(以及哪些)。我會給出的主要例子是基本遊戲之一。假設的設置是這樣的:類指針與參考

  • 新的世界
    • 相機
    • 地圖

世界是一個指針,因爲每次遊戲開始一個新的保存或加載現有一,它刪除世界並加載一個新的。但在世界範圍內,只有一個相機和地圖的存在應該存在,並且只存在於世界的時間。如果世界被摧毀,那麼他們顯然也應該如此。然而..讓讓Map需要訪問攝像頭(但其他對象也是如此),Camera是否應該通過引用傳遞給Map或作爲指針,或者?舉例來說,如果它應該是通過引用,它應該是:

map = Map(&camera); 
(inside map class) Map(Camera camera) {...} 

還是更喜歡:

map = Map(camera); 
(inside map class) Map(Camera &camera) {...} 

而且,可以說地圖擁有瓷磚稱爲網格的2D矢量。喜歡的東西:

std::vector< std::vector<Tile> > > grid; 

現在可以說,我有需要該網格傳入探路類它需要直接編輯瓦片改變F,G等值(尋路)。該2D矢量是否應該是Tile的正常2D矢量,並且整個事情是通過引用PathFinder傳遞的?還是應該是Tile指針的2D矢量?此外,NPC和玩家將有一個currentTile,這是他們當前所在的圖塊。他們將需要有一個引用或指針的瓷磚,使他們也可以通過這樣的人大/播放器類中設置自己爲對瓷磚乘員:

currentTile = tile; 
currentTile->SetOccupant(this); 

其他關心進來當我再銷燬該網格以加載新地圖,我如何輕鬆處理,確保沒有任何內容指向不再存在的Tiles。我只需循環這些類並將currentTile設置爲NULL?

這是我開始真正被這個東西弄糊塗的地方。 任何幫助表示讚賞,因爲我顯然非常nooby。 @ _ @; 對不起,如果這不是真的遊戲相關主題。如果它需要移動到不同的堆棧交換,請讓我知道或移動它(如果可以的話)。 > _ <

+2

被認爲屬於StackOverflow,因爲這實際上是一個關於C++最佳實踐的問題。在附註中,2D網格的矢量矢量非常糟糕;只需使用一個矢量並手動計算其內部的偏移量(或者編寫一個簡單的包裝)。 –

+0

@SeanMiddleditch感謝向量載體的提示。沒有意識到這是不好的。只是做了一個接口,我的瓷磚網格計算偏移量,所以它只是一個向量。 ^^; – Zyaga

回答

1

考慮Map類。您可以通過引用或指針傳入相機。這真的不重要。重要的是相機傳入的內容會發生什麼。您是否將其分配給Camera *的成員?否則,在構造函數中設置攝像頭不會有太大的成就。每次調用需要攝像頭的地圖時,您都必須提供相機指針/參考。

對於存儲平鋪對象,單維std :: vector <>會很好。通過使用一些簡單的數學,這個瓦片網格可以很容易地遍歷。嵌套另一個向量只會導致不必要的開銷。這裏是這樣做的一個抽樣算法:

std::vector<Tile> tiles = makeTiles(); 
for (int y=0; y<mapHeight; y++) 
{ 
    for (int x=0; x<mapWidth; x++) 
    { 
     Tile tile = tiles.at(x + y*mapWidth); 
     tile.doSomethingWithTile(); 
    } 
} 

決定如何從地圖到探路者獲取瓦片數據是真正的你要如何保護你的地圖數據的問題。通過提供所有瓦片數據的參考,您基本上可以將其公開訪問。由於路徑查找需要編輯個別瓷磚,但不是整個小塊陣列本身,更好的辦法是有一個這樣的方法:

Tile* Map::AccessTile(int tx, int ty); 

這樣,瓷磚數據的整個媒介不會暴露,但路徑查找器將能夠得到所需的東西。此外,Map :: AccessTile()可以變爲私有,並且路徑查找器被聲明爲Map的朋友。另一種方法是提供像Map :: SetTileF(int tx,int ty,float f)這樣的方法。這可能很乏味。

對於NPC和播放器,可以使用類似的解決方案。他們實際上並不需要直接寫入他們所在的磁貼。添加一個像Map :: SetTileOccupant(Entity * entity)和相應的Map :: GetTileOccupant()的方法。

現在您關注刪除對象。您應該查看一些由C++提供的仿真指針(特別是std::shared_ptr<>std::weak_ptr<>)。這些快速解釋是shared_ptr是一個「擁有」一個對象的指針,而weak_ptr知道在哪裏訪問該對象,但實際上並不「擁有」這個對象。

通過這些模擬指針,你可以這樣做以下:

//prototype for setWorld 
//note that shared_ptr<> casts to weak_ptr<> nicely 
Camera::setWorld(std::weak_ptr<World> world); 

//setup the camera and world 
std::shared_ptr<World> world(new World); 
Camera camera; 
camera.setWorld(world); 

與上面的代碼,攝像頭有一個指針到世界各地。如果世界是由於某種原因被刪除,相機可以通過下面的方法算出來:

bool Camera::worldIsValid() 
{ 
    return (this->mWorld.expired() == false); 
} 

而且,要封裝世界內的攝像頭,這是可能是你並不需要做的。相反,相機可以是獨立的,只要需要關於它的信息或World中包含的地圖,就可以引用世界。

+0

如果你不介意的話,最後一個明確。如果我想讓地圖持續世界的持續時間,並希望能夠將它傳遞給其他世界成員/類,Map應該成爲世界內的指針(或者只是一個普通變量)嗎?我假設如果我不*使它成爲一個指針,它會失去範圍? – Zyaga

+0

你可以使它成爲一個指針,但沒關係。如果您將其聲明爲Map或Map *,則只要世界對象仍在周圍,它就會持續。顯然,如果你有一個Map *,你將不得不使用new運算符手動創建對象。如果你想使用shared_ptr <>,那麼該地圖需要聲明爲shared_ptr 。 –