2011-06-16 58 views
2

我在寫遊戲,它將使用基於組件的實體系統。我正在實現的前兩個組件是EntityRepresentation和EntityState。該表示包含動畫,狀態決定實體如何對遊戲事件做出反應(EntityStates的例子:站立,跳躍,攻擊,死亡,墜落)。基於組件的遊戲實體和類型檢查

EntityRepresnetation根據Entity的EntityState決定在屏幕上繪製哪些動畫。如果實體處於「跳躍」狀態,則將播放相應的動畫。 (見EntityRepresentation :: changeAnimation()函數。)

這裏大概我如何寫作類...

class EntityRepresentation 
{ 
    public: 
    void draw(float x, float y, long currentTime, DrawingContext& dc) { 
     // ... 
    } 

    void changeAnimation(const EntityState::Id& stateId) { 
     currentAnimation = animationMap_[stateId]; 
    } 

    private: 
    map<EntityState::Id, const Animation*> animationMap_; 
    const Animation* currentAnimation_; 
}; 

有東西,我真的不與我目前的做法喜歡...> :(EntityState :: Id部分目前,EntityRepresentation將它保存的每個動畫映射到一個特定的EntityState :: Id,這個ID對於派生自EntityState的每個類是唯一的(對於類是唯一的,而不是實例)。基本上是必須在類的構造函數中手寫的字符串,這意味着它們更容易發生名稱衝突—,因爲我打算讓遊戲可腳本化(Python)。

有人可以給我一些建議,關於如何我可以減輕我與ID的問題。我在遊戲中看到很多基於組件的系統的實現,這些遊戲也使用了ID,但我仍然不喜歡它們。它只是歪曲我的方式。

也許你可以建議一個設計更改,以便EntityRepresentation不必知道EntityState的類型,同時仍然保留封裝。

+0

「取決於實體的狀態」 - 這是與EntityState相關的,或者例如到更廣義的國家? – 2011-06-16 12:35:06

+0

@Luc在EntityState類上。 EntityState是所有狀態的基類。 EntityState有一個類型爲EntityState :: Id的字段(它只是一個字符串),對於每種類型的EntityState來說都是(應該是)唯一的。 – 2011-06-16 12:40:14

回答

1

使用typeid的()的設計,這就是它是。您可以使用const type_info*作爲關鍵類型。或者,你可以使用實際繼承,就像調用一個虛擬函數來獲取當前的動畫一樣,這會更聰明。

+0

使用'typeid'是我留在腦後的一個選項,但我試圖避免,因爲它通常用於調試目的。不過,我並沒有放棄它。 ** | **我不太瞭解遺傳如何在我的情況下工作。你能否添加一些更多的細節? – 2011-06-16 13:29:17

1

假設在編譯時不需要與每個EntityState關聯的ID,我使用的一個技巧是使用指針作爲ID。如果EntityState是一個單身人士,這種方法特別有效,在這種情況下,您可以簡單地使用單身人員實例的地址作爲ID。否則爲每個ID靜態分配一小塊內存就可以正常工作。

class EntityState { 
public: 
    EntityState(void *id) : mId(id) { } 
private: 
    void *mId; 
}; 

class EntityStateJump : public EntityState { 
public: 
    EntityStateJump() : EntityState(getId()) { } 
private: 
    void *getId() { 
     static void *id = new int; 
     return id; 
    } 
}; 

編輯:輕微更改以避免靜態初始化順序問題。

+0

我已經通過了這兩種解決方案。除此之外,我還會使用單例,它們越來越成爲一種可行的選擇,特別是因爲它們很容易在Python(我將要使用的腳本語言)中實現。不過,我並不十分了解'EntityStateJump'類如何爲每個類類型生成唯一的ID。 – 2011-06-16 13:31:42

+0

你對「班級類型」有什麼意義?我假設你將爲每個從EntityState派生的類創建一個且只有一個ID,其中該類的每個實例都具有相同的ID。 – zennehoy 2011-06-17 09:47:22

+0

@zennnehoy是的,這就是我的意思。 – 2011-06-17 10:00:35

1

我建議實現使用State pattern

class EntityState 
{ 
public: 
    EntityState(const Animation* animation); 
    static const EntityState* getStandingState(); 
    static const EntityState* getJumpingState(); 
    static const EntityState* getAttackingState(); 

    const Animation& getAnimation() const; 

protected: 
    const Animation* pAnymation_; 
}; 

class EntityRepresentation 
{ 
public: 
    void draw(float x, float y, long currentTime, DrawingContext& dc) { 
     // ... 
     const Animation& animation(state_->getAnimation()); 
    } 

    void changeState(const EntityState* newState) { 
     state_ = newState; 
    } 

private: 
    const EntityState* state_; 
}; 

void EventHandler(EntityRepresentation& entity) 
{ 
    entity.changeState(EntityState::getJumpingState()); 
} 
+0

謝謝你的回答! :)當我對「保護封裝」發表評論時,這就是我所說的。我不希望國家持有本來只對代表性感興趣的數據。 – 2011-06-16 13:27:17