Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Dominik2000

Member Since 12 Jul 2013
Offline Last Active Jan 17 2015 12:27 PM

Topics I've Started

Movement system low or high level in ecs design

04 January 2015 - 01:51 PM

Hello,

 

sorry for writing so many ECS related topics, but as I'm programming, I come over more and more problems...

 

My architecture has an entity manager and a system manager, the entity manager manages all entities (entities are only ids), and every component has it's component pool which gives the component for the id back.

The system manager has all systems (render system, audio system,...).

 

Then I have an additional class scene manager, which, for example, creates the scene in the beginning of the game. The scene manager routes all work to the render system, he told the render system to create an entity with the given mesh, on the given position and so on.

And here I have my question, most of the articles say, that the movement system is a system. In my opinion, systems are low level classes, and managers (or how the will ever be named) are high level. The movement system moves my entities, that means, the movement system checks the velocity component and the position component of the entity, and moves the position of the entity by the given velocity, and told the render manager that the entity is moved. That means for me, that the movement system is not a system but a manager (it's high level, because it has nothing to do with the rendering of the entity).

 

Or should all systems knows the entity manager and the renderer checks all positions of the entities and moves them? But also then, the movement system is high level.

 

Is the ecs architecture combining high level and low level systems? This really is hard to solve for me, I know, that there is no given ECS way to go, but you have much more knowledge of this pattern I think.

 

Thank you!

Dominik


ComponentPools problem

19 December 2014 - 04:49 AM

I have a simple entity manager with pointers to my component pools. My components are simple POC structs. My component pool is a template class.

 

Components:

#ifndef COMPONENTS_H
#define COMPONENTS_H

#include "Datatypes/vector3.h"

enum MESH_TYPE
{
    STATIC_GROUND_MESH,
    ANIMATED_MESH
};

typedef struct
{
    Vector3 position;
    Vector3 rotation;
} SpatialComponent;

typedef struct
{
    float farClipping;
    Vector3 target;
} CameraComponent;

typedef struct
{
    MESH_TYPE type;
    std::string name;
} MeshComponent;

typedef struct
{
    Vector3 translate;
    Vector3 rotate;
} MovementComponent;
#endif // COMPONENTS_H

ComponentPool:

#ifndef COMPONENTPOOL_H
#define COMPONENTPOOL_H

#include "components.h"
#include "datatypes.h"

#include <boost/container/flat_map.hpp>
#include <algorithm>
#include <vector>
#include <iostream>
#include <climits>
#include <typeinfo>

class ComponentPoolBase
{

};

template <typename T>
class ComponentPool : public ComponentPoolBase, public boost::container::flat_map< EntityId, T >
{
    typedef boost::container::flat_map< EntityId, T > Components_t;

public:
    ComponentPool()
    {
    }

    T& Get(const EntityId& entityId)
    {
        return this->at(entityId);
    }

    int Size()
    {
        return this->size();
    }

    bool Has(EntityId entityId)
    {
        typename Components_t::iterator itr = this->find(entityId);

        if(itr == this->end())
        {
            return false;
        }

        return true;
    }

    bool Add(EntityId entityId)
    {
        try
        {
            this->insert(boost::container::container_detail::pair< EntityId, T >(entityId, T()));

            std::cout << "New component entity id: " << entityId << " Type: " << typeid(T).name() << std::endl;
            std::cout << "Count: " << this->size() << std::endl;
            return true;
        }
        catch (std::exception& ex)
        {
            std::cout << "Exception: " << ex.what() << std::endl;
        }

        return false;
    }

    bool Remove(EntityId entityId)
    {
        try
        {
            this[entityId] = NULL;

            std::cout << "Delete component entity id: " << entityId << " Type: " << typeid(T).name() << std::endl;
            return true;
        }
        catch (std::exception& ex)
        {
            std::cout << "Exception: " << ex.what() << std::endl;
        }

        return false;
    }
};

#endif // COMPONENTPOOL_H

EntityManager:

#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H

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

#include <iostream>
#include <queue>

class EntityManager
{
    typedef std::queue< EntityId > EntityList_t;

public:
    EntityManager();
    ~EntityManager();

    void Init();
    void Shutdown();

    EntityId CreateEntity(const std::string& name);
    void DestroyEntity(EntityId entityId);

    EntityId GetCreatedEntities();
    EntityId GetRemovedEntities();

    ComponentPool<SpatialComponent>* m_pSpatialComponents;
    ComponentPool<CameraComponent>* m_pCameraComponents;
    ComponentPool<MeshComponent>* m_pMeshComponents;
    ComponentPool<MovementComponent>* m_pMovementComponents;

private:
    EntityList_t* m_pCreatedEntities;
    EntityList_t* m_pRemovedEntities;



    EntityId getNextId()
    {
        return ++s_NextId;
    }

    static EntityId s_NextId;
};

#endif // ENTITYMANAGER_H

My great problem, are the pointers to the ComponentPool. I want to store this in a vector with unique pointer, because the entity manager is the only one, who is responsible for the lifetime of my entites and components.

 

I thought it should be this way:

std::vector<std::unique_ptr<ComponentPool<ComponentPoolBase*>>> m_ComponentPools;

And I add a unique pointer this way:

m_ComponentPools.push_back(std::unique_ptr<ComponentPool<SpatialComponent>>(new ComponentPool<SpatialComponent>()));

But this doesn't work with a not matching function error in the compiler. Why?

 

Is there a better solution to implement this component pool and entity manager?


Pathfinding AI in an ECS game

15 December 2014 - 02:52 PM

Hello,

 

when I have an ECS system, where the entities are only ids, the components PODs and the systems (in my case managers, because systems are low level) have all the logic.

How can I implement Pathfinding. My thought is, that I have a component PathfindingComponent, where some points are defined, where the vehicle (as example) can drive. That means, if I have a straight street, I have 2 points, the begin and the end of the street piece, in my PathfindingComponent.

If a street is added to the scene, my PathfindingManager will be notified, and see there is a component, and add the point from the component to his store. Now the AI comes in say, the vehicle have to drive to a specified street tile, and add a new waypoint (the entity id) to the WaypointComponent of the vehicle. The pathfinding now knows, where to drive an can look for a path.

Is this ok? Are there any errors in my thinking?

 

One problem occurs I think: What if I have a street tile which has parking slots. One for a bus and 4 for cars. These 5 points are also in the pathfinding system, but now, the AI cannot say, drive to the street tile with the entity id, the AI have to say where exactly on the street tile. How can this be solved? Are the parking slots saved in an array in another component, or should the AI exactly say where to drive?

 

I hope it is clear, what I mean, if not, ask and I will try to describe it better.

 

Dominik


Camera movement in input system or not

11 December 2014 - 02:18 AM

I have a component based system. For camera I have a camera component (clipping range, ...) and a position component. There is a input sytem also, which converts the input to a key enum from my engine, and routes the input to the different key input handlers. For every action I have a handler. The handler checks in its queue, if a specific button is pressed (maybe with a modifier) and calls a function in a class through std::bind.

 

Now my question should I move the camera (edit position component) directly in the input system (input handler recognises W key -> MESSAGE::MOVE_CAMERA_FORWARD -> move function in input system will be called with MESSAGE::MOVE_CAMERA_FORWARD), or should this be a completly different system (movement system)? A movement system is responsible to move other entities too, so I need it anyway, or?

 

Thanks

Dominik


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


PARTNERS