diff --git a/CMakeLists.txt b/CMakeLists.txt index fd96ef8e..70d6a98e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,34 +35,34 @@ set(SOURCES sources/Component/Keyboard/KeyboardComponent.hpp sources/Component/Health/HealthComponent.cpp sources/Component/Health/HealthComponent.hpp - sources/System/Movable/MovableSystem.hpp - sources/System/Movable/MovableSystem.cpp - sources/System/Controllable/ControllableSystem.cpp - sources/System/Controllable/ControllableSystem.hpp - sources/System/Gamepad/GamepadSystem.cpp - sources/System/Gamepad/GamepadSystem.hpp - sources/System/Health/HealthSystem.cpp - sources/System/Health/HealthSystem.hpp - sources/System/Keyboard/KeyboardSystem.cpp - sources/System/Keyboard/KeyboardSystem.hpp - sources/System/Movable/MovableSystem.cpp - sources/System/Movable/MovableSystem.hpp +# sources/System/Movable/MovableSystem.hpp +# sources/System/Movable/MovableSystem.cpp +# sources/System/Controllable/ControllableSystem.cpp +# sources/System/Controllable/ControllableSystem.hpp +# sources/System/Gamepad/GamepadSystem.cpp +# sources/System/Gamepad/GamepadSystem.hpp +# sources/System/Health/HealthSystem.cpp +# sources/System/Health/HealthSystem.hpp +# sources/System/Keyboard/KeyboardSystem.cpp +# sources/System/Keyboard/KeyboardSystem.hpp +# sources/System/Movable/MovableSystem.cpp +# sources/System/Movable/MovableSystem.hpp sources/Models/Vector3.hpp sources/Component/GridCentered/GridCenteredComponent.cpp sources/Component/GridCentered/GridCenteredComponent.hpp - sources/System/GridCentered/GridCenteredSystem.cpp - sources/System/GridCentered/GridCenteredSystem.hpp +# sources/System/GridCentered/GridCenteredSystem.cpp +# sources/System/GridCentered/GridCenteredSystem.hpp sources/Models/Vector2.hpp sources/Component/Renderer/Drawable2DComponent.hpp sources/Component/Renderer/Drawable3DComponent.hpp - sources/System/Renderer/RenderSystem.hpp - sources/System/Renderer/RenderSystem.cpp +# sources/System/Renderer/RenderSystem.hpp +# sources/System/Renderer/RenderSystem.cpp sources/Component/Renderer/CameraComponent.cpp sources/Component/Renderer/CameraComponent.hpp sources/Component/Animation/AnimationsComponent.cpp sources/Component/Animation/AnimationsComponent.hpp - sources/System/Animation/AnimationsSystem.cpp - sources/System/Animation/AnimationsSystem.hpp +# sources/System/Animation/AnimationsSystem.cpp +# sources/System/Animation/AnimationsSystem.hpp sources/Component/Collision/CollisionComponent.cpp sources/Component/Collision/CollisionComponent.hpp sources/System/Collision/CollisionSystem.hpp diff --git a/lib/wal/sources/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp index d8948f87..c4a4e9cf 100644 --- a/lib/wal/sources/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -65,6 +65,16 @@ namespace WAL return *static_cast(existing->second.get()); } + template + T *getComponentOrDefault() + { + const std::type_index &type = typeid(T); + auto existing = this->_components.find(type); + if (existing == this->_components.end()) + return nullptr; + return *static_cast(existing->second.get()); + } + //! @brief Check if this entity has a component. //! @tparam T The type of the component template diff --git a/lib/wal/sources/Scene/Scene.cpp b/lib/wal/sources/Scene/Scene.cpp index fe9fbb19..22ed03ff 100644 --- a/lib/wal/sources/Scene/Scene.cpp +++ b/lib/wal/sources/Scene/Scene.cpp @@ -26,25 +26,22 @@ namespace WAL void Scene::_componentAdded(Entity &entity, const std::type_index &type) { for (auto &view : this->_views) { - if (std::find(view->types.begin(), view->types.end(), type) == view->types.end()) + if (std::find(view->getTypes().begin(), view->getTypes().end(), type) == view->getTypes().end()) continue; - bool valid = std::all_of(view->types.begin(), view->types.end(), [&entity](const auto &type){ + bool valid = std::all_of(view->getTypes().begin(), view->getTypes().end(), [&entity](const auto &type){ return entity.hasComponent(type); }); if (valid) - view->entities.emplace_back(entity); + view->emplace_back(entity); } } void Scene::_componentRemoved(const Entity &entity, const std::type_index &type) { for (auto &view : this->_views) { - if (std::find(view->types.begin(), view->types.end(), type) == view->types.end()) + if (std::find(view->getTypes().begin(), view->getTypes().end(), type) == view->getTypes().end()) continue; - view->entities.erase(std::remove_if(view->entities.begin(), view->entities.end(), [&entity](const auto &ref) - { - return &ref.get() == &entity; - }), view->entities.end()); + view->erase(entity); } } } // namespace WAL \ No newline at end of file diff --git a/lib/wal/sources/Scene/Scene.hpp b/lib/wal/sources/Scene/Scene.hpp index be5e160b..aab47566 100644 --- a/lib/wal/sources/Scene/Scene.hpp +++ b/lib/wal/sources/Scene/Scene.hpp @@ -24,7 +24,7 @@ namespace WAL //! @brief The list of registered entities std::list _entities = {}; //! @brief The list of cached views to update. - std::vector> _views = {}; + std::vector> _views = {}; //! @brief Notify this scene that a component has been added to the given entity. //! @param entity The entity with the new component diff --git a/lib/wal/sources/System/ISystem.hpp b/lib/wal/sources/System/ISystem.hpp index be755d65..ab8dc3f3 100644 --- a/lib/wal/sources/System/ISystem.hpp +++ b/lib/wal/sources/System/ISystem.hpp @@ -15,21 +15,16 @@ namespace WAL 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 Update the whole system (every entities that this system is responsible can be updated. + //! @param dtime The delta time since the last call to this method. + virtual void update(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. + //! @brief An alternative of update 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; + virtual void fixedUpdate() = 0; //! @brief Get a view containing every entity this system should update. - virtual BaseView &getView() = 0; + virtual IView &getView() = 0; //! @brief A virtual default destructor. virtual ~ISystem() = default; diff --git a/lib/wal/sources/System/System.hpp b/lib/wal/sources/System/System.hpp index 56a5404d..c21de9d2 100644 --- a/lib/wal/sources/System/System.hpp +++ b/lib/wal/sources/System/System.hpp @@ -35,15 +35,33 @@ namespace WAL //! @brief Update the corresponding component of the given entity //! @param entity The entity to update. //! @param dtime The delta time. - void onUpdate(Entity &entity, std::chrono::nanoseconds dtime) override {} + virtual void onUpdate(ViewEntity &entity, std::chrono::nanoseconds dtime) {} //! @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. - void onFixedUpdate(Entity &entity) override {} + virtual void onFixedUpdate(ViewEntity &entity) {} //! @brief A method called after all entities that this system manage has been updated. - void onSelfUpdate() override {} + virtual void onSelfUpdate() {} + + + //! @brief Update the whole system (every entities that this system is responsible can be updated. + //! @param dtime The delta time since the last call to this method. + void update(std::chrono::nanoseconds dtime) final + { + for (auto entity : this->getView()) + this->onUpdate(entity, dtime); + this->onSelfUpdate(); + } + + //! @brief An alternative of update 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. + void fixedUpdate() final + { + for (auto entity : this->getView()) + this->onFixedUpdate(entity); + } protected: //! @brief A reference to the ECS. Wal &_wal; diff --git a/lib/wal/sources/View/View.hpp b/lib/wal/sources/View/View.hpp index 52a46294..22c02b60 100644 --- a/lib/wal/sources/View/View.hpp +++ b/lib/wal/sources/View/View.hpp @@ -13,46 +13,152 @@ namespace WAL { - //! @brief A basic view used to manipulate view without knowing their type at compile time. - class BaseView + template + class ViewEntity { + private: + std::tuple, std::reference_wrapper...> _value; public: - //! @brief The list of entities in the view. - std::vector> entities = {}; + explicit ViewEntity(std::tuple, std::reference_wrapper...> value) + : _value(value) + {} - //! @brief The list of types that every entity of the view has. - std::vector types = {}; - - size_t size() const + Entity *operator->() { - return entities.size(); + return &(std::get<0>(this->_value).get()); } + Entity &operator*() + { + return std::get<0>(this->_value); + } + + operator Entity &() + { + return std::get<0>(this->_value); + } + + template + T &get() + { + return std::get>(this->_value); + } + }; + + template + class ViewIterator + { + private: + It _it; + + public: + ViewEntity operator*() + { + ViewEntity entity(*this->_it); + return entity; + } + + ViewEntity operator->() + { + ViewEntity entity(*this->_it); + return entity; + } + + ViewIterator &operator++() + { + this->_it++; + return *this; + } + + ViewIterator operator++(int) + { + ViewIterator copy = *this; + this->_it++; + return *this; + } + + bool operator==(const ViewIterator &other) const + { + return this->_it == other._it; + } + + bool operator!=(const ViewIterator &other) const + { + return !this->operator==(other); + } + + explicit ViewIterator(It current) + : _it(current) + {} + }; + + //! @brief A basic view used to manipulate view without knowing their type at compile time. + class IView + { + public: + //! @brief The list of types that every entity of the view has. + virtual const std::vector &getTypes() const = 0; + + virtual void emplace_back(Entity &) = 0; + + virtual void erase(const Entity &) = 0; + //! @brief A default destructor - ~BaseView() = default; - protected: - //! @brief A basic view can't be constructed, you should use the View templated class. - BaseView() = default; - //! @brief A basic view can't be constructed, you should use the View templated class. - BaseView(const BaseView &) = default; - //! @brief A basic view can't be assigned. See the View template class. - BaseView &operator=(const BaseView &) = default; + virtual ~IView() = default; }; //! @brief A view allowing one to easily access entities containing a set list of component. //! A view is always updated and only references to entities are kept. template - class View : public BaseView + class View : public IView { + private: + using entity_type = std::tuple, std::reference_wrapper...>; + + //! @brief The list of entities in the view. + std::vector _entities = {}; + //! @brief The list of types that every entity of the view has. + std::vector _types = {}; public: + using iterator = ViewIterator::iterator, Components...>; + + iterator begin() + { + return iterator(this->_entities.begin()); + } + + iterator end() + { + return iterator(this->_entities.begin()); + } + + const std::vector &getTypes() const override + { + return this->_types; + } + + void emplace_back(Entity &) override + { + + } + + void erase(const Entity &) override + { + + } + //! @brief Construct a view from a list of entities. //! Those entities are never copied but references to them are kept internally. explicit View(std::list &scene) { - this->types = {typeid(Components)...}; - std::copy_if(scene.begin(), scene.end(), std::back_inserter(this->entities), [](Entity &entity) { - return (entity.hasComponent() && ...); - }); + this->_types = {typeid(Components)...}; + for (auto &entity : scene) { + auto tuple = std::make_tuple(entity, entity.getComponentOrDefault()...); + std::apply(&this->_entities.emplace_back, tuple); + } + // std::copy_if(scene.begin(), scene.end(), std::back_inserter(this->entities), [](Entity &entity) { +// return (entity.hasComponent() && ...); +// }); } //! @brief Copying a view is not possible since a view must be managed by a scene. diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 2456296a..ef138871 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -129,16 +129,11 @@ namespace WAL while (fBehind > Wal::timestep) { fBehind -= Wal::timestep; - 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(); + for (auto &system : this->_systems) + system->fixedUpdate(); } + for (auto &system : this->_systems) + system->update(dtime); callback(*this, state); } } diff --git a/sources/Map/Map.hpp b/sources/Map/Map.hpp index 177d836f..7f396b31 100644 --- a/sources/Map/Map.hpp +++ b/sources/Map/Map.hpp @@ -14,7 +14,6 @@ #include #include #include "Component/Renderer/Drawable3DComponent.hpp" -#include "System/Renderer/RenderSystem.hpp" #include "Scene/Scene.hpp" #include "Model/Model.hpp" #include "Component/Component.hpp" diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index b64a61c1..ff933fff 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -4,30 +4,30 @@ #include #include -#include "System/Movable/MovableSystem.hpp" -#include "System/Renderer/RenderSystem.hpp" +//#include "System/Movable/MovableSystem.hpp" +//#include "System/Renderer/RenderSystem.hpp" #include #include #include -#include +//#include #include -#include -#include +//#include +//#include #include #include #include #include #include -#include -#include "Models/Vector2.hpp" +//#include +//#include "Models/Vector2.hpp" #include "Component/Renderer/CameraComponent.hpp" -#include "Component/Renderer/Drawable2DComponent.hpp" +//#include "Component/Renderer/Drawable2DComponent.hpp" #include "Component/Renderer/Drawable3DComponent.hpp" #include "Runner.hpp" #include "Models/GameState.hpp" #include #include "Component/Animation/AnimationsComponent.hpp" -#include "System/Animation/AnimationsSystem.hpp" +//#include "System/Animation/AnimationsSystem.hpp" #include "Map/Map.hpp" namespace RAY2D = RAY::Drawables::Drawables2D; @@ -47,18 +47,19 @@ namespace BBM void addSystems(WAL::Wal &wal) { - wal.addSystem() - .addSystem() - .addSystem() - .addSystem() - .addSystem(); + wal.addSystem(); + // wal.addSystem() +// .addSystem() +// .addSystem() +// .addSystem() +// .addSystem(); } void enableRaylib(WAL::Wal &wal) { RAY::TraceLog::setLevel(LOG_WARNING); RAY::Window &window = RAY::Window::getInstance(600, 400, "Bomberman", FLAG_WINDOW_RESIZABLE); - wal.addSystem(window); +// wal.addSystem(window); } std::shared_ptr loadGameScene(WAL::Wal &wal) diff --git a/sources/System/Collision/CollisionSystem.cpp b/sources/System/Collision/CollisionSystem.cpp index 4c91fc45..79351729 100644 --- a/sources/System/Collision/CollisionSystem.cpp +++ b/sources/System/Collision/CollisionSystem.cpp @@ -23,20 +23,20 @@ namespace BBM return (overlapX && overlapY && overlapZ); } - void CollisionSystem::onFixedUpdate(WAL::Entity &entity) + void CollisionSystem::onFixedUpdate(WAL::ViewEntity &entity) { - auto &posA = entity.getComponent(); - auto &col = entity.getComponent(); + auto &posA = entity.get(); + auto &col = entity.get(); Vector3f position = posA.position; - if (entity.hasComponent(typeid(MovableComponent))) - position += entity.getComponent().getVelocity(); +// if (entity.hasComponent(typeid(MovableComponent))) +// position += entity.getComponent().getVelocity(); Vector3f minA = Vector3f::min(position, position + col.bound); Vector3f maxA = Vector3f::max(position, position + col.bound); - for (WAL::Entity &other : this->getView().entities) { - if (&other == &entity) + for (auto other : this->getView()) { + if (other->getUid() == entity->getUid()) continue; - auto colB = other.getComponent(); - auto posB = other.getComponent().position; + auto colB = other.get(); + auto posB = other.get().position; Vector3f minB = Vector3f::min(posB, posB + colB.bound); Vector3f maxB = Vector3f::max(posB, posB + colB.bound); if (collide(minA, maxA, minB, maxB)) { diff --git a/sources/System/Collision/CollisionSystem.hpp b/sources/System/Collision/CollisionSystem.hpp index 45ee9816..2c0f5491 100644 --- a/sources/System/Collision/CollisionSystem.hpp +++ b/sources/System/Collision/CollisionSystem.hpp @@ -10,6 +10,7 @@ #include "System/System.hpp" #include "Models/Vector3.hpp" #include "Component/Collision/CollisionComponent.hpp" +#include "Component/Position/PositionComponent.hpp" namespace BBM { @@ -18,7 +19,7 @@ namespace BBM { public: //! @inherit - void onFixedUpdate(WAL::Entity &entity) override; + void onFixedUpdate(WAL::ViewEntity &entity) override; //! @brief A default constructor explicit CollisionSystem(WAL::Wal &wal);