2016-12-13 65 views
-2

我正在開發C++ roguelike RPG遊戲。現在我正在完成任務系統,這個想法是有抽象類Quest,每個新任務(例如「殺老鼠守衛」)都是新類,每個任務都包含我們需要做的抽象目標類的一些目標,一個一個。這工作正常。問題是目標彼此不同,例如實現多態的想法

class KillMonstersWhole : public Objective 
{ 
    vector<KillMonster> vector_of_monsters_to_kill; 
public: 
    virtual void ShowObjectiveStatus(); 
    virtual void CheckIfConditionsFilled(); 
    virtual vector<KillMonster> GetMonstersToKill() { return vector_of_monsters_to_kill; } 
    virtual vector<KillMonster>::iterator GetBeginOfMonstersToKill() { return vector_of_monsters_to_kill.begin(); } 
    virtual vector<KillMonster>::iterator GetEndOfMonstersToKill() { return vector_of_monsters_to_kill.end(); } 
    KillMonstersWhole(int amount, KillMonster first, ...); 
}; 

那類需要像GetMonsterToKill()等。(這是一個從抽象繼承目標)的一些特定功能,但如該

class ReachXY : public Objective 
{ 
    int x, y; 
    string status_text; 
public:  
    virtual void ShowObjectiveStatus(); 
    virtual void CheckIfConditionsFilled(); 
    ReachXY(int x, int y, string status_text); 
}; 

並不需要它,我不知道怎麼弄一種實現它的方式,不需要創建空白函數,這些函數不會做任何事情,並且會破壞我的代碼。我想繼續從一個抽象類繼承,因爲它的工作很好 - 在Quest類中,我只有一個Objective *對象的向量。我知道我可以在基礎Objective類中創建vector_of_monsters_to_kill,然後創建一個非純的虛函數,但ReachXY會帶上額外的,不可用的地方。當我使這個函數非虛擬化並將它們放在KillMonstersWhole類中時,我將失去通過多態指針來獲取它的能力Objective *。有什麼聰明的方法來做到這一點? Objective and Quest classes for everything clear:

class Objective 
{ 
protected: 
    bool conditions_fullfilled; 
    OBJECTIVE_ID id; 
public: 
    Objective() {} 
    bool GetConditionsState() { return conditions_fullfilled; } 
    virtual void ShowObjectiveStatus() = 0; 
    virtual void CheckIfConditionsFilled() = 0; 
    virtual vector<KillMonster> GetMonstersToKill() = 0; 
    virtual vector<KillMonster>::iterator GetBeginOfMonstersToKill() = 0; 
    virtual vector<KillMonster>::iterator GetEndOfMonstersToKill() = 0; 
    virtual OBJECTIVE_ID GetID() { return id; } 
    virtual ~Objective() {} 
}; 

class Quest 
{ 
protected: 
    string name; 
    vector<Objective*> objectives_list; 
    vector<Objective*>::iterator quest_state; 
public: 
    Quest() {} 
    vector<Objective*>::iterator GetQuestState() { return quest_state; } 
    OBJECTIVE_ID GetQuestStateID(); 
    vector<Objective*> GetObjectivesList() { return objectives_list; } 
    virtual void CheckRaiseQuestState(); 
    virtual void ShowDescription() = 0; 
    virtual ~Quest() {} 
}; 
+0

多態性依賴於統一的_interface contracts_。 –

回答

1

保持較高級別的類別的愚蠢,並使用較低級別的類別來完成詳細的工作。如果另一個類需要知道任務的狀態,應該有一個非常通用的接口,像

std::string Objective::getStatus() 

,對殺鼠經典的任務將實施類似

std::string RatKiller::getStatus() 
{ 
    switch (ratcounter)   
    { 
     case 0: 
      return "Rodents Of Unusual Size? I KNOW they don't exist. Heh heh heh." 
     case 1: 
      return "You need to kill 1 more rat!" 
     default: 
      return "You need to kill " + std::to_string(ratcounter) + " more rats!" 
    } 
} 

如果英雄的目標是聚集一個波旁威士忌,一個蘇格蘭威士忌和一個啤酒,getStatus看着英雄的庫存,發現波本威士忌和蘇格蘭威士忌,並返回「索羅格驅逐艦仍然需要一瓶啤酒!」。

這種方式頂層不會給smurf什麼目標,它只是顯示一個字符串。

我在這裏使用了一個字符串,因爲它沒有比字符串更通用,但是可以使用所有通用的狀態結構。

struct status 
{ 
    std::string message; 
    double percentComplete; 
    std::vector<std::string> othernotes; 
    // more general information here 
}; 

如果英雄執行一個動作(例如,殺死一個怪物),將該信息傳遞給目標,目標將相應地更新其內部狀態。

void RatKiller::updateStatus(Action & actionPerformed) 
{ 
    if (actionPerformed.getActionType() == KilledRat) 
    { 
     if (ratcounter > 0) 
     { 
      ratcounter--; 
     } 
    } 
}