From 35937f1e76402d25fce180c0519bef6ce77769fe Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Fri, 4 May 2018 18:37:00 +0100 Subject: Improving ECS and adding documentation. --- yage/entity/README.md | 36 ++++++++++++++++++++++++++++++++++++ yage/entity/componentmanager.h | 17 +++++++++++++++++ yage/entity/engine.cpp | 14 +++++++++++--- yage/entity/engine.h | 14 ++++++++------ yage/entity/entity.h | 21 --------------------- yage/entity/entitymanager.cpp | 3 +-- yage/entity/entitymanager.h | 11 ++++++++--- yage/entity/space.cpp | 7 +++++++ yage/entity/space.h | 12 +++++++++++- yage/entity/system.h | 3 ++- 10 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 yage/entity/README.md create mode 100644 yage/entity/componentmanager.h delete mode 100644 yage/entity/entity.h (limited to 'yage/entity') diff --git a/yage/entity/README.md b/yage/entity/README.md new file mode 100644 index 00000000..ebf539f3 --- /dev/null +++ b/yage/entity/README.md @@ -0,0 +1,36 @@ +# Entity Component System (ECS) + +## Structure + +### Entity + +The `EntityManager` is the class that manages the entities, by allocating and +deleting them as necessary. The `Entity` itself is just a handle, and does not +contain any logic or data. It is just used to refer to the `Entity` when doing +operations on it. + +### Components + +These are just data that is associated with Entities, and it gets processed +by the Systems when these are updated. The systems only process a few components +at once, which separates the logic and makes it easy to develop the Systems and +Components orthogonally. + +### Systems + +These process the Components and update their state. This completely separates +the data from the logic, and means that they can be tested independently. New +systems can be created by inheriting from the `BaseSystem`, which provides an +interface which then enables that system to be added to the main `Engine` +through different types of `Spaces`. + +## Implementation + +The Entity is just an `unsigned int`, which has a `typedef` called `Entity`, +which is also what all the functions return. + +The link between the components are managed by a templated `ComponentMapper` +class, that links every entity with it's component. This way it is also to find +out if an entity is part of a specific component, and that entity will never be +processed in the system that only targets that component, which makes it much +more efficient. diff --git a/yage/entity/componentmanager.h b/yage/entity/componentmanager.h new file mode 100644 index 00000000..fa1096e7 --- /dev/null +++ b/yage/entity/componentmanager.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "entitymanager.h" + +namespace yage +{ + +template +class ComponentMapper +{ +private: + std::map map_; +}; + +} // namespace yage diff --git a/yage/entity/engine.cpp b/yage/entity/engine.cpp index 503dc919..f3a056db 100644 --- a/yage/entity/engine.cpp +++ b/yage/entity/engine.cpp @@ -8,20 +8,28 @@ #include "engine.h" +#include "../core/core.h" + #include "space.h" -#include "entity.h" namespace yage { +Engine::~Engine() +{ + quit(); +} + void Engine::init() { + yage::init(); window_.create("Game Engine", 800, 640); } void Engine::mainLoop() { while (!window_.shouldClose()) { + window_.pollEvents(); window_.clearBuffer(); update(); @@ -32,8 +40,8 @@ void Engine::mainLoop() void Engine::update() { - for(auto &space : spaces_) { - + for (auto &space : spaces_) { + space->update(); } } diff --git a/yage/entity/engine.h b/yage/entity/engine.h index fe7e5eb0..bac32fe0 100644 --- a/yage/entity/engine.h +++ b/yage/entity/engine.h @@ -6,11 +6,12 @@ * ---------------------------------------------------------------------------- */ -#ifndef YAGE_CORE_ENGINE_H -#define YAGE_CORE_ENGINE_H +#pragma once #include "system.h" + #include "../core/window.h" +#include "../util/noncopyable.h" #include #include @@ -24,9 +25,12 @@ class Space; * Main engine class that contains a systems, the main loop and the update * function that updates all the systems. */ -class Engine +class Engine : public NonCopyable { public: + + ~Engine(); + /// Initialize window and other aspects of the engine. void init(); @@ -41,7 +45,7 @@ public: /// Returns the instance of the engine, as there is only one instance of the /// engine. - static Engine &instance(); + static Engine& instance(); private: /// Window @@ -52,5 +56,3 @@ private: }; } // namespace yage - -#endif diff --git a/yage/entity/entity.h b/yage/entity/entity.h deleted file mode 100644 index 9ba0d46d..00000000 --- a/yage/entity/entity.h +++ /dev/null @@ -1,21 +0,0 @@ -/** --------------------------------------------------------------------------- - * @file: entity.h - * - * Copyright (c) 2017 Yann Herklotz Grave - * MIT License, see LICENSE file for more details. - * ---------------------------------------------------------------------------- - */ - -#ifndef YAGE_ENGINE_ENTITY_H -#define YAGE_ENGINE_ENTITY_H - -#include - -namespace yage -{ - -typedef unsigned int Entity; - -} // namespace yage - -#endif diff --git a/yage/entity/entitymanager.cpp b/yage/entity/entitymanager.cpp index 5eb17075..205eec30 100644 --- a/yage/entity/entitymanager.cpp +++ b/yage/entity/entitymanager.cpp @@ -13,8 +13,7 @@ namespace yage EntityManager::EntityManager(Space *space) : space_(space) {} -EntityManager::EntityManager(Space *space, std::size_t n) - : space_(space) +EntityManager::EntityManager(Space *space, std::size_t n) : space_(space) { entities_.reserve(n); } diff --git a/yage/entity/entitymanager.h b/yage/entity/entitymanager.h index 85ad9051..2de5e13c 100644 --- a/yage/entity/entitymanager.h +++ b/yage/entity/entitymanager.h @@ -9,8 +9,6 @@ #ifndef YAGE_ENGINE_ENTITYMANAGER_H #define YAGE_ENGINE_ENTITYMANAGER_H -#include "entity.h" - #include namespace yage @@ -18,6 +16,8 @@ namespace yage class Space; +typedef unsigned int Entity; + /** * Manages entities in a space. */ @@ -51,7 +51,12 @@ public: * * @return The handle to the entity that was created in the space. */ - unsigned createEntity(); + Entity createEntity(); + + /** + * Delete an entity. + */ + void deleteEntity(Entity entity); private: /** diff --git a/yage/entity/space.cpp b/yage/entity/space.cpp index f3e343b5..24afda72 100644 --- a/yage/entity/space.cpp +++ b/yage/entity/space.cpp @@ -18,4 +18,11 @@ unsigned Space::createEntity() return em_.createEntity(); } +void Space::update() +{ + for (auto &system : systems_) { + system->update(); + } +} + } // namespace yage diff --git a/yage/entity/space.h b/yage/entity/space.h index 969ef503..113110aa 100644 --- a/yage/entity/space.h +++ b/yage/entity/space.h @@ -42,7 +42,12 @@ public: * visible to the user, as the user only needs to worry about the * handle when referring to the Entity and changing it. */ - unsigned createEntity(); + Entity createEntity(); + + /** + * Update all the systems. + */ + void update(); private: /** @@ -58,6 +63,11 @@ private: * current space. */ EntityManager em_; + + /** + * Manages all the components + */ + // ComponentManager cm_; }; } // namespace yage diff --git a/yage/entity/system.h b/yage/entity/system.h index 15845390..0ca50009 100644 --- a/yage/entity/system.h +++ b/yage/entity/system.h @@ -19,7 +19,8 @@ namespace yage class System : public NonCopyable { public: - + virtual void init() = 0; + virtual void update() = 0; }; } // namespace yage -- cgit