简体   繁体   English

为我的2D C ++游戏实现组件系统

[英]Implementing a component System for my 2d C++ game

I've been trying to figure out a way to implement a component system for my simple 2d fighting game where I can easily swap in new components returned from my system functions. 我一直在尝试为简单的2D格斗游戏实现一种组件系统的方法,在该系统中,我可以轻松地交换系统功能返回的新组件。 The idea is I have a bunch of system functions which will work on a set of components: 我的想法是,我有很多系统功能可以在一组组件上运行:

example: 例:

PosisiontComponent MovementSystem(PositionComponent pos, VelocityComponent vel)
{
    //..Make entity move
   return pos;
}

The key here is I want to return a new copy of the component, and not modify the state directly in within my system function (for easier comprehension and testing of systems). 这里的关键是我想返回该组件的新副本,而不是直接在我的系统函数中修改状态(以便于理解和测试系统)。 Ideally, this new updated position component can then be inserted in my Fighter (which acts basically like an entity class) through an myFighter.Insert() member function of some sort. 理想情况下,可以通过某种myFighter.Insert()成员函数将该新更新的位置组件插入到我的Fighter中(其行为基本上像实体类)。 So far, I'm thinking of using a std::map<int key, Component* comp> to store my components with the key being a unique id that is connected with only one component type which I can use to look up certain components within the map. 到目前为止,我正在考虑使用std::map<int key, Component* comp>存储我的组件,该键是唯一的ID,仅与一种组件类型相关联,我可以使用它来查找某些组件在地图内。 The fighter class might look something like: 战斗机类可能类似于:

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];
}

The problem I'm running into is I don't quite know how I would return individual components through a GetComponent() function (currently just getting compiler errors due to conversion of type problems) with the current implementation. 我遇到的问题是我不太了解如何在当前实现中通过GetComponent()函数返回单个组件(当前由于类型问题的转换而导致编译器错误)。

My question(s) are: 我的问题是:

1.) Is my current implementation a viable solution? 1.)我当前的实施方案是否可行? Is there a way to extract specific components from GetComponent() function without getting compiler issues? 有没有一种方法可以从GetComponent()函数中提取特定组件,而不会出现编译器问题? If not, whats a better way to easily swap out individual components inside my Fighter class? 如果没有,有什么更好的方法可以轻松替换我的Fighter类中的各个组件?

Assuming each entity can only have one component per type, you could use templates. 假设每个实体每种类型只能有一个组件,则可以使用模板。

template<typename T>
T* getComponent() {
    for (auto &component : components)
    {
        T* derivedComponent = dynamic_cast<T*>(component);
        if (derivedComponent)
        {
            return derivedComponent;
        }
    }

    return NULL;
}

Then using it will be simple and it does not require an id to be shared around. 然后使用它会很简单,并且不需要共享ID。 Also the order of the map can be changed without breaking the game. 同样,可以在不中断游戏的情况下更改地图的顺序。 This is would happen as you add and remove components at runtime. 这是在运行时添加和删除组件时发生的。

Fighter* f;
PosisiontComponent* positionComponent = f->getComponent<PosisiontComponent>();

This is the approach I have used in the past and it has worked very nicely. 这是我过去使用的方法,并且效果很好。 However, I would recommend using smart pointers as opposed to raw pointers for these containers. 但是,我建议为这些容器使用智能指针,而不是原始指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM