Entity Component System (ECS)#

Files ECS.hpp and ECS.cpp contain the implementation of the basis of the Entity Component System (ECS). This includes the definition of the base Entity, Component and Manager classes.

The Manager class handles the updating, rendering and deletion of Entities. Entities are grouped according to the groups defined in the group_labels enum, and groups are rendered in order. The addition of the entity to a group must be done manually.

Note

As of now, an Entity can be part of multiple groups, which may lead to repetitive rendering of the same Entity. Manager::render could eventually be changed so this won’t happen.

Entities contain Components, which define things like their positioning, their sprites and animations, how they handle keyboard inputs etc.

Note

The order in which components are updated may be sometimes important. They are now updated in the order that the components were added to the entity. For example:

/* In this code, component Transform will be updated before its
Sprite, which will be updated before its KeyboardController.*/
player.addComponent<Transform>();
player.addComponent<Sprite>("player1");
player.addComponent<KeyboardController>();
player.add_group(PLAYER_GROUP);

Typedefs

using ComponentID = std::size_t#
using Group = std::size_t#
using ComponentBitSet = std::bitset<max_components>#

Used for checking if an Entity has a given Component.

using GroupBitSet = std::bitset<max_groups>#

Used for checking if an Entity is part of a group.

using ComponentArray = std::array<Component*, max_components>#

Array of Component pointers.

Enums

enum EntityGroup#

Enumerator for groups of entities (cannot be an enum class because its values are used in std::size_t dependant functions):

Values:

enumerator MAP_GROUP#
enumerator COLLIDER_GROUP#
enumerator TEMPORARY_GROUP#
enumerator PLAYER_GROUP#
enumerator ATTACK_GROUP#

Functions

inline ComponentID getNewComponentTypeID()#

Function for generating a new ID when a new Component is defined. This function is only called in getComponentTypeID, if the Component hasn’t yet been assigned an ID. This is done by using a static variable, which is incremented everytime this function is called.

template<typename T>
inline ComponentID getComponentTypeID() noexcept#

Returns the ID of the passed Component. This is done by using a template, specifying the Component type, and a static variable so that the function remembers the ID from one call to the next.

Variables

constexpr ComponentID max_components = 32#

Max amount of components an entity is capable of holding.

constexpr Group max_groups = 32#

Max. number of groups (layers).

class Component#
#include <ECS.hpp>

Definition of the generic component class, which will be subsequently used for other specific ones (see Components.hpp).

Subclassed by Collider, Cooldown, Damage, Health, KeyboardController, MouseController, Sprite, Transform, UILabel

Public Functions

inline virtual void init()#
inline virtual void update()#

Component initialization. This is called in Entity::addComponent and should have no arguments.

inline virtual void render()#

Update function (called every game tick).

inline virtual ~Component()#

Rendering (called every game tick).

inline bool is_active()#
inline void destroy()#

Public Members

Entity *entity#

Pointer to the Entity it is associated to.

Protected Attributes

bool active = true#
class Entity#
#include <ECS.hpp>

Definition of the generic Entity class.

Subclassed by Player, Projectile, TempEntity

Public Functions

Entity(Manager &user_manager, std::string mName)#
inline virtual ~Entity()#
void refresh()#
inline virtual void update()#

Default update function: updates each component.

inline virtual void render()#

Default render function: renders each component.

template<typename T>
inline bool has_component() const#

Returns whether the Entity has a given Component.

Template Parameters:

T – A Component type.

inline bool has_group(Group group)#

Returns whether the Entity is part of a given group.

template<typename T, typename ...TArgs>
T &addComponent(TArgs&&... mArgs)#

Function for adding a component T to the Entity (defined in the end of ECS.hpp).

Template Parameters:
  • T – A Component type.

  • Targs – The types of parameters mArgs (this must be defined in the template so we can have a generic definition in the function).

Parameters:

mArgs – T’s constructor arguments.

template<typename T>
T &getComponent() const#

Function for getting one of the Entity’s components (defined in the end of ECS.hpp).

Template Parameters:

T – A Component type.

void add_group(std::size_t group)#

Function for adding the Entity to a group. This will call the Entity’s manager’s Manager::add_to_group function. Because of this, this function is defined in ECS.cpp (because it requires full definition of the Manager class, and declaring outside Entity’s definition cause a linker “duplicate symbols” error).

inline void del_group(std::size_t group)#
inline std::string get_name()#
inline void set_name(std::string mName)#
inline bool is_active() const#
inline virtual void destroy()#

Destroys the Entity by setting “active” member to false. The Entity’s Manager will then delete it.

Public Members

Manager &manager#

Reference to the manager the entity it is attached to.

std::string name#

A name to identify the entity Used to decide whether to delete an entity or not at each game tick. This is handled in Manager::refresh.

std::vector<std::unique_ptr<Component>> components#

Vector of the Entity’s Components (as unique pointers). Entries are emplaced in the order they are added to the entity.

ComponentArray component_array#

Array of components that the entity has. Here, entry k corresponds to the Component with type ID k (see getComponentTypeID function).

ComponentBitSet component_bitset#

Bitset array containing information of which Component types the entity has.

GroupBitSet group_bitset#

Bitset array containing information of which groups the entity is part of.

Protected Attributes

bool active = true#
class Manager#
#include <ECS.hpp>

This class serves to manage groups of entities in the game at each frame. It will delete entities that are not active.

Subclassed by TileMap

Public Functions

inline std::shared_ptr<Entity> &addEntity(std::string mName = "None")#

Function for adding an entity to the entity_vector by creating a new pointer.

inline std::shared_ptr<Entity> &addEntity(Entity *e)#

Instead, add an existing entity to the entity_vector.

inline std::shared_ptr<Entity> &addEntity(const std::shared_ptr<Entity> sh_ptr)#
inline void add_to_group(Entity *entity, std::size_t group)#

Add an entity to a group. This is called by Entity’s Entity::add_group. It shouldn’t be called directly.

inline std::vector<Entity*> &get_group(Group group)#

Function for getting the vector of entities in a group.

inline void update()#

Function for updating every entity in the Manager::entity_vector.

inline void render()#

Function for rendering every entity in the entity_vector. This is done group by group, in the order defined in the group_labels enum.

void refresh()#

Checks for inactive Entity’s and delete them. Defined in ECS.cpp because it is long.

inline virtual ~Manager()#

Public Members

std::vector<std::shared_ptr<Entity>> entity_vector#

Vector of entities. We define it as a shared pointer because we want Game::camera_ref_entity to be a weak pointer of a given entity, which requires it to be a shared_ptr. We don’t want to share its ownership, though.

std::array<std::vector<Entity*>, max_groups> grouped_entities#

Array of vectors for each group.