Skip to content

Commit

Permalink
EntityManager - Entity Component System
Browse files Browse the repository at this point in the history
Added Entity Manager on the Engine ECS

ECS Refactoring
  • Loading branch information
Berags committed May 4, 2022
1 parent 6523292 commit 3d8c257
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 11 deletions.
16 changes: 15 additions & 1 deletion include/engine/ecs/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,35 @@
namespace Engine::ECS {
class Entity {
public:
using id_t = unsigned int;
using id_t = uint32_t;

// Explicitly deleted public constructor so that an Entity
// can only be created from its Factory Method
Entity() = delete;

// Entity Factory Method
// Generates its own id
static Entity create() {
static id_t currentId = 0;
return Entity{currentId++};
}

// Adds a component to the Entity components vector
// Checks if the same component is already stored
void addComponent(Engine::ECS::IComponent *component);

// Removes a component to the Entity components vector
// Checks if the component is actually stored
void removeComponent(Engine::ECS::IComponent *component);

// Updates all the components stored into components vector
// Calls onUpdate on each component stored into components vector
void update(float dt);

// Destroys the Entity
// Calls onDestroy on each component stored into components vector
void destroy();

[[nodiscard]] id_t getId() const;

private:
Expand Down
45 changes: 45 additions & 0 deletions include/engine/ecs/EntityManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Created by Jacopo Beragnoli on 04/05/22.
//

#ifndef MINIMINIMOTORWAYS_ENTITYMANAGER_H
#define MINIMINIMOTORWAYS_ENTITYMANAGER_H

#include <unordered_map>
#include "Entity.h"
#include "../FrameInfo.h"

namespace Engine::ECS {
class EntityManager {
public:
using Map = std::unordered_map<Engine::ECS::Entity::id_t, Engine::ECS::Entity>;
static constexpr uint32_t MAX_ENTITIES = 64;

// Creates a new Entity and adds it to availableEntities Map
// Checks if number of living entities is greater than MAX_ENTITIES
// and asserts if true
Engine::ECS::Entity createNewEntity();

// Destroys an Entity from availableEntities Map
// Calls onDestroy method on all Entity components
// Updates numberOfLivingEntities to match availableEntities size
void destroyEntity(Engine::ECS::Entity::id_t id);

// Returns an Entity from a given id
Engine::ECS::Entity &getEntity(Engine::ECS::Entity::id_t id);

// Updates all Entities stored in availableEntities
// i.e. calls method update() on each entity
void updateEntities(Engine::FrameInfo &frameInfo);

private:
// Stores all living Entities
Engine::ECS::EntityManager::Map availableEntities{};

// Number of living Entities, should always match availableEntities size
uint32_t livingEntityCount{};
};
}


#endif //MINIMINIMOTORWAYS_ENTITYMANAGER_H
18 changes: 10 additions & 8 deletions include/engine/ecs/IComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
namespace Engine::ECS {
class IComponent {
public:
virtual void onCreate() = 0; // Only called one time when dt == 0
// On Create Method
// Is called when a Component is created and added to an Entity
virtual void onCreate() = 0;

virtual void onUpdate(float dt) {
if (equals(dt, .0f)) onCreate();
}
// On Update Method
// Is called on each frame and updates the Component related to an Entity
virtual void onUpdate(float dt) = 0;

private:
static bool equals(float a, float b) {
return fabs(a - b) <= ((fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * std::numeric_limits<double>::epsilon());
}
// On Destroy Method
// Is called whenever a Component is removed from an Entity or whenever an
// Entity is destroyed
virtual void onDestroy() = 0;
};
}

Expand Down
8 changes: 6 additions & 2 deletions include/engine/ecs/TestComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ namespace Engine::ECS {
class TestComponent : public Engine::ECS::IComponent {
public:
void onCreate() override {
std::cout << "On Create function" << std::endl;
std::cout << "On Create method" << std::endl;
}

void onUpdate(float dt) override {
IComponent::onUpdate(dt);
std::cout << "On Update method" << std::endl;
}

void onDestroy() override {
std::cout << "On destroy method" << std::endl;
}
};
}
Expand Down
6 changes: 6 additions & 0 deletions src/engine/ecs/Entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@ namespace Engine::ECS {
id_t Entity::getId() const {
return id;
}

void Entity::destroy() {
std::for_each(components.begin(), components.end(), [&](const auto &item) {
item->onDestroy();
});
}
}

37 changes: 37 additions & 0 deletions src/engine/ecs/EntityManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Created by Jacopo Beragnoli on 04/05/22.
//

#include "../../../include/engine/ecs/EntityManager.h"

namespace Engine::ECS {
Engine::ECS::Entity EntityManager::createNewEntity() {
assert(livingEntityCount < Engine::ECS::EntityManager::MAX_ENTITIES && "Too many entities!");

auto entity = Engine::ECS::Entity::create();
availableEntities.emplace(livingEntityCount, entity);
livingEntityCount++;
return entity;
}

void EntityManager::destroyEntity(Engine::ECS::Entity::id_t id) {
assert(id < Engine::ECS::EntityManager::MAX_ENTITIES && "Entity out of range!");

availableEntities.at(id).destroy();
availableEntities.erase(id);
livingEntityCount--;
}

Engine::ECS::Entity &EntityManager::getEntity(Engine::ECS::Entity::id_t id) {
assert(id < Engine::ECS::EntityManager::MAX_ENTITIES && "Entity out of range!");

return availableEntities.at(id);
}

void EntityManager::updateEntities(Engine::FrameInfo &frameInfo) {
std::for_each(availableEntities.begin(), availableEntities.end(), [&](auto &item) {
auto &entity = item.second;
entity.update(frameInfo.frameTime);
});
}
}

0 comments on commit 3d8c257

Please sign in to comment.