要动态创建游戏对象,我会使用 ObjectTypeID ,这是 unsigned int ,并让它在很长的时间内进行比较 switch()声明。如果找到适当的swith case,我创建对象并存储它。因为我已经拥有90个游戏对象,所以Switch()已经很长,并且会增长到大约300个对象。
为了避免超长的switch()语句,并提高速度,完美的候选者将利用索引数组来存储所有对象类型(ObjectTypeID从0向上增加)。 有没有办法,如何在数组中存储对象类型?
我想使用这样的东西:
请问如何在我的情况下如何利用动态数组索引,以及如何避免超长的switch()语句?您的建议可能与我的想法不同,关键是使用数组索引并删除long switch()语句。
答案 0 :(得分:8)
在c ++中,类不是第一类对象,因此您无法直接执行所需的操作。但是,如果游戏对象继承自公共基类,则只需使用工厂。
class GameObject {
};
class GameObjectFactory {
public:
virtual GameObject * create() = 0;
};
class SomeGameObject : public GameObject {
};
class SomeGameObjectFactory : public GameObjectFactory {
virtual GameObject * create() { return new SomeGameObject; }
};
然后将工厂实例存储在数组中。
答案 1 :(得分:2)
创建工厂的一种更简单的方法是使用模板创建工厂方法,然后使用函数指针或boost::function
或std::function
存储它(如果它们可用)。
例如,给定对象:
#include <iostream>
struct GameObject {
virtual ~GameObject() {}
virtual void foo() const = 0;
};
struct ExampleObject : GameObject {
void foo() const { std::cout << "ExampleObject::foo\n"; }
};
我们可以使用模板来定义通用对象工厂:
template <typename Object>
GameObject* object_factory() const
{
return new Object();
};
定义一个向量来存储工厂方法的函数指针:
#include <vector>
typedef GameObject*(*factory_ptr)();
std::vector<factory_ptr> factories;
然后使用类似的东西向工厂添加一个对象:
int example_object_id = factories.size();
factories.push_back(&object_factory<ExampleObject>);
然后用以下方法创建对象:
GameObject* obj = factories[example_object_id]();
这是一个完整的例子:
#include <iostream>
#include <vector>
template <typename BaseObject>
class game_object_factory
{
template <typename Object>
static BaseObject* create_object()
{
return new Object();
};
typedef BaseObject*(*factory)();
std::vector<factory> factories;
public:
template <typename Object>
int register_type()
{
int index = factories.size();
factories.push_back(&create_object<Object>);
return index;
}
BaseObject* create(int id) const {
return factories[id]();
}
};
struct GameObject {
virtual ~GameObject() {}
virtual void foo() const = 0;
};
struct Example1 : GameObject {
void foo() const { std::cout << "Example1::foo\n"; }
};
struct Example2 : GameObject {
void foo() const { std::cout << "Example2::foo\n"; }
};
int main() {
game_object_factory<GameObject> factory;
int obj1_id = factory.register_type<Example1>();
int obj2_id = factory.register_type<Example2>();
// Should use a smart pointer here to simplify memory management.
GameObject* obj = factory.create(obj2_id);
obj->foo();
delete obj;
}
答案 2 :(得分:1)
我认为Erik给出了一个很好的答案,即使用Factory设计模式并使用Factory实例填充数组。
我唯一需要注意的是,使用ID作为数组索引会产生一些维护开销 - 您需要确保ID和数组内容匹配。当你有10个ID时很容易,当你有300个时就不那么简单了,当代码被维护了几个月或几年时,肯定不那么简单。
如果你能够在性能上受到影响(我很欣赏这可能是一个主要考虑因素)那么最好使用某种类型的地图(我将实现选择留给你!),其中数组的每个条目都包含一个ID 和其对应的工厂实例。这样,您可以逻辑地对对象进行分组,而不必以数字方式对它们进行排序,并且对象ID不需要是连续的。但无论哪种方式,工厂都是一个很好的方式。