2017-08-11 83 views
0

我一直在想办法为我的简单2d格斗游戏实现一个组件系统,在这里我可以轻松地交换从我的系统函数返回的新组件。这个想法是我有一堆的系统功能,这将在一组部件的工作:为我的2d C++游戏实现组件系统

例如:

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返回单个组件(功能(目前刚刚起步,由于转换编译器错误类型问题)与当前的实现。

我的问题(S)是:

1)是我目前的执行可行的解决方案?有没有办法从GetComponent()函数中提取特定的组件而不会发生编译器问题?如果没有,最好的方法是更换我的Fighter类中的单个组件。

回答

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>(); 

这是我过去使用的方法,它的工作原理非常好。但是,我会建议使用智能指针而不是这些容器的原始指针。

+0

感谢您的建议!但是,让我问你,鉴于getcomp调用的频率,dynamic_cast效果的性能呢? – Jason

+0

@Jason是的,它的确,动态演员阵容很多,但速度很快。它会影响性能。 – skypjack