我正在为2D游戏引擎编写实体组件系统,该引擎使用可变参数模板来构建游戏对象。这是对象类,它只是所有组件的容器。我删除了无关的东西。
template<class ... Components>
class Object : public Components...{
public:
Object(Game* game) : Components(game)...{
}
};
组件由对象继承,但我试图找到检查这些组件类型的最佳方法,以便它们可以正确地相互通信。例如,Physics组件将包含对象的更新位置。 Drawable组件需要获得该位置,以便可以在世界中的正确位置绘制。我想向Object添加一个更新函数,用于更新每个组件并传输现有组件之间可以/需要传输的任何信息。
答案 0 :(得分:0)
多态性就是你想要的。 简单地制作这样的所有组件:
public Object
{
enum TYPE{
COMPONENT,,
GAMEOBJECT,
ETC,,,
};
Object(TYPE id){m_id = id;}
protected:
TYPE m_id;
virtual void Update(void) = 0;
virtual void Render(void) = 0;
public:
void GetTypeOf(void)const{return m_id;}
};
class Component : Object
{
enum COMPONENT_TYPE
{
COLLIDER,
RENDERER,
ETC,,,,
};
Component() : Object (COMPONENT){/**/}
virtual void Update(void){return;}
virtual void Render(void){return;}
};
class BoxCollider : Component
{
BoxCollider(void) : Component(BOXCOLLIDER){/**/}
void Update(void)
{
//to do
}
void Render(void)
{
//to do
}
};
然后你可以简单地拥有Object *或Component *的数据结构 你可以通过这种方式迭代:
std::vector<Component*>::iterator components = ComponentVector.begin();
for(;components != ComponentVector.end() ; ++components)
{
*(component)->Update();
*(component)->Render();
std::cout << "id" << *component->getTypeOf() << std::endl;
}
答案 1 :(得分:0)
Object
类继承其所有Components
,这意味着实际上 所有组件。
您可以使用此信息来设计update
方法
举个例子:
#include <cassert>
struct Game { };
struct Physics {
int position{0};
Physics(Game *) { }
void update(void *) { }
};
struct Drawable {
Drawable(Game *) { }
void update(Physics *physics) {
physics->position = 42;
}
};
template<class ... Components>
class Object: public Components... {
public:
Object(Game* game) : Components(game)... { }
void update() {
int a[] = { (Components::update(this), 0)... };
}
};
int main() {
Game game;
Object<Physics, Drawable> object{&game};
assert(object.position == 0);
object.update();
assert(object.position == 42);
}
您可以看到Drawable
在调用Physics
方法时收到update
。
该解决方案的缺点是:
update
方法必须获得指针参数,即使它们不需要引用任何其他组件。update
方法的参数,要么强制转换void *
。