我已经研究了很多,但我似乎找不到任何实际可行的东西,或者它是否可行。我需要的是一个对象工厂或我认为的注册表,我不知道如何,没有线程真正帮助。他们通常会使用我不熟悉的想法,因此很难遵循。
在我的例子中,我有一个名为Art
的父类和一组Art
类型的子类(例如FireBolt
)。我希望用户能够自由地将FireBolt
对象添加到他们的Arts
列表中,而无需在任何地方包含FireBolt
对象。所以只通过Art
对象,我需要一种方法来创建一个新的Art
子类并返回它。这个想法是它将像一个控制台/神模式类型的交易,用户将能够在任何给定的时间添加他们喜欢的任何东西。我知道Skyrim这样的游戏有这个ID系统,我不知道怎么做。
我试图简单地将字符串映射到Art *对象(std::map<std::string, Art*> artMap
),并使用名为regArt(std::string ID, Art* art)
的函数,但每当我尝试使用它时,它返回错误“错误:预期的构造函数,析构函数或类型转换之前'('此外,我相信这意味着每个人都会分享Art
的单一版本,而在游戏规范中,Art
可以在游戏中期改变。
请注意,我已经链接到试图解决相同问题的其他线程,但我无法让它们在我的示例中工作。对答案的很多评论只是说'这不起作用'。
一些可能无用的代码;
Art.h;
class Art {
std::string name;
int EPCost;
int castTime;
int AoESize;
std::string ID;
public:
Art(std::string n, int cp, int ct, int as):name(n), EPCost(cp), castTime(ct), AoESize(as) {}
virtual ~Art() {}
int getAoESize() {return AoESize;}
std::string getName() {return name;}
int getEPCost() {return EPCost;}
virtual int getBaseDamage() = 0;
};
FireBolt.h;
class FireBolt:public Art {
static const std::string name;
static const int EPCost;
static const int castTime;
static const int AoESize;
public:
FireBolt():Art(name, EPCost, castTime, AoESize) {}
~FireBolt() {}
int getBaseDamage();
};
因此,经过几个小时的玩游戏,我有一些可以做的事情。我不完全认为我想做的事情是可能的,或者如果它是我根本不知道如何。这就是我解决的问题。
我创建了一个名为ArtFactory
的新课程(未决定是否仅使用以下标题和源文件将其扩展到游戏中的所有内容,即设备,攻击等);
ArtFactory.h;
#include "Arts.h"
#include "FireBolt.h"
#include <functional>
class ArtFactory {
static std::map<std::string, std::function<Art*()>> artMap;
public:
ArtFactory();
static void loadArts();
static Art* getNewArt(std::string ID) {return artMap.find(ID)->second();}
static void regArt(std::string ID, std::function<Art*()> f) {artMap[ID] = f;}
};
这会将字符串(ID)映射到静态映射中的lambda函数。如果你输入正确的ID,lambda函数将简单地返回我们想要的新版本的Art
,从而允许它生成许多相同的Art
,这意味着我不是每个人都必须在任何地方初始化ArtFactory
。我需要#include我在这个文件中制作的每一件艺术品,这很不幸,但我认为这是必要的。如果没有,我会喜欢一种不需要的方式。
源文件,cpp文件;
#include "ArtFactory.h"
std::map<std::string, std::function<Art*()>> ArtFactory::artMap;
ArtFactory::ArtFactory() {
return;
}
void ArtFactory::loadArts() {
artMap["001A"] = []() -> Art* {return new FireBolt();};
}
然后展开它,只需复制loadArts中的行,并用新ID替换ID(在本例中为“001A”),并用新类替换新类(在本例中为FireBolt()
)。
我不喜欢这个,如果我在任何地方加入#include "ArtFactory.h"
,我还包括其他所有艺术品。这种方法并不能消除与其他艺术相关的需要,事实上恰恰相反。在这个游戏中,某些角色/敌人从某些艺术/攻击开始,某些物品带有这些艺术/攻击,所以包含我需要的特定艺术/攻击而不是使用这个工厂会更好。
实现控制台/神模式将会有什么用处,因为我现在可以轻松列出每个可用的艺术品和它的ID,并返回一个新的艺术。我真诚地希望这在某些方面对某人有所帮助。我被困在这个问题很长一段时间,我找不到任何好的线程。