简体   繁体   中英

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. 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. 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. 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.

My question(s) are:

1.) Is my current implementation a viable solution? Is there a way to extract specific components from GetComponent() function without getting compiler issues? If not, whats a better way to easily swap out individual components inside my Fighter class?

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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