我即将结束一个游戏编程入门课程,我想把我在课堂上学到的技能和我以前的OOP经验结合起来,创建一个小库来制作2D游戏。不过,我目前关心的是,这是管理类实例集合的最佳方法。
我使用的库(DarkGDK)完全由作用于整数的自由函数组成。当使用像dbSprite()这样的函数创建"object“时,您会给它一个唯一的ID (int值)来引用它--我猜是一种”地址“。我个人认为这种方法是对的,所以我创建了类来封装每一组免费函数,如AnimatedSprite和AnimatedSprite( DarkGDK库中的两种Sprite类型是不同的)。
问题是,为了使这些对象工作,我仍然必须向构造函数传递一个唯一的ID,以便针对适当的地址调用DarkGDK函数。我试图避免使用ID来引用这些东西,但我正在讨论如何创建对象。目前,我有一些AssetManager类保存对创建的每个对象的引用,检查现有的ID,并且只允许惟一的ID,但这仍然不能解决强制生成管理类外部ID的问题。这使我认为工厂是最好的方法。
我知道在C#中我可以创建一个AssetFactory<T> where T:Asset,它可以很容易地为每个资产调用适当的构造函数来创建实例,但据我所知,C++没有这样的工具。
所以我认为我应该采取的方法是使用某种抽象的AssetFactory。我的想法(正确与否)是,AssetFactory的子级将跟踪使用中的is,并且只发出独立对象的唯一is。就像这样:
class Asset {
int m_index;
Asset(int index);
};
class Image : public Asset {
Image(char* imgPath);
void Draw();
};
class Sprite : public Asset {
Sprite(Image* img);
void Draw();
};
class AssetFactory {
private:
std::vector<Asset*> m_assets;
int GetUniqueID();
public:
AssetFactory();
~AssetFactory();
virtual Asset* CreateAsset(); // but each class has different constructor parameters...
};
class ImageFactory : public AssetFactory {
Asset* CreateAsset(char* imgPath); // ...so this wouldn't work (nor compile)
};
class SpriteFactory : public AssetFactory {
Asset* CreateAsset(); // ...so will i be forced to call the default constructor and modify it later?
};这里的问题是,如上所述,不同的对象有不同的构造函数,这使得这个设计变得毫无意义。我应该采取不同的方法吗?还是我对工厂模式有错误的看法?
编辑:为了澄清起见,我希望为雪碧和图片分开工厂的原因是,雪碧和图像具有相同的ID是可以允许的。ID只能在相同“类型”的其他资产中是唯一的。
发布于 2011-10-13 10:27:46
如果您的库允许任意if,并且您在一个相对相等的地址空间中工作(例如,sizeof of (Int) == sizeof of(int*)),这是一个非常简单的问题,在我所知道的几乎所有32位编译器上都是如此。生成ID非常简单--只需reinterpret_cast指针即可。
class Sprite {
int GetUniqueID() { return reinterpret_cast<int>(this); } // easies
public:
// public interface
};此外,重复使用旧ID实际上可能不值得。继续做新的吧。我是说,你不会用32位整数耗尽空间的。
最后,您绝对不能在这里使用运行时继承。如果必须的话,请使用编译时混合。
发布于 2011-10-12 11:08:27
在C#有泛型的地方,C++有模板。您不能很容易地在C++中提供对泛型参数的约束,但是有一些方法可以确保只将从资产派生出来的类型作为模板参数。
为了将适当的参数传递给构造函数,可以使用可变模板方法。我现在没有编译器.稍后我将使用一个示例再次编辑,尽管您可以在堆栈溢出上找到许多其他的可变模板代码。
发布于 2011-10-12 22:38:22
也许我漏掉了什么,我不清楚你为什么不能将ID生成器移到AssetManager中,这样就可以从外部世界隐藏所有唯一ID的痛苦。
无论如何,如果您需要跟踪if,您将需要manager类,据我从您的帖子中可以看出。如果您使用工厂方法而不是工厂类,那么您刚刚到达了终点线:)剩下的唯一问题是in的处理,但是您可以在Asset类的虚拟析构函数中这样做。如果您想保持它的干净,那么您应该在管理器中为它提供一个受保护的方法,并使资产类析构函数(或一些清理函数)成为管理器的朋友。
https://stackoverflow.com/questions/7738819
复制相似问题