c++architectureentity-systemcomponent-based

Entity System in C++


I've recently discover the Entity System architecture and i've got some difficulties to do it in C++ / understand implementation.

How i see Entity System :

Components : A class with attributs, set and get.

  1. Sprite
  2. Physicbody
  3. SpaceShip
  4. ...

System : A class with a list of components.

  1. List item
  2. EntityManager
  3. Renderer
  4. Input
  5. Camera
  6. ...

Entity : Just a empty class with a list of components.

What i've done :

Currently, i've got a program who allow me to do that :

// Create a new entity/
Entity* entity = game.createEntity();

// Add some components.
entity->addComponent( new TransformableComponent() )
            ->setPosition( 15, 50 )
            ->setRotation( 90 )
        ->addComponent( new PhysicComponent() )
            ->setMass( 70 )
        ->addComponent( new SpriteComponent() )
            ->setTexture( "name.png" )
            ->addToSystem( new RendererSystem() );

If I've correctly understood the EntitySystem, each System has its own list of components on which it works. (List of components or list of entity, that is the question)

class Component;

/////////////////////////////////////////////////
/// \brief  An abstract system. (Interface)
///
/////////////////////////////////////////////////
class System
{
public:

    /////////////////////////////////////////////////
    /// \brief Call when process is created.
    ///
    /////////////////////////////////////////////////
    virtual bool start() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is updated.
    ///
    /////////////////////////////////////////////////   
    virtual void update() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is removed.
    ///
    /////////////////////////////////////////////////
    virtual void end() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is removed.
    ///
    /////////////////////////////////////////////////
    virtual void addComponent( Component* component )
    {
        elements.push_back( component );
    }

protected:

    std::vector<Component*> elements;

};

(I'had put the code in .h just for fast debug ^^)

The problem

I want add a "T" Component in a System with a list of X components

What i've tried :

std::vector<Component*> elements;

But i want something like that :

std::vector<T*> elements;

My System class is abstract. My System childrens class needs to have this list with is own type.

Solution :

I've tried to put my System class has a template class, so i've just to do : class Renderer : System

But my SystemManager doesn't like this code : std::vector<System> systems.

System class with T type :

template<class T>
class System
{
public:

    /////////////////////////////////////////////////
    /// \brief Call when process is created.
    ///
    /////////////////////////////////////////////////
    virtual bool start() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is updated.
    ///
    /////////////////////////////////////////////////   
    virtual void update() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is removed.
    ///
    /////////////////////////////////////////////////
    virtual void end() = 0;

    /////////////////////////////////////////////////
    /// \brief Call when process is removed.
    ///
    /////////////////////////////////////////////////
    virtual void addComponent( T* component )
    {
        elements.push_back( component );
    }

protected:

    std::vector<T*> elements;

};

SystemManager code :

class System;

class SystemManager
{
public:

    /////////////////////////////////////////////////
    /// \brief Default constructor.
    ///
    /////////////////////////////////////////////////
    SystemManager();

    /////////////////////////////////////////////////
    /// \brief Call when system is created.
    /// \param system A system to add.
    ///
    /////////////////////////////////////////////////
    bool addSystem( System* system);

    /////////////////////////////////////////////////
    /// \brief Call when system is updated.
    ///
    /////////////////////////////////////////////////
    void update();

    /////////////////////////////////////////////////
    /// \brief Call when system is removed.
    /// \param system A system to remove.
    ///
    /////////////////////////////////////////////////
    void removeSystem( System* system );

private:

    std::vector<System*> systemList;

};

With this, i've got this error in my SystemManager : "Redefinition of 'System' as different kind of symbol" (Pointing on the line "class System" in the SystemManager)

Did you have a solution for this problem ? Did my EntitySystem approch is good ?

Thanks!


Solution

  • In your code System is a template, later in the System manager class you try to use System as if it were not a template. This will not work. You need to either specify the type, make system manager a template and pass the type parameter through to system, or not have system be a template. Also forward declaring templates, as a non template no less, isn't going to work. Take a step back and figure out how templates work in C++.

    Further more http://gamedev.stackexchange.com has many questions and answers about entity component designs, you might find it useful.