From 306f07972da2466130dd13e6639fe5e783be1cf7 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 4 Jun 2021 00:50:38 +0200 Subject: [PATCH] Reworking systems --- lib/wal/CMakeLists.txt | 4 +- lib/wal/sources/System/ISystem.hpp | 37 ++++++++++++++ lib/wal/sources/System/System.cpp | 28 ----------- lib/wal/sources/System/System.hpp | 34 ++++++++----- lib/wal/sources/View/View.hpp | 2 +- lib/wal/sources/Wal.cpp | 49 ------------------- lib/wal/sources/Wal.hpp | 32 ++++++------ sources/System/Collision/CollisionSystem.cpp | 6 +-- sources/System/Collision/CollisionSystem.hpp | 11 ++--- .../Controllable/ControllableSystem.cpp | 7 +-- .../Controllable/ControllableSystem.hpp | 10 ++-- sources/System/Gamepad/GamepadSystem.cpp | 7 +-- sources/System/Gamepad/GamepadSystem.hpp | 10 ++-- .../GridCentered/GridCenteredSystem.cpp | 8 +-- .../GridCentered/GridCenteredSystem.hpp | 9 ++-- sources/System/Health/HealthSystem.cpp | 6 +-- sources/System/Health/HealthSystem.hpp | 9 ++-- sources/System/Keyboard/KeyboardSystem.cpp | 7 +-- sources/System/Keyboard/KeyboardSystem.hpp | 10 ++-- sources/System/Movable/MovableSystem.cpp | 7 +-- sources/System/Movable/MovableSystem.hpp | 9 ++-- tests/CollisionTest.cpp | 4 +- 22 files changed, 129 insertions(+), 177 deletions(-) create mode 100644 lib/wal/sources/System/ISystem.hpp delete mode 100644 lib/wal/sources/System/System.cpp delete mode 100644 lib/wal/sources/Wal.cpp diff --git a/lib/wal/CMakeLists.txt b/lib/wal/CMakeLists.txt index ba2a60a0..c0aac922 100644 --- a/lib/wal/CMakeLists.txt +++ b/lib/wal/CMakeLists.txt @@ -7,7 +7,6 @@ add_library(wal sources/Entity/Entity.hpp sources/Component/Component.hpp sources/System/System.hpp - sources/Wal.cpp sources/Wal.hpp sources/Scene/Scene.cpp sources/Scene/Scene.hpp @@ -15,8 +14,7 @@ add_library(wal sources/Exception/WalError.hpp sources/Entity/Entity.cpp sources/Component/Component.cpp - sources/System/System.cpp sources/Models/Callback.hpp - sources/View/View.hpp) + sources/View/View.hpp sources/System/ISystem.hpp) target_include_directories(wal PUBLIC sources) \ No newline at end of file diff --git a/lib/wal/sources/System/ISystem.hpp b/lib/wal/sources/System/ISystem.hpp new file mode 100644 index 00000000..be755d65 --- /dev/null +++ b/lib/wal/sources/System/ISystem.hpp @@ -0,0 +1,37 @@ +// +// Created by Zoe Roux on 2021-06-04. +// + + +#pragma once + +#include "Entity/Entity.hpp" +#include "View/View.hpp" +#include + +namespace WAL +{ + //! @brief A base class that represent a system. + class ISystem + { + public: + //! @brief Update the corresponding component of the given entity + //! @param entity The entity to update. + //! @param dtime The delta time. + virtual void onUpdate(Entity &entity, std::chrono::nanoseconds dtime) = 0; + + //! @brief An alternative of onUpdate that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. + //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. + //! @param entity The entity to update. + virtual void onFixedUpdate(Entity &entity) = 0; + + //! @brief A method called after all entities that this system manage has been updated. + virtual void onSelfUpdate() = 0; + + //! @brief Get a view containing every entity this system should update. + virtual BaseView &getView() = 0; + + //! @brief A virtual default destructor. + virtual ~ISystem() = default; + }; +} \ No newline at end of file diff --git a/lib/wal/sources/System/System.cpp b/lib/wal/sources/System/System.cpp deleted file mode 100644 index 0dd69f30..00000000 --- a/lib/wal/sources/System/System.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zoe Roux on 5/17/21. -// - -#include "System.hpp" -#include -#include - -namespace WAL -{ - System::System(std::vector dependencies) - : _dependencies(std::move(dependencies)) - {} - - void System::onUpdate(Entity &entity, std::chrono::nanoseconds dtime) - {} - - void System::onFixedUpdate(Entity &entity) - {} - - void System::onSelfUpdate() - {} - - const std::vector &System::getDependencies() const - { - return this->_dependencies; - } -} // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/System/System.hpp b/lib/wal/sources/System/System.hpp index 8dc164a7..56a5404d 100644 --- a/lib/wal/sources/System/System.hpp +++ b/lib/wal/sources/System/System.hpp @@ -9,39 +9,49 @@ #include #include #include "Entity/Entity.hpp" +#include "Wal.hpp" +#include "View/View.hpp" +#include "ISystem.hpp" namespace WAL { //! @brief A base system of WAL - class System + //! @tparam Dependencies The list of dependencies this system has. + template + class System : public ISystem { - private: - //! @brief The list of dependencies of this system - std::vector _dependencies = {}; public: //! @brief A virtual, default, destructor - virtual ~System() = default; + ~System() override = default; //! @brief A system can be moved - System(System &&) = default; + System(System &&) noexcept = default; - //! @brief Get the name of the component corresponding to this system. - const std::vector &getDependencies() const; + //! @brief Get a view of all entities containing every dependencies of this system. + View &getView() override + { + return this->_wal.scene->template view(); + } //! @brief Update the corresponding component of the given entity //! @param entity The entity to update. //! @param dtime The delta time. - virtual void onUpdate(Entity &entity, std::chrono::nanoseconds dtime); + void onUpdate(Entity &entity, std::chrono::nanoseconds dtime) override {} //! @brief An alternative of onUpdate that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. //! @param entity The entity to update. - virtual void onFixedUpdate(Entity &entity); + void onFixedUpdate(Entity &entity) override {} //! @brief A method called after all entities that this system manage has been updated. - virtual void onSelfUpdate(); + void onSelfUpdate() override {} protected: + //! @brief A reference to the ECS. + Wal &_wal; + //! @brief A system can't be instantiated, it should be derived. - explicit System(std::vector dependencies); + explicit System(Wal &wal) + : _wal(wal) + {} //! @brief A system can't be instantiated, it should be derived. System(const System &) = default; //! @brief A system can't be instantiated, it should be derived. diff --git a/lib/wal/sources/View/View.hpp b/lib/wal/sources/View/View.hpp index 9df63f55..2db9e2ff 100644 --- a/lib/wal/sources/View/View.hpp +++ b/lib/wal/sources/View/View.hpp @@ -23,7 +23,7 @@ namespace WAL //! @brief The list of types that every entity of the view has. std::vector types = {}; - size_t size() + size_t size() const { return entities.size(); } diff --git a/lib/wal/sources/Wal.cpp b/lib/wal/sources/Wal.cpp deleted file mode 100644 index d4262b73..00000000 --- a/lib/wal/sources/Wal.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by Zoe Roux on 2021-05-14. -// - -#include -#include -#include "Wal.hpp" -#include "Scene/Scene.hpp" - -namespace WAL -{ - std::chrono::nanoseconds Wal::timestep = std::chrono::milliseconds(8); - - void Wal::_update(std::chrono::nanoseconds dtime) - { - auto &entities = this->scene->getEntities(); - - for (auto &system : this->_systems) { - for (auto &entity : entities) { - if (!Wal::_hasDependencies(entity, *system)) - continue; - system->onUpdate(entity, dtime); - } - system->onSelfUpdate(); - } - } - - void Wal::_fixedUpdate() - { - auto &entities = this->scene->getEntities(); - - for (auto &system : this->_systems) { - for (auto &entity : entities) { - if (!Wal::_hasDependencies(entity, *system)) - continue; - system->onFixedUpdate(entity); - } - } - } - - bool Wal::_hasDependencies(const Entity &entity, const System &system) - { - // TODO use an hashmap to cache results. - const auto &dependency = system.getDependencies(); - return std::ranges::all_of(dependency.begin(), dependency.end(), [&entity](const auto &dependency) { - return entity.hasComponent(dependency); - }); - } -} // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 7e361904..4bb9500a 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -10,7 +10,7 @@ #include #include #include "Exception/WalError.hpp" -#include "System/System.hpp" +#include "System/ISystem.hpp" #include "Models/Callback.hpp" #include "Scene/Scene.hpp" @@ -19,31 +19,22 @@ namespace WAL class Entity; class Scene; + template + class System; + //! @brief The main WAL class, it is used to setup and run the ECS. class Wal { private: //! @brief The list of registered systems - std::vector> _systems = {}; - - //! @brief Call the onUpdate of every system with every component - void _update(std::chrono::nanoseconds dtime); - - //! @brief Call the onFixedUpdate of every system with every component - void _fixedUpdate(); - - //! @brief Check if an entity met a system's dependencies. - //! @param entity The entity to check - //! @param system The system that will list dependencies - //! @return True if all dependencies are met, false otherwise. - static bool _hasDependencies(const Entity &entity, const System &system); + std::vector> _systems = {}; public: //! @brief The scene that contains entities. std::shared_ptr scene; //! @brief True if the engine should close after the end of the current tick. bool shouldClose = false; //! @brief The time between each fixed update. - static std::chrono::nanoseconds timestep; + static constexpr std::chrono::nanoseconds timestep = std::chrono::milliseconds(8); //! @brief Create a new system in place. //! @return The wal instance used to call this function is returned. This allow method chaining. @@ -132,9 +123,16 @@ namespace WAL while (fBehind > Wal::timestep) { fBehind -= Wal::timestep; - this->_fixedUpdate(); + for (auto &system : this->_systems) { + for (auto &entity : system->getView().entities) + system->onFixedUpdate(entity); + } + } + for (auto &system : this->_systems) { + for (auto &entity : system->getView().entities) + system->onUpdate(entity, dtime); + system->onSelfUpdate(); } - this->_update(dtime); callback(*this, state); } } diff --git a/sources/System/Collision/CollisionSystem.cpp b/sources/System/Collision/CollisionSystem.cpp index 6bb58d51..7561b984 100644 --- a/sources/System/Collision/CollisionSystem.cpp +++ b/sources/System/Collision/CollisionSystem.cpp @@ -11,10 +11,8 @@ namespace BBM { CollisionSystem::CollisionSystem(WAL::Wal &wal) - : WAL::System({typeid(PositionComponent), typeid(CollisionComponent)}), _wal(wal) - { - - } + : System(wal) + { } bool CollisionSystem::collide(Vector3f minA, Vector3f maxA, Vector3f minB, Vector3f maxB) { diff --git a/sources/System/Collision/CollisionSystem.hpp b/sources/System/Collision/CollisionSystem.hpp index c4c2de25..4e3961d9 100644 --- a/sources/System/Collision/CollisionSystem.hpp +++ b/sources/System/Collision/CollisionSystem.hpp @@ -12,23 +12,20 @@ namespace BBM { //! @brief A system to handle collisions. - class CollisionSystem : public WAL::System + class CollisionSystem : public WAL::System { - private: - //! @brief reference to the ECS engine to get other entities - WAL::Wal &_wal; public: //! @inherit void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - CollisionSystem(WAL::Wal &wal); + explicit CollisionSystem(WAL::Wal &wal); //! @brief A Collision system is copy constructable CollisionSystem(const CollisionSystem &) = default; //! @brief A default destructor ~CollisionSystem() override = default; - //! @brief A Collision system is assignable. - CollisionSystem &operator=(const CollisionSystem &) = default; + //! @brief A system is not assignable. + CollisionSystem &operator=(const CollisionSystem &) = delete; //! @brief check AABB collision static bool collide(Vector3f minA, Vector3f maxA, Vector3f minB, Vector3f maxB); diff --git a/sources/System/Controllable/ControllableSystem.cpp b/sources/System/Controllable/ControllableSystem.cpp index 0a9c789c..941319cf 100644 --- a/sources/System/Controllable/ControllableSystem.cpp +++ b/sources/System/Controllable/ControllableSystem.cpp @@ -12,11 +12,8 @@ namespace BBM { float ControllableSystem::speed = .25f; - ControllableSystem::ControllableSystem() - : WAL::System({ - typeid(ControllableComponent), - typeid(MovableComponent) - }) + ControllableSystem::ControllableSystem(WAL::Wal &wal) + : System(wal) {} void ControllableSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/Controllable/ControllableSystem.hpp b/sources/System/Controllable/ControllableSystem.hpp index fac4db08..45e7513a 100644 --- a/sources/System/Controllable/ControllableSystem.hpp +++ b/sources/System/Controllable/ControllableSystem.hpp @@ -5,12 +5,14 @@ #pragma once +#include "Component/Movable/MovableComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" #include "System/System.hpp" namespace BBM { //! @brief A system to handle Controllable entities. - class ControllableSystem : public WAL::System + class ControllableSystem : public WAL::System { public: //! @brief The speed applied to every controllable entities. @@ -20,12 +22,12 @@ namespace BBM void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - ControllableSystem(); + explicit ControllableSystem(WAL::Wal &wal); //! @brief A Controllable system is copy constructable ControllableSystem(const ControllableSystem &) = default; //! @brief A default destructor ~ControllableSystem() override = default; - //! @brief A Controllable system is assignable. - ControllableSystem &operator=(const ControllableSystem &) = default; + //! @brief A system is not assignable. + ControllableSystem &operator=(const ControllableSystem &) = delete; }; } diff --git a/sources/System/Gamepad/GamepadSystem.cpp b/sources/System/Gamepad/GamepadSystem.cpp index 5df6bd96..9392dc02 100644 --- a/sources/System/Gamepad/GamepadSystem.cpp +++ b/sources/System/Gamepad/GamepadSystem.cpp @@ -13,11 +13,8 @@ using Gamepad = RAY::Controller::GamePad; namespace BBM { - GamepadSystem::GamepadSystem() - : WAL::System({ - typeid(GamepadComponent), - typeid(ControllableComponent) - }) + GamepadSystem::GamepadSystem(WAL::Wal &wal) + : System(wal) {} void GamepadSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/Gamepad/GamepadSystem.hpp b/sources/System/Gamepad/GamepadSystem.hpp index 9c8c705f..8daa5e06 100644 --- a/sources/System/Gamepad/GamepadSystem.hpp +++ b/sources/System/Gamepad/GamepadSystem.hpp @@ -6,23 +6,25 @@ #include "System/System.hpp" #include +#include "Component/Gamepad/GamepadComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" namespace BBM { //! @brief A system to handle Gamepad entities. - class GamepadSystem : public WAL::System + class GamepadSystem : public WAL::System { public: //! @inherit void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - GamepadSystem(); + explicit GamepadSystem(WAL::Wal &wal); //! @brief A Gamepad system is copy constructable GamepadSystem(const GamepadSystem &) = default; //! @brief A default destructor ~GamepadSystem() override = default; - //! @brief A Gamepad system is assignable. - GamepadSystem &operator=(const GamepadSystem &) = default; + //! @brief A system is not assignable. + GamepadSystem &operator=(const GamepadSystem &) = delete; }; } diff --git a/sources/System/GridCentered/GridCenteredSystem.cpp b/sources/System/GridCentered/GridCenteredSystem.cpp index 5dcca1a9..d6337c3a 100644 --- a/sources/System/GridCentered/GridCenteredSystem.cpp +++ b/sources/System/GridCentered/GridCenteredSystem.cpp @@ -8,12 +8,8 @@ namespace BBM { - GridCenteredSystem::GridCenteredSystem() - : WAL::System({ - typeid(GridCenteredComponent), - typeid(MovableComponent), -// typeid(PositionComponent) - }) + GridCenteredSystem::GridCenteredSystem(WAL::Wal &wal) + : System(wal) {} void GridCenteredSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/GridCentered/GridCenteredSystem.hpp b/sources/System/GridCentered/GridCenteredSystem.hpp index e84e65fb..3af49ea1 100644 --- a/sources/System/GridCentered/GridCenteredSystem.hpp +++ b/sources/System/GridCentered/GridCenteredSystem.hpp @@ -5,22 +5,23 @@ #pragma once #include +#include "Component/Position/PositionComponent.hpp" namespace BBM { //! @brief The system handling GridCenteredComponent - class GridCenteredSystem : public WAL::System + class GridCenteredSystem : public WAL::System { public: void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - GridCenteredSystem(); + explicit GridCenteredSystem(WAL::Wal &wal); //! @brief A GridCenteredSystem is copyable. GridCenteredSystem(const GridCenteredSystem &) = default; //! @brief A default destructor ~GridCenteredSystem() override = default; - //! @brief A GridCenteredSystem is assignable - GridCenteredSystem &operator=(const GridCenteredSystem &) = default; + //! @brief A system is not assignable + GridCenteredSystem &operator=(const GridCenteredSystem &) = delete; }; } diff --git a/sources/System/Health/HealthSystem.cpp b/sources/System/Health/HealthSystem.cpp index 90bbfbb9..e9aaa155 100644 --- a/sources/System/Health/HealthSystem.cpp +++ b/sources/System/Health/HealthSystem.cpp @@ -10,10 +10,8 @@ namespace BBM { - HealthSystem::HealthSystem() - : WAL::System({ - typeid(HealthComponent) - }) + HealthSystem::HealthSystem(WAL::Wal &wal) + : System(wal) {} void HealthSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/Health/HealthSystem.hpp b/sources/System/Health/HealthSystem.hpp index 15ca2062..fe8bb1ab 100644 --- a/sources/System/Health/HealthSystem.hpp +++ b/sources/System/Health/HealthSystem.hpp @@ -5,24 +5,25 @@ #pragma once +#include "Component/Health/HealthComponent.hpp" #include "System/System.hpp" namespace BBM { //! @brief A system to handle Health entities. - class HealthSystem : public WAL::System + class HealthSystem : public WAL::System { public: //! @inherit void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - HealthSystem(); + explicit HealthSystem(WAL::Wal &wal); //! @brief A Health system is copy constructable HealthSystem(const HealthSystem &) = default; //! @brief A default destructor ~HealthSystem() override = default; - //! @brief A Health system is assignable. - HealthSystem &operator=(const HealthSystem &) = default; + //! @brief A system is not assignable. + HealthSystem &operator=(const HealthSystem &) = delete; }; } diff --git a/sources/System/Keyboard/KeyboardSystem.cpp b/sources/System/Keyboard/KeyboardSystem.cpp index 13ad9804..044373b4 100644 --- a/sources/System/Keyboard/KeyboardSystem.cpp +++ b/sources/System/Keyboard/KeyboardSystem.cpp @@ -14,11 +14,8 @@ using Keyboard = RAY::Controller::Keyboard; namespace BBM { - KeyboardSystem::KeyboardSystem() - : WAL::System({ - typeid(KeyboardComponent), - typeid(ControllableComponent) - }) + KeyboardSystem::KeyboardSystem(WAL::Wal &wal) + : System(wal) {} void KeyboardSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/Keyboard/KeyboardSystem.hpp b/sources/System/Keyboard/KeyboardSystem.hpp index f17c5f15..56977386 100644 --- a/sources/System/Keyboard/KeyboardSystem.hpp +++ b/sources/System/Keyboard/KeyboardSystem.hpp @@ -7,23 +7,25 @@ #include "System/System.hpp" #include +#include "Component/Keyboard/KeyboardComponent.hpp" +#include "Component/Controllable/ControllableComponent.hpp" namespace BBM { //! @brief A system to handle keyboard entities. - class KeyboardSystem : public WAL::System + class KeyboardSystem : public WAL::System { public: //! @inherit void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - KeyboardSystem(); + explicit KeyboardSystem(WAL::Wal &wal); //! @brief A keyboard system is copy constructable KeyboardSystem(const KeyboardSystem &) = default; //! @brief A default destructor ~KeyboardSystem() override = default; - //! @brief A keyboard system is assignable. - KeyboardSystem &operator=(const KeyboardSystem &) = default; + //! @brief A system is not assignable. + KeyboardSystem &operator=(const KeyboardSystem &) = delete; }; } diff --git a/sources/System/Movable/MovableSystem.cpp b/sources/System/Movable/MovableSystem.cpp index 1c439345..c6d86457 100644 --- a/sources/System/Movable/MovableSystem.cpp +++ b/sources/System/Movable/MovableSystem.cpp @@ -8,11 +8,8 @@ namespace BBM { - MovableSystem::MovableSystem() - : WAL::System({ - typeid(MovableComponent), - typeid(PositionComponent) - }) + MovableSystem::MovableSystem(WAL::Wal &wal) + : System(wal) {} void MovableSystem::onFixedUpdate(WAL::Entity &entity) diff --git a/sources/System/Movable/MovableSystem.hpp b/sources/System/Movable/MovableSystem.hpp index 51a56ea9..173bc5a8 100644 --- a/sources/System/Movable/MovableSystem.hpp +++ b/sources/System/Movable/MovableSystem.hpp @@ -5,25 +5,26 @@ #pragma once +#include "Component/Movable/MovableComponent.hpp" #include "System/System.hpp" #include "Entity/Entity.hpp" namespace BBM { //! @brief A system to handle movable entities. This system update velocity based on accelerations and positions based on velocity. - class MovableSystem : public WAL::System + class MovableSystem : public WAL::System { public: //! @inherit void onFixedUpdate(WAL::Entity &entity) override; //! @brief A default constructor - MovableSystem(); + explicit MovableSystem(WAL::Wal &wal); //! @brief A movable system is copy constructable MovableSystem(const MovableSystem &) = default; //! @brief A default destructor ~MovableSystem() override = default; - //! @brief A movable system is assignable. - MovableSystem &operator=(const MovableSystem &) = default; + //! @brief A system is not assignable. + MovableSystem &operator=(const MovableSystem &) = delete; }; } // namespace WAL diff --git a/tests/CollisionTest.cpp b/tests/CollisionTest.cpp index 447a8dbb..f869bb3e 100644 --- a/tests/CollisionTest.cpp +++ b/tests/CollisionTest.cpp @@ -20,7 +20,7 @@ using namespace BBM; TEST_CASE("Collision test", "[Component][System]") { Wal wal; - CollisionSystem collision(wal); + CollisionSystem collision(<#initializer#>, wal); wal.scene = std::make_shared(); wal.scene->addEntity("player") .addComponent() @@ -63,7 +63,7 @@ TEST_CASE("Collision test", "[Component][System]") TEST_CASE("Collsion test with movable", "[Component][System]") { Wal wal; - CollisionSystem collision(wal); + CollisionSystem collision(<#initializer#>, wal); MovableSystem movable; wal.scene = std::make_shared(); wal.scene->addEntity("player")