我一直在试图找到一种方法来实现我的简单2d格斗游戏的组件系统,我可以轻松地交换从我的系统函数返回的新组件。我的想法是我有一堆系统函数可以处理一组组件:
示例:
PosisiontComponent MovementSystem(PositionComponent pos, VelocityComponent vel)
{
//..Make entity move
return pos;
}
这里的关键是我想返回组件的新副本,而不是直接在我的系统函数中修改状态(为了更容易理解和测试系统)。理想情况下,这个新的更新位置组件然后可以通过某种类型的myFighter.Insert()
成员函数插入到我的Fighter中(其作用基本上类似于实体类)。到目前为止,我正在考虑使用std::map<int key, Component* comp>
来存储我的组件,其中键是一个唯一的id,它只与一种组件类型连接,我可以使用它来查找映射中的某些组件。战斗机类可能看起来像:
class Fighter
{
public:
void Insert(Component* comp);
Component* Get();
std::map<int, Component*> componentMap;
}
Fighter::Fighter(std::string const imageFilePath, float startPositionX, float startPositionY) :
sprite(imageFilePath, 200, 200)
{
componentMap[0] = new PositionComponent(glm::vec2{ 0.0f, 0.0f });
componentMap[1] = new VelocityComponent();
}
void Fighter::Insert(Component* component)
{
componentMap.erase(compID);
componentMap[compID)] = component;
}
Component* GetComponent()
{
return componentMap[id];
}
我遇到的问题是我不知道如何通过GetComponent()函数返回单个组件(当前只是由于类型问题的转换而导致编译器错误)与当前实现。
我的问题是:
1。)我目前的实施是否可行?有没有办法从GetComponent()函数中提取特定组件而不会遇到编译器问题?如果没有,最好的方法是轻松换掉我的Fighter类中的各个组件吗?
答案 0 :(得分:0)
假设每个实体每个类型只能有一个组件,您可以使用模板。
template<typename T>
T* getComponent() {
for (auto &component : components)
{
T* derivedComponent = dynamic_cast<T*>(component);
if (derivedComponent)
{
return derivedComponent;
}
}
return NULL;
}
然后使用它将很简单,并且不需要共享id。此外,可以在不破坏游戏的情况下更改地图的顺序。当您在运行时添加和删除组件时会发生这种情况。
Fighter* f;
PosisiontComponent* positionComponent = f->getComponent<PosisiontComponent>();
这是我过去使用的方法,它运作得非常好。但是,我建议使用智能指针而不是这些容器的原始指针。