Jump to content

  • Log In with Google      Sign In   
  • Create Account

Dominik2000

Member Since 12 Jul 2013
Offline Last Active Sep 02 2014 01:56 PM

Topics I've Started

ECS based system - Entity Manager with templates

11 August 2014 - 07:09 AM

I have an ecs based system. Every system has an update method, which will be called every frame. The components should be stored in the entity manager, so every system can get every component from the entity, which it is interested in.

 

The Entity Manager has ComponentPools which have a map with entity id and component. The ComponentPool is a template. My components have a base class, with component id and the special data type (Vector3, Vector2, ...)

 

I have three classes:

 

Component.h

#ifndef COMPONENT_H
#define COMPONENT_H

#include "datatypes.h"

#define INVALID_COMPONENT_ID 0
#define INVALID_ENTITY_ID 0

class Component
{
public:
    Component(ComponentTypeId_t componentType) : m_ComponentType(componentType), m_ComponentId(INVALID_COMPONENT_ID), m_EntityId(INVALID_ENTITY_ID) {}
    virtual ~Component() {}

    template <typename T>
    friend class ComponentPool;

    ComponentTypeId_t GetType() const { return m_ComponentType; }
    ComponentId_t GetId() const { return m_ComponentId; }
    EntityId_t GetEntity() const { return m_EntityId; }

private:
    ComponentTypeId_t m_ComponentType;
    ComponentId_t m_ComponentId;

    EntityId_t m_EntityId;
};

#endif // COMPONENT_H

ComponentPool.h

#ifndef COMPONENTPOOL_H
#define COMPONENTPOOL_H

#include "component.h"
#include "datatypes.h"

#include <algorithm>
#include <vector>

template <typename T>
class ComponentPool
{
public:
    T *GetComponent(EntityId_t entityId)
    {
        typename std::vector< T* >::iterator itr = find_if(m_Components.begin(), m_Components.end(), [entityId](T const &component) {
            return component.m_EntityId == entityId;
        });

        if(itr != m_Components.end())
        {
            return itr;
        }
        else
        {
            return NULL;
        }
    }

    bool AddComponent(T *component)
    {
        typename std::vector< T* >::iterator *itr = std::find(m_Components->begin(), m_Components->end(), component);
        if(itr == m_Components->end())
        {
            m_Components->push_back(component);
            return true;
        }
        else
        {
            return false;
        }
    }

private:

    typedef std::vector< T* > Components_t;
    Components_t *m_Components;

};

static const ComponentId_t COMPONENT_UNIQUE_ID = 0;

#endif // COMPONENTPOOL_H

My problem is the entity manager:

#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H

#include "Component/componentpool.h"
#include "Component/positioncomponent.h"
#include "datatypes.h"

class EntityManager
{
    public:
        EntityManager();
        virtual ~EntityManager();

        void Init();
        void Loop();

        void Shutdown();

        EntityId_t AddEntity();
        EntityId_t RemoveEntity(EntityId_t entityId);

        template <typename T>
        void AddComponent(EntityId_t entityId, T const &component)
        {

        }

    private:
        std::vector<ComponentPool<Component>> *m_pComponentPools; //?????
};

static const EntityId_t ENTITY_UNIQUE_ID = 0;

#endif // ENTITYMANAGER_H

How can I store all component pools easily? A vector is not a good solution, or?

I want to be very flexible, so I don't want to initialize my component pools line for line:

ComponentPool<PositionComponent> *m_pPositionComponentPool;
ComponentPool<MeshComponent> *m_pMeshComponentPool;
ComponentPool<PhysicsComponent> *m_pPhysicsComponentPool;

Another problem with this approach is, I have to use a switch command in my AddComponent method.

I think I'm thinking to complicated.

 

My goal to add a component to a entity is:

m_pComponentPools<T>->m_pComponents->addComponent(entityId);

Maybe it's the wrong way. Can anyone help me?

Thank you

Dominik


Input handling in ECS system

06 March 2014 - 03:17 AM

I ask me the question how the input managment is best implemented in an ecs system. Especially how to stop the program, when ESC is pressed.

 

The architecture is like this:

A core game class, which initializes the renderer, different systems (placement system, physics system, ...) and the entity manager, which only stores many maps of components, with an entity id. All systems take their components from the system manager, so every system has access to all components it needs. The input low level class will be initialized by the input system. On the update cycle of the input system  if an ESC click occurs, the input system, sets the game isRunning property to false.

 

Or should I initialize the input low level also in the game class and then message direct from the low level input to the game class? I don't think so because I break the layers in this way.

 

Are there any advantages in the second method? Or is my first approach ok?


Component based game and component communication

10 January 2014 - 05:33 AM

Hello,

 

I want to use a component based system in my game. It should have subsystems for logic, and every subsystem has a list of components which stores the data. 

 

The problem is: How to sync the components?

  • Should I have a pointer to another component (Movement subsystem needs position of entity, so its component has a pointer to the position component?)
  • Should I go with a observer pattern, which notifies all other (registered) subsystems, that the position of the entity has changed? Then I need a reference from the movement subsystem to the position subsystem, to get the actual position, because with the notify I only want that the notified subsystem adds a "to-be-processed" entry to it's queue. This should avoid a confuse processing of the entities.

Are there other (better?) approaches?

 

Thank you for your tips!


Component based architecture and messaging

09 September 2013 - 05:28 AM

Hello,

 

I have a component based architecture with subsystems, which hold the component data and implement the game logic. Now a great problem is, how to implement a messaging system.

 

I have a message dispatcher system, with template where every message type registers it's own eventhandler. On Dispatch every function in the list will be called. I don't like this, because it's hard to delete one listener and I don't get how a message queue could be implemented.

 

So I think of a design like that every subsystem has it's own queue and a high level system (e.g. world manager, ...) write to this queue if anything needs to be updated. One problem is, I think, that every high level system needs to know about the low level systems.

 

Is this a good approach? How do you think about coupling/decoupling, because coupling would be the case in my idea.

 

Dominik


Unique Id production

30 August 2013 - 04:26 AM

Hello,

 

I have found a code snippet in this forum, to generate unique ids for each type.

#ifndef UNQIUETYPEID_HPP
#define UNQIUETYPEID_HPP


unsigned int generateNextId()
{
    unsigned int nextId = 0;
    return ++nextId;
}


template< class T >
class UniqueTypeId
{
public:
    static unsigned int m_Id;
};


template< class T >
unsigned int UniqueTypeId<T>::m_Id = generateNextId();


#endif // UNQIUETYPEID_HPP

The error multiple definitions of generateNextId occurs. But even if I write UniqueNextId::generateNextId an error occurs. Why?

 


PARTNERS