我正在尝试创建一种机制,用一个Spell对象填充 vector ,每个对象都有自己的名称,然后选择带有cin输入的咒语并将其投射到目标上。最好的方法是什么?这就是我所做的,但是,如果该咒语具有多种咒语效果,该怎么办?
//Spell.h
class Spell
{
public:
enum e_spellType //enum with all spells
{
FIREBALL = 1,
FROSTBOLT
};
enum e_spellEffect //enum with different effects
{
DAMAGE = 1, //for damaging effect
SLOW
};
Spell(e_spellEffect effect);
void returnSpellEffect(Unit* target);
//getters here
string getSpellName() const { return m_SpellName; }
int getSpellValue() const { return m_SpellValue; }
int getCooldown() const { return m_Cooldown; }
int getManaCost() const { return m_ManaCost; }
protected:
string m_SpellName;
int m_SpellValue;
int m_Cooldown;
int m_ManaCost;
int m_SpellID;
e_spellEffect m_spellEffect;
e_spellType m_spellType;
};
Spell::Spell(e_spellType type)
{
m_spellType = type;
switch (m_spellType)
{
case 1: //Fireball
m_SpellValue = 35;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = DAMAGE;
case 2: //Frostbolt
m_SpellValue = 30;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = SLOW;
}
}
void Spell::returnSpellEffect(Unit * target)
{
switch (m_SpellEffect)
{
case DAMAGE:
target->takeDamage(m_SpellValue);
break;
case SLOW:
target->setDamage(0.5); //modifies Unit object's attack dmg to half
break;
default:
break;
}
}
//Game.h
class Game
{
public:
void enemyCombat();
protected:
Player *player;
vector<Enemy*> enemyList;
vector<Spell*> spellList;
};
void Game::enemyCombat()
{
//after you have chosen a target from enemyList (enemyList[target])
spellList.push_back(new Spell(FIREBALL));
spellList.push_back(new Spell(FROSTBOLT));
cout << "Choose a spell to cast:" << endl
<< "1. Fireball" << endl
<< "2. Frostbolt" << endl;
int spellChoice = 0;
cin >> spellChoice;
spellList[spellChoice-1]->returnSpellEffect(enemyList[target]);
}
如何使整个事情变得更抽象,以使一个咒语可以使用多个咒语效果?
最佳答案
考虑使用多态性。如果您具有虚函数doSpellEffects
,则可以在基类中实现“常规”逻辑,而在其他类中针对特定咒语或咒语类别实现更专门的逻辑。
class Spell
{
public:
// Copying disabled to avoid slicing.
Spell(const Spell&) = delete;
Spell& operator=(const Spell&) = delete;
virtual ~Spell() = default;
enum e_spellType { /*...*/ };
// TBD whether e_spellEffect belongs in Spell or SimpleSpell.
// Factory function:
static std::unique_ptr<Spell> create(e_spellType spellType);
const std::string& getSpellName() const noexcept { return m_SpellName; }
int getCooldown() const noexcept { return m_Cooldown; }
int getManaCost() const noexcept { return m_ManaCost; }
virtual void doSpellEffects(Unit* target) = 0;
protected:
Spell(e_spellType spellType) :
m_spellType(spellType), m_SpellName(),
m_Cooldown(0), m_ManaCost(0) {}
e_spellType m_spellType;
std::string m_SpellName;
int m_Cooldown;
int m_ManaCost;
};
class SimpleSpell : public Spell
{
public:
SimpleSpell(e_spellType spellType);
void doSpellEffects(Unit* target) override;
int getSpellValue() const { return m_SpellValue; }
protected:
e_spellEffect m_spellEffect;
int m_SpellValue;
};
class WarlocksRay : public Spell
{
public:
WarlocksRay() : Spell(WARLOCKS_RAY, "Warlock's Ray") {}
void doSpellEffects(Unit* target) override;
};
void WarlocksRay::doSpellEffects(Unit* target)
{
// Two effects!
target->takeDamage(5);
target->stun();
}
// The factory function that creates all spells:
std::unique_ptr<Spell> Spell::create(e_spellType spellType) {
switch(spellType) {
case FIREBALL:
case FROSTBOLT:
return std::make_unique<SimpleSpell>(spellType);
case WARLOCKS_RAY:
return std::make_unique<WarlocksRay>();
}
// Invalid spellType: Log an error? Throw an exception? Just return nullptr?
throw std::invalid_argument("Bad spellType in Spell::create");
}
您可以通过其他方式使用子类,这可能值得也可能不值得:
switch
中的SimpleSpell::doSpellEffects
,为每种常见效果类型创建类,例如DamageSpell
和SlowSpell
。 Spell
中移到NormalCastingSpell
类或某些东西中,该类将介于Spell
和层次结构中的其他类之间。 SimpleSpell
或DamageSpell
等,并且它需要定义的唯一成员是正确设置所有数据成员的构造函数。 关于c++ - 我应该如何在文字RPG中称呼玩家咒语?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56816917/