我目前正在为一个学校项目工作,我们必须设计一个基于文本的冒险游戏。 在我的游戏中,我制作了“物品”类,但想知道区分物品的最佳方法是什么。 我首先想到继承:
class Item{
protected:
//generic item info (cost, name, etc.)
public:
Item();
~Item();
};
class Weapon: public Item{
private:
//weapon specific info
public:
//functions
};
或者有武器类型的枚举定义?
enum ItemType{
Weapon,
//more item types (armor, consumable, etc)
};
class Item{
private:
ItemType _itemType;
//more code
};
只是想知道哪种是最佳的实现方式,特别是如果我将来计划扩展和添加游戏!另外,如果玩家喜欢,因为玩家会拥有一个“库存”-> std :: vector <* Item> _inventory;
最好!
答案 0 :(得分:1)
我喜欢这两种选择,但情况不同。
用于处理不同项目类型的不同行为的继承机制,但是我将差异相对较小的项目组合在一起,也许用enum
来区分它们。
例如,治疗药水与剑之间存在巨大差异,但可能存在许多不同类型的治疗药水或剑,其区别仅在于对目标的治疗或伤害量。可以用string
来描述数十种不同的剑,以命名它们以及它们可以造成的一系列伤害。 “次要治疗药水”也许能恢复1至6点生命,但是“主要治疗药水”可以恢复10至60点生命。这是唯一的区别。不需要不同的代码,只是成员变量中具有不同值的不同实例。大剑比小剑(同等级,不同实例)造成更大的伤害,但烈焰剑有点燃目标的机会,因此它获得了自己的等级,可能有多个实例,大烈焰剑和小烈焰剑会造成不同的伤害并且有将目标变成活火炬的机会。
当您构建足够的虚拟函数以避免使用dynamic_cast
玩愚蠢的游戏时,继承最有用。
例如
void use(entity & on) = 0;
作为Item
虚拟函数。有了它,您可以在任何use
上Item
entity
,而无需知道它是什么。如果您在use
上调用sword
,则sword
的{{1}}实现将尝试从use
中删除运行状况。在on
上调用use
会试图将vorpal_sword
斩首并造成伤害。
在on
上调用use
,它将尝试将运行状况恢复为healing_potion
。
在on
上调用use
,它将把flux_capacitor
发送到另一个时间。祝您编码愉快。
这些选项仅限于您的想象力和编写特殊效果的能力。所有这些将只需要在主要逻辑中使用一些非常简单的代码:
on
主要逻辑不知道_inventory[index]->use(target);
是什么。它甚至不需要知道Item
是什么。它只知道它是target
上的use
项42。
现在就target
做一个注释。您可能想要
_inventory
尽可能使用smart pointers来管理对象的所有权。您并非总是想简单地指向另一个列表中的通用std::vector<std::unique_ptr<Item>> _inventory;
。以三个愿望的灯为例。阿拉丁只需要一个私有实例来跟踪他留下的愿望数量即可。