diff --git a/lib/wal/sources/Models/Callback.hpp b/lib/wal/sources/Models/Callback.hpp index be2c092f..dc12a18b 100644 --- a/lib/wal/sources/Models/Callback.hpp +++ b/lib/wal/sources/Models/Callback.hpp @@ -24,10 +24,14 @@ namespace WAL //! @brief Add a method to be called when this callback is invoked. //! @param callback The list of arguments of the callback method //! @return A unique ID for this callback. That can be used to remove the callback later. - int addCallback(std::function callback) + template + int addCallback(Func callback) { int id = this->_nextID++; - this->_functions[id] = std::move(callback); + if constexpr(std::is_same_v>) + this->_functions[id] = std::move(callback); + else + this->_functions[id] = std::function(callback); return id; } @@ -53,8 +57,9 @@ namespace WAL //! @brief A default assignment operator Callback &operator=(const Callback &) = default; - //! @brief Implicitly transform a function into a callback. - Callback(std::function callback) // NOLINT(google-explicit-constructor) + //! @brief Implicitly transform a callable into a callback. + template + Callback(Func callback) // NOLINT(google-explicit-constructor) { this->addCallback(callback); } diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index ef138871..f0c8dd50 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -28,6 +28,56 @@ namespace WAL private: //! @brief The list of registered systems std::vector> _systems = {}; + + //! @brief Start the game loop + //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) + //! @param state An initial game state. If not specified, it will be defaulted. + //! @tparam T A type used to track your game state. It must be default constructable. + template + void _run(const Callback &callback, T state = T()) + { + auto lastTick = std::chrono::steady_clock::now(); + std::chrono::nanoseconds fBehind(0); + + while (!this->shouldClose) { + auto now = std::chrono::steady_clock::now(); + std::chrono::nanoseconds dtime = now - lastTick; + fBehind += dtime; + lastTick = now; + + while (fBehind > Wal::timestep) { + fBehind -= Wal::timestep; + for (auto &system : this->_systems) + system->fixedUpdate(); + } + for (auto &system : this->_systems) + system->update(dtime); + callback(*this, state); + } + } + +#if defined(PLATFORM_WEB) + template + static void _runIteration(void *param) + { + static auto [wal, callback, state] = *reinterpret_cast &, T &> *>(param); + static auto lastTick = std::chrono::steady_clock::now(); + static std::chrono::nanoseconds fBehind(0); + + auto now = std::chrono::steady_clock::now(); + std::chrono::nanoseconds dtime = now - lastTick; + fBehind += dtime; + lastTick = now; + while (fBehind > Wal::timestep) { + fBehind -= Wal::timestep; + for (auto &system : wal._systems) + system->fixedUpdate(); + } + for (auto &system : wal._systems) + system->update(dtime); + callback(wal, state); + } +#endif public: //! @brief The scene that contains entities. std::shared_ptr scene; @@ -94,23 +144,6 @@ namespace WAL return *this; } - //! @brief Start the game loop - //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) - //! @param state An initial game state. If not specified, it will be defaulted. - //! @tparam T A type used to track your game state. It must be default constructable. - template - void run(const std::function &callback, T state = T()) - { - Callback update(callback); - - #if defined(PLATFORM_WEB) - std::tuple iterationParams(this, &update, &state); - return emscripten_set_main_loop_arg((em_arg_callback_func)runIteration, (void *)&iterationParams, 0, 1); - #else - return this->run(update, state); - #endif - } - //! @brief Start the game loop //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) //! @param state An initial game state. If not specified, it will be defaulted. @@ -118,50 +151,14 @@ namespace WAL template void run(const Callback &callback, T state = T()) { - auto lastTick = std::chrono::steady_clock::now(); - std::chrono::nanoseconds fBehind(0); - - while (!this->shouldClose) { - auto now = std::chrono::steady_clock::now(); - std::chrono::nanoseconds dtime = now - lastTick; - fBehind += dtime; - lastTick = now; - - while (fBehind > Wal::timestep) { - fBehind -= Wal::timestep; - for (auto &system : this->_systems) - system->fixedUpdate(); - } - for (auto &system : this->_systems) - system->update(dtime); - callback(*this, state); - } + #if defined(PLATFORM_WEB) + std::tuple &, T &> iterationParams(*this, callback, state); + return emscripten_set_main_loop_arg((em_arg_callback_func)_runIteration, (void *)&iterationParams, 0, 1); + #else + return this->_run(callback, state); + #endif } - #if defined(PLATFORM_WEB) - template - static void runIteration(void *param) - { - static auto iterationParams = reinterpret_cast *, T *> *>(param); - static const Callback callback = *((Callback *)std::get<1>(*iterationParams)); - static T *state = (T *)std::get<2>(*iterationParams); - static Wal *wal = (Wal *)std::get<0>(*iterationParams); - static auto lastTick = std::chrono::steady_clock::now(); - static std::chrono::nanoseconds fBehind(0); - - auto now = std::chrono::steady_clock::now(); - std::chrono::nanoseconds dtime = now - lastTick; - fBehind += dtime; - lastTick = now; - while (fBehind > Wal::timestep) { - fBehind -= Wal::timestep; - wal->_fixedUpdate(); - } - wal->_update(dtime); - callback(*wal, *state); - } - #endif - //! @brief A default constructor Wal() = default; //! @brief A WAL can't be copy constructed diff --git a/sources/Component/Collision/CollisionComponent.cpp b/sources/Component/Collision/CollisionComponent.cpp index 22cbdef8..df727b2d 100644 --- a/sources/Component/Collision/CollisionComponent.cpp +++ b/sources/Component/Collision/CollisionComponent.cpp @@ -16,14 +16,6 @@ namespace BBM return new CollisionComponent(entity); } - CollisionComponent::CollisionComponent(WAL::Entity &entity, std::function onCollide, std::function onCollided, Vector3f bound) - : WAL::Component(entity), onCollide(onCollide), onCollided(onCollided), bound(bound) - { } - - CollisionComponent::CollisionComponent(WAL::Entity &entity, std::function onCollide, std::function onCollided, float boundSize) - : WAL::Component(entity), onCollide(onCollide), onCollided(onCollided), bound({boundSize, boundSize, boundSize}) - { } - CollisionComponent::CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided, Vector3f bound) : WAL::Component(entity), onCollide(onCollide), onCollided(onCollided), bound(bound) { } diff --git a/sources/Component/Collision/CollisionComponent.hpp b/sources/Component/Collision/CollisionComponent.hpp index 4636c79a..5bfe7e16 100644 --- a/sources/Component/Collision/CollisionComponent.hpp +++ b/sources/Component/Collision/CollisionComponent.hpp @@ -27,12 +27,6 @@ namespace BBM //! @brief A component can't be instantiated, it should be derived. explicit CollisionComponent(WAL::Entity &entity); - //! @brief Constructor with a callback function - CollisionComponent(WAL::Entity &entity, std::function onCollide, std::function onCollided, Vector3f bound); - - //! @brief Constructor with a callback function, same boundSize for all axis - CollisionComponent(WAL::Entity &entity, std::function onCollide, std::function onCollided, float boundSize = 0); - //! @brief Constructor with a WAL::Callback CollisionComponent(WAL::Entity &entity, WAL::Callback onCollide, WAL::Callback onCollided,Vector3f bound); diff --git a/sources/System/Renderer/RenderSystem.cpp b/sources/System/Renderer/RenderSystem.cpp index 1607183e..bd6a3adc 100644 --- a/sources/System/Renderer/RenderSystem.cpp +++ b/sources/System/Renderer/RenderSystem.cpp @@ -26,26 +26,14 @@ namespace BBM this->_window.clear(); this->_window.useCamera(this->_camera); - for (auto &entity : this->_wal.scene->getEntities()) { - if (!entity.hasComponent() - || !entity.hasComponent()) - continue; - auto &drawable = entity.getComponent(); - auto &pos = entity.getComponent(); - + for (auto &[_, pos, drawable] : this->_wal.scene->view()) { drawable.drawable->setPosition(pos.position); drawable.drawable->drawOn(this->_window); } this->_window.unuseCamera(); // TODO sort entities based on the Z axis - for (auto &entity : this->_wal.scene->getEntities()) { - if (!entity.hasComponent() - || !entity.hasComponent()) - continue; - auto &drawable = entity.getComponent(); - auto &pos = entity.getComponent(); - + for (auto &[_, pos, drawable] : this->_wal.scene->view()) { drawable.drawable->setPosition(Vector2f(pos.position.x, pos.position.y)); drawable.drawable->drawOn(this->_window); }