From a73ff31b67faa7e6a922cfb5598f56f80bc01d62 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 7 Dec 2024 14:19:16 +0100 Subject: added loopTimer and eventManager to mediator and removed the singletons --- src/crepe/manager/LoopTimerManager.h | 133 +++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/crepe/manager/LoopTimerManager.h (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h new file mode 100644 index 0000000..dba0f66 --- /dev/null +++ b/src/crepe/manager/LoopTimerManager.h @@ -0,0 +1,133 @@ +#pragma once + +#include +#include "../manager/Manager.h" +namespace crepe { + +class LoopTimerManager : public Manager { +public: + LoopTimerManager(Mediator & mediator); + /** + * \brief Get the current delta time for the current frame. + * + * \return Delta time in seconds since the last frame. + */ + double get_delta_time() const; + + /** + * \brief Get the current game time. + * + * \note The current game time may vary from real-world elapsed time. It is the cumulative + * sum of each frame's delta time. + * + * \return Elapsed game time in seconds. + */ + double get_current_time() const; + + /** + * \brief Set the target frames per second (FPS). + * + * \param fps The desired frames rendered per second. + */ + void set_target_fps(int fps); + + /** + * \brief Get the current frames per second (FPS). + * + * \return Current FPS. + */ + int get_fps() const; + + /** + * \brief Get the current time scale. + * + * \return The current time scale, where 0 = paused, 1 = normal speed, and values > 1 speed + * up the game. + */ + double get_time_scale() const; + + /** + * \brief Set the time scale. + * + * \param game_scale The desired time scale (0 = pause, 1 = normal speed, > 1 = speed up). + */ + void set_time_scale(double game_scale); + +private: + friend class LoopManager; + + /** + * \brief Start the loop timer. + * + * Initializes the timer to begin tracking frame times. + */ + void start(); + /** + * \brief Enforce the frame rate limit. + * + * Ensures that the game loop does not exceed the target FPS by delaying frame updates as + * necessary. + */ + void enforce_frame_rate(); + + /** + * \brief Get the fixed delta time for consistent updates. + * + * Fixed delta time is used for operations that require uniform time steps, such as physics + * calculations. + * + * \return Fixed delta time in seconds. + */ + double get_fixed_delta_time() const; + + /** + * \brief Get the accumulated lag in the game loop. + * + * Lag represents the difference between the target frame time and the actual frame time, + * useful for managing fixed update intervals. + * + * \return Accumulated lag in seconds. + */ + double get_lag() const; + + /** + * \brief Update the timer to the current frame. + * + * Calculates and updates the delta time for the current frame and adds it to the cumulative + * game time. + */ + void update(); + + /** + * \brief Advance the game loop by a fixed update interval. + * + * This method progresses the game state by a consistent, fixed time step, allowing for + * stable updates independent of frame rate fluctuations. + */ + void advance_fixed_update(); + +private: + //! Target frames per second + int target_fps = 50; + //! Actual frames per second + int actual_fps = 0; + //! Current game scale + double game_scale = 1; + //! Maximum delta time in seconds to avoid large jumps + std::chrono::duration maximum_delta_time{0.25}; + //! Delta time for the current frame in seconds + std::chrono::duration delta_time{0.0}; + //! Target time per frame in seconds + std::chrono::duration frame_target_time + = std::chrono::duration(1.0) / target_fps; + //! Fixed delta time for fixed updates in seconds + std::chrono::duration fixed_delta_time = std::chrono::duration(1.0) / 50.0; + //! Total elapsed game time in seconds + std::chrono::duration elapsed_time{0.0}; + //! Total elapsed time for fixed updates in seconds + std::chrono::duration elapsed_fixed_time{0.0}; + //! Time of the last frame + std::chrono::steady_clock::time_point last_frame_time; +}; + +} // namespace crepe -- cgit v1.2.3 From a06ea7d18008d0859818f7e8fd3e595e7dd05772 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 7 Dec 2024 14:44:46 +0100 Subject: changed looptimerManager doxygen --- src/crepe/manager/LoopTimerManager.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index dba0f66..fee6310 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -1,9 +1,19 @@ #pragma once #include -#include "../manager/Manager.h" + +#include "Manager.h" + namespace crepe { +/** + * \brief Manages timing and frame rate for the game loop. + * + * The LoopTimerManager class is responsible for calculating and managing timing functions + * such as delta time, frames per second (FPS), fixed time steps, and time scaling. It ensures + * consistent frame updates and supports game loop operations, such as handling fixed updates + * for physics and other time-sensitive operations. + */ class LoopTimerManager : public Manager { public: LoopTimerManager(Mediator & mediator); @@ -49,6 +59,8 @@ public: /** * \brief Set the time scale. * + * time_scale is a value that changes the delta time that can be retrieved using get_delta_time function. + * * \param game_scale The desired time scale (0 = pause, 1 = normal speed, > 1 = speed up). */ void set_time_scale(double game_scale); -- cgit v1.2.3 From f05458cdbf68e8efe1ed812f57e957921921941d Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 7 Dec 2024 14:51:12 +0100 Subject: more doxygen changes --- src/crepe/api/LoopManager.cpp | 1 - src/crepe/api/LoopManager.h | 9 +++++---- src/crepe/manager/LoopTimerManager.cpp | 6 +++--- src/crepe/manager/LoopTimerManager.h | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 69cbfaf..42a1e77 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,4 +1,3 @@ -#include #include "../facade/SDLContext.h" #include "../manager/EventManager.h" diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 00f5409..d07ef66 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -94,13 +94,14 @@ private: ComponentManager component_manager{mediator}; //! Scene manager instance SceneManager scene_manager{mediator}; - - //! SDL context \todo no more singletons! - SDLContext & sdl_context = SDLContext::get_instance(); - //! LoopTimer instance + //! LoopTimerManager instance LoopTimerManager loop_timer{mediator}; //! EventManager instance EventManager event_manager{mediator}; + + //! SDL context \todo no more singletons! + SDLContext & sdl_context = SDLContext::get_instance(); + private: /** diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 8156c6d..2379fdd 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -38,7 +38,7 @@ void LoopTimerManager::update() { this->last_frame_time = current_frame_time; } -double LoopTimerManager::get_delta_time() const { return this->delta_time.count() * this->game_scale; } +double LoopTimerManager::get_delta_time() const { return this->delta_time.count() * this->time_scale; } double LoopTimerManager::get_current_time() const { return this->elapsed_time.count(); } @@ -54,9 +54,9 @@ void LoopTimerManager::set_target_fps(int fps) { int LoopTimerManager::get_fps() const { return this->actual_fps; } -void LoopTimerManager::set_time_scale(double value) { this->game_scale = value; } +void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; } -double LoopTimerManager::get_time_scale() const { return this->game_scale; } +double LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { auto current_frame_time = std::chrono::steady_clock::now(); auto frame_duration = current_frame_time - this->last_frame_time; diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index fee6310..cd05bf2 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -51,7 +51,7 @@ public: /** * \brief Get the current time scale. * - * \return The current time scale, where 0 = paused, 1 = normal speed, and values > 1 speed + * \return The current time scale, where (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). * up the game. */ double get_time_scale() const; @@ -61,9 +61,9 @@ public: * * time_scale is a value that changes the delta time that can be retrieved using get_delta_time function. * - * \param game_scale The desired time scale (0 = pause, 1 = normal speed, > 1 = speed up). + * \param time_scale The desired time scale (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). */ - void set_time_scale(double game_scale); + void set_time_scale(double time_scale); private: friend class LoopManager; @@ -123,8 +123,8 @@ private: int target_fps = 50; //! Actual frames per second int actual_fps = 0; - //! Current game scale - double game_scale = 1; + //! time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) + double time_scale = 1; //! Maximum delta time in seconds to avoid large jumps std::chrono::duration maximum_delta_time{0.25}; //! Delta time for the current frame in seconds -- cgit v1.2.3 From cc1b36f4f0a20695bcfc5c16c853cb32312fe70c Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sun, 8 Dec 2024 17:32:11 +0100 Subject: added scaled fixed delta time --- src/crepe/api/LoopManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.cpp | 7 ++++++ src/crepe/manager/LoopTimerManager.h | 42 ++++++++++++++++++++++++---------- src/test/LoopManagerTest.cpp | 22 ++++++++++++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 4d97e16..d17aee1 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -48,7 +48,7 @@ void LoopManager::loop() { while (game_running) { this->loop_timer.update(); - while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { + while (this->loop_timer.get_lag() >= this->loop_timer.get_scaled_fixed_delta_time()) { this->process_input(); this->fixed_update(); this->loop_timer.advance_fixed_update(); diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index e30b90d..5d4545f 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -82,3 +82,10 @@ void LoopTimerManager::enforce_frame_rate() { double LoopTimerManager::get_lag() const { return (this->elapsed_time - this->elapsed_fixed_time).count(); } +double LoopTimerManager::get_scaled_fixed_delta_time() const{ + return this->fixed_delta_time.count() * this->time_scale; +} +void LoopTimerManager::set_fixed_delta_time(int seconds) { + this->fixed_delta_time = std::chrono::duration(seconds); +} + diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index cd05bf2..8fb4461 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -65,6 +65,35 @@ public: */ void set_time_scale(double time_scale); + /** + * \brief Get the scaled fixed delta time om seconds. + * + * The fixed delta time is used for operations that require uniform time steps, + * such as physics calculations, and is scaled by the current time scale. + * + * \return The fixed delta time, scaled by time scale, in seconds. + */ + double get_scaled_fixed_delta_time() const; + + /** + * \brief Get the fixed delta time in seconds without scaling by the time scale. + * + * This value is used in the LoopManager to determine how many times + * the fixed_update should be called within a given interval. + * + * \return The unscaled fixed delta time in seconds. + */ + double get_fixed_delta_time() const; + + /** + * \brief Set the fixed_delta_time in seconds. + * + * \param ms fixed_delta_time in seconds. + * + * The fixed_delta_time value is used to determine how many times per second the fixed_update and process_input functions are called. + */ + void set_fixed_delta_time(int seconds); + private: friend class LoopManager; @@ -81,17 +110,6 @@ private: * necessary. */ void enforce_frame_rate(); - - /** - * \brief Get the fixed delta time for consistent updates. - * - * Fixed delta time is used for operations that require uniform time steps, such as physics - * calculations. - * - * \return Fixed delta time in seconds. - */ - double get_fixed_delta_time() const; - /** * \brief Get the accumulated lag in the game loop. * @@ -123,7 +141,7 @@ private: int target_fps = 50; //! Actual frames per second int actual_fps = 0; - //! time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) + //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) double time_scale = 1; //! Maximum delta time in seconds to avoid large jumps std::chrono::duration maximum_delta_time{0.25}; diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp index f73605e..55ccbb3 100644 --- a/src/test/LoopManagerTest.cpp +++ b/src/test/LoopManagerTest.cpp @@ -45,6 +45,28 @@ TEST_F(LoopManagerTest, FixedUpdate) { // Test finished } +TEST_F(LoopManagerTest, ScaledFixedUpdate) { + // Arrange + test_loop.loop_timer.set_target_fps(60); + + // Set expectations for the mock calls + EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60)); + EXPECT_CALL(test_loop, update).Times(::testing::Exactly(60)); + EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); + + // Start the loop in a separate thread + std::thread loop_thread([&]() { test_loop.start(); }); + + // Let the loop run for exactly 1 second + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Stop the game loop + test_loop.game_running = false; + // Wait for the loop thread to finish + loop_thread.join(); + + // Test finished +} TEST_F(LoopManagerTest, ShutDown) { // Arrange test_loop.loop_timer.set_target_fps(60); -- cgit v1.2.3 From 77be74d880675c548417c7ff5af17e1785c62e05 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 9 Dec 2024 09:41:33 +0100 Subject: changed some function names --- src/crepe/api/LoopManager.cpp | 7 ++++--- src/crepe/api/LoopManager.h | 9 +-------- src/crepe/manager/LoopTimerManager.cpp | 10 +++++----- src/crepe/manager/LoopTimerManager.h | 2 +- src/test/LoopManagerTest.cpp | 8 ++++---- 5 files changed, 15 insertions(+), 21 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 922e66b..f588d7f 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -48,13 +48,13 @@ void LoopManager::loop() { while (game_running) { this->loop_timer.update(); - while (this->loop_timer.get_lag() >= this->loop_timer.get_scaled_fixed_delta_time()) { + while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_loop_interval()) { this->process_input(); this->fixed_update(); this->loop_timer.advance_fixed_update(); } - this->update(); + this->frame_update(); this->render(); this->loop_timer.enforce_frame_rate(); } @@ -72,9 +72,10 @@ void LoopManager::render() { this->get_system().update(); this->get_system().update(); } + bool LoopManager::on_shutdown(const ShutDownEvent & e) { this->game_running = false; return false; } -void LoopManager::update() {} +void LoopManager::frame_update() {} diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 6b2e857..f94cea1 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -63,14 +63,7 @@ private: * * Updates the game state based on the elapsed time since the last frame. */ - virtual void update(); - - /** - * \brief Late update which is called after update(). - * - * This function can be used for final adjustments before rendering. - */ - void late_update(); + virtual void frame_update(); /** * \brief Fixed update executed at a fixed rate. diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 9d9897d..9c77785 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -48,10 +48,6 @@ void LoopTimerManager::advance_fixed_update() { this->elapsed_fixed_time += this->fixed_delta_time; } -double LoopTimerManager::get_fixed_delta_time() const { - return this->fixed_delta_time.count(); -} - void LoopTimerManager::set_target_fps(int fps) { this->target_fps = fps; // target time per frame in seconds @@ -82,9 +78,13 @@ void LoopTimerManager::enforce_frame_rate() { double LoopTimerManager::get_lag() const { return (this->elapsed_time - this->elapsed_fixed_time).count(); } -double LoopTimerManager::get_scaled_fixed_delta_time() const { +double LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time.count() * this->time_scale; } void LoopTimerManager::set_fixed_delta_time(int seconds) { this->fixed_delta_time = std::chrono::duration(seconds); } + +double LoopTimerManager::get_fixed_loop_interval() const { + return this->fixed_delta_time.count(); +} diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 8fb4461..84178eb 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -73,7 +73,7 @@ public: * * \return The fixed delta time, scaled by time scale, in seconds. */ - double get_scaled_fixed_delta_time() const; + double get_fixed_loop_interval() const; /** * \brief Get the fixed delta time in seconds without scaling by the time scale. diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp index 55ccbb3..c44ebda 100644 --- a/src/test/LoopManagerTest.cpp +++ b/src/test/LoopManagerTest.cpp @@ -15,7 +15,7 @@ protected: class TestGameLoop : public crepe::LoopManager { public: MOCK_METHOD(void, fixed_update, (), (override)); - MOCK_METHOD(void, update, (), (override)); + MOCK_METHOD(void, frame_update, (), (override)); MOCK_METHOD(void, render, (), (override)); }; @@ -29,7 +29,7 @@ TEST_F(LoopManagerTest, FixedUpdate) { // Set expectations for the mock calls EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60)); - EXPECT_CALL(test_loop, update).Times(::testing::Exactly(60)); + EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); // Start the loop in a separate thread @@ -51,7 +51,7 @@ TEST_F(LoopManagerTest, ScaledFixedUpdate) { // Set expectations for the mock calls EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60)); - EXPECT_CALL(test_loop, update).Times(::testing::Exactly(60)); + EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); // Start the loop in a separate thread @@ -72,7 +72,7 @@ TEST_F(LoopManagerTest, ShutDown) { test_loop.loop_timer.set_target_fps(60); EXPECT_CALL(test_loop, render).Times(::testing::AtLeast(1)); - EXPECT_CALL(test_loop, update).Times(::testing::AtLeast(1)); + EXPECT_CALL(test_loop, frame_update).Times(::testing::AtLeast(1)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::AtLeast(1)); // Start the loop in a separate thread std::thread loop_thread([&]() { test_loop.start(); }); -- cgit v1.2.3 From e7d90aa34ebb5898785d8432e01f25c5b03d021b Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 9 Dec 2024 17:13:37 +0100 Subject: removed white line and standard target fps = 60 --- src/crepe/api/LoopManager.cpp | 1 - src/crepe/manager/LoopTimerManager.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 464dab9..de249ec 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,5 +1,4 @@ #include "../facade/SDLContext.h" - #include "../manager/EventManager.h" #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 84178eb..8fc69ed 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -138,7 +138,7 @@ private: private: //! Target frames per second - int target_fps = 50; + int target_fps = 60; //! Actual frames per second int actual_fps = 0; //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) -- cgit v1.2.3 From fa2d728d847e5aa29859c8cf72d8ee8df363373e Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 9 Dec 2024 17:25:50 +0100 Subject: added doxygens --- src/crepe/manager/EventManager.h | 3 +++ src/crepe/manager/LoopTimerManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.h | 12 ++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/EventManager.h b/src/crepe/manager/EventManager.h index ba55edf..639e37f 100644 --- a/src/crepe/manager/EventManager.h +++ b/src/crepe/manager/EventManager.h @@ -33,6 +33,9 @@ typedef size_t event_channel_t; class EventManager : public Manager { public: static constexpr const event_channel_t CHANNEL_ALL = -1; + /** + * \param mediator A reference to a Mediator object used for transfering managers. + */ EventManager(Mediator & mediator); /** * \brief Subscribe to a specific event type. diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 9c77785..597b214 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -81,7 +81,7 @@ double LoopTimerManager::get_lag() const { double LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time.count() * this->time_scale; } -void LoopTimerManager::set_fixed_delta_time(int seconds) { +void LoopTimerManager::set_fixed_delta_time(double seconds) { this->fixed_delta_time = std::chrono::duration(seconds); } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 8fc69ed..77674b4 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -16,7 +16,10 @@ namespace crepe { */ class LoopTimerManager : public Manager { public: - LoopTimerManager(Mediator & mediator); + /** + * \param mediator A reference to a Mediator object used for transfering managers. + */ + LoopTimerManager(Mediator &mediator); /** * \brief Get the current delta time for the current frame. * @@ -66,7 +69,7 @@ public: void set_time_scale(double time_scale); /** - * \brief Get the scaled fixed delta time om seconds. + * \brief Get the scaled fixed delta time in seconds. * * The fixed delta time is used for operations that require uniform time steps, * such as physics calculations, and is scaled by the current time scale. @@ -88,13 +91,14 @@ public: /** * \brief Set the fixed_delta_time in seconds. * - * \param ms fixed_delta_time in seconds. + * \param seconds fixed_delta_time in seconds. * * The fixed_delta_time value is used to determine how many times per second the fixed_update and process_input functions are called. */ - void set_fixed_delta_time(int seconds); + void set_fixed_delta_time(double seconds); private: + //! Friend relation to use start,enforce_frame_rate,get_lag,update,advance_fixed_update. friend class LoopManager; /** -- cgit v1.2.3 From 2c1f7df48bfd1ea87912826c4faa39a18e936146 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 9 Dec 2024 17:29:09 +0100 Subject: switched doxygen --- src/crepe/manager/LoopTimerManager.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 77674b4..5a9eda8 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -69,22 +69,22 @@ public: void set_time_scale(double time_scale); /** - * \brief Get the scaled fixed delta time in seconds. + * \brief Get the fixed delta time in seconds without scaling by the time scale. * - * The fixed delta time is used for operations that require uniform time steps, - * such as physics calculations, and is scaled by the current time scale. + * This value is used in the LoopManager to determine how many times + * the fixed_update should be called within a given interval. * - * \return The fixed delta time, scaled by time scale, in seconds. + * \return The unscaled fixed delta time in seconds. */ double get_fixed_loop_interval() const; /** - * \brief Get the fixed delta time in seconds without scaling by the time scale. + * \brief Get the scaled fixed delta time in seconds. * - * This value is used in the LoopManager to determine how many times - * the fixed_update should be called within a given interval. + * The fixed delta time is used for operations that require uniform time steps, + * such as physics calculations, and is scaled by the current time scale. * - * \return The unscaled fixed delta time in seconds. + * \return The fixed delta time, scaled by time scale, in seconds. */ double get_fixed_delta_time() const; -- cgit v1.2.3 From fb3edf33aedc1b0c37c3f74a5eaac05bf48f491a Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 10 Dec 2024 10:19:49 +0100 Subject: clarified doxygen and changed function name --- src/crepe/api/LoopManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.h | 28 +++++++++++++++++----------- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 9bb2183..492b982 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -47,7 +47,7 @@ void LoopManager::loop() { while (game_running) { this->loop_timer.update(); - while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_loop_interval()) { + while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { this->process_input(); this->fixed_update(); this->loop_timer.advance_fixed_update(); diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 366d48a..d2e40fe 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -92,6 +92,6 @@ void LoopTimerManager::set_fixed_delta_time(double seconds) { this->fixed_delta_time = std::chrono::duration(seconds); } -double LoopTimerManager::get_fixed_loop_interval() const { +double LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time.count(); } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 5a9eda8..46a0dcb 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -22,7 +22,10 @@ public: LoopTimerManager(Mediator &mediator); /** * \brief Get the current delta time for the current frame. - * + * + * This value represents the estimated frame duration of the current frame. + * This value can be used in the frame_update to convert pixel based values to time based values. + * * \return Delta time in seconds since the last frame. */ double get_delta_time() const; @@ -73,19 +76,10 @@ public: * * This value is used in the LoopManager to determine how many times * the fixed_update should be called within a given interval. + * This value is also the timing value which is used in the fixed_loop to convert pixels to time. * * \return The unscaled fixed delta time in seconds. */ - double get_fixed_loop_interval() const; - - /** - * \brief Get the scaled fixed delta time in seconds. - * - * The fixed delta time is used for operations that require uniform time steps, - * such as physics calculations, and is scaled by the current time scale. - * - * \return The fixed delta time, scaled by time scale, in seconds. - */ double get_fixed_delta_time() const; /** @@ -94,9 +88,21 @@ public: * \param seconds fixed_delta_time in seconds. * * The fixed_delta_time value is used to determine how many times per second the fixed_update and process_input functions are called. + * This value is also the timing value which is used in the fixed_loop to convert pixels to time. */ void set_fixed_delta_time(double seconds); + /** + * \brief Retrieves the scaled fixed delta time in seconds. + * + * The scaled fixed delta time is the timing value used within the `fixed_update` function. + * It is adjusted by the time_scale to account for any changes in the simulation's + * speed. + * + * \return The fixed delta time, scaled by the current time scale, in seconds. + */ + double get_scaled_fixed_delta_time() const; + private: //! Friend relation to use start,enforce_frame_rate,get_lag,update,advance_fixed_update. friend class LoopManager; -- cgit v1.2.3 From 3cf434961be522dc94e91e52361af15e370406c0 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 10 Dec 2024 13:47:44 +0100 Subject: feedback changes --- src/crepe/api/LoopManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.cpp | 14 ++++++++------ src/crepe/manager/LoopTimerManager.h | 9 +++++---- 3 files changed, 14 insertions(+), 11 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 492b982..6ebf280 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -50,7 +50,7 @@ void LoopManager::loop() { while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { this->process_input(); this->fixed_update(); - this->loop_timer.advance_fixed_update(); + this->loop_timer.advance_fixed_elapsed_time(); } this->frame_update(); diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index d2e40fe..057a18e 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -47,7 +47,7 @@ double LoopTimerManager::get_delta_time() const { double LoopTimerManager::get_current_time() const { return this->elapsed_time.count(); } -void LoopTimerManager::advance_fixed_update() { +void LoopTimerManager::advance_fixed_elapsed_time() { this->elapsed_fixed_time += this->fixed_delta_time; } @@ -68,13 +68,15 @@ void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; double LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { - auto current_frame_time = std::chrono::steady_clock::now(); - auto frame_duration = current_frame_time - this->last_frame_time; + std::chrono::steady_clock::time_point current_frame_time = std::chrono::steady_clock::now(); + std::chrono::duration frame_duration = current_frame_time - this->last_frame_time; + // Check if frame duration is less than the target frame time if (frame_duration < this->frame_target_time) { - auto delay_time = std::chrono::duration_cast( - this->frame_target_time - frame_duration); + std::chrono::microseconds delay_time = std::chrono::duration_cast( + this->frame_target_time - frame_duration); + if (delay_time.count() > 0) { std::this_thread::sleep_for(delay_time); @@ -85,7 +87,7 @@ void LoopTimerManager::enforce_frame_rate() { double LoopTimerManager::get_lag() const { return (this->elapsed_time - this->elapsed_fixed_time).count(); } -double LoopTimerManager::get_fixed_delta_time() const { +double LoopTimerManager::get_scaled_fixed_delta_time() const { return this->fixed_delta_time.count() * this->time_scale; } void LoopTimerManager::set_fixed_delta_time(double seconds) { diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 46a0dcb..9336520 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -139,12 +139,13 @@ private: void update(); /** - * \brief Advance the game loop by a fixed update interval. + * \brief Progress the elapsed fixed time by the fixed delta time interval. * - * This method progresses the game state by a consistent, fixed time step, allowing for - * stable updates independent of frame rate fluctuations. + * This method advances the game's fixed update loop by adding the fixed_delta_time + * to elapsed_fixed_time, ensuring the fixed update catches up with the elapsed time. */ - void advance_fixed_update(); + void advance_fixed_elapsed_time(); + private: //! Target frames per second -- cgit v1.2.3 From 4ea6ea704ba59f0d56718e1ed903f49ca250ab5d Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 10 Dec 2024 13:48:06 +0100 Subject: make format --- src/crepe/api/LoopManager.cpp | 4 +--- src/crepe/manager/LoopTimerManager.cpp | 15 ++++++++------- src/crepe/manager/LoopTimerManager.h | 3 +-- 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 6ebf280..46a7635 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -77,6 +77,4 @@ bool LoopManager::on_shutdown(const ShutDownEvent & e) { return false; } -void LoopManager::frame_update() { - this->scene_manager.load_next_scene(); -} +void LoopManager::frame_update() { this->scene_manager.load_next_scene(); } diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 057a18e..e57ec6f 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -23,7 +23,8 @@ void LoopTimerManager::start() { } void LoopTimerManager::update() { - std::chrono::steady_clock::time_point current_frame_time = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point current_frame_time + = std::chrono::steady_clock::now(); // Convert to duration in seconds for delta time this->delta_time = std::chrono::duration_cast>( current_frame_time - last_frame_time); @@ -54,7 +55,7 @@ void LoopTimerManager::advance_fixed_elapsed_time() { void LoopTimerManager::set_target_fps(int fps) { this->target_fps = fps; //check if fps is lower or equals 0 - if(fps <= 0){ + if (fps <= 0) { return; } // target time per frame in seconds @@ -68,15 +69,15 @@ void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; double LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { - std::chrono::steady_clock::time_point current_frame_time = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point current_frame_time + = std::chrono::steady_clock::now(); std::chrono::duration frame_duration = current_frame_time - this->last_frame_time; - // Check if frame duration is less than the target frame time if (frame_duration < this->frame_target_time) { - std::chrono::microseconds delay_time = std::chrono::duration_cast( - this->frame_target_time - frame_duration); - + std::chrono::microseconds delay_time + = std::chrono::duration_cast(this->frame_target_time + - frame_duration); if (delay_time.count() > 0) { std::this_thread::sleep_for(delay_time); diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 9336520..ec44d52 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -19,7 +19,7 @@ public: /** * \param mediator A reference to a Mediator object used for transfering managers. */ - LoopTimerManager(Mediator &mediator); + LoopTimerManager(Mediator & mediator); /** * \brief Get the current delta time for the current frame. * @@ -146,7 +146,6 @@ private: */ void advance_fixed_elapsed_time(); - private: //! Target frames per second int target_fps = 60; -- cgit v1.2.3 From f64b793ad8e796458c8e175f298e8d13eb3b3459 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 11 Dec 2024 14:16:40 +0100 Subject: feedback --- src/crepe/api/LoopManager.cpp | 45 ++++++++++++------------ src/crepe/api/LoopManager.h | 18 ++-------- src/crepe/manager/LoopTimerManager.cpp | 56 ++++++++++++++--------------- src/crepe/manager/LoopTimerManager.h | 64 +++++++++++++++++----------------- src/crepe/manager/Mediator.h | 1 + src/crepe/system/AnimatorSystem.cpp | 2 +- src/test/LoopManagerTest.cpp | 12 ++----- src/test/LoopTimerTest.cpp | 20 +++++------ 8 files changed, 99 insertions(+), 119 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 46a7635..a1da8be 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -7,7 +7,8 @@ #include "../system/PhysicsSystem.h" #include "../system/RenderSystem.h" #include "../system/ScriptSystem.h" -#include "manager/EventManager.h" +#include "../manager/EventManager.h" +#include "../util/Log.h" #include "LoopManager.h" @@ -25,56 +26,56 @@ LoopManager::LoopManager() { this->event_manager.subscribe( [this](const ShutDownEvent & event) { return this->on_shutdown(event); }); } - -void LoopManager::process_input() { - this->get_system().update(); - this->event_manager.dispatch_events(); -} - void LoopManager::start() { this->setup(); this->loop(); } -void LoopManager::fixed_update() { - this->get_system().update(); - this->get_system().update(); - this->get_system().update(); +void LoopManager::setup() { + this->game_running = true; + this->loop_timer.start(); + this->scene_manager.load_next_scene(); } void LoopManager::loop() { + try { while (game_running) { this->loop_timer.update(); while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { - this->process_input(); this->fixed_update(); this->loop_timer.advance_fixed_elapsed_time(); } this->frame_update(); - this->render(); this->loop_timer.enforce_frame_rate(); } + }catch(const exception & e){ + Log::logf(Log::Level::ERROR, "Exception caught in main loop: %s", e.what()); + this->event_manager.trigger_event(ShutDownEvent{}); + } } -void LoopManager::setup() { - this->game_running = true; - this->loop_timer.start(); - this->scene_manager.load_next_scene(); +// will be called at a fixed interval +void LoopManager::fixed_update() { + this->get_system().update(); + this->event_manager.dispatch_events(); + this->get_system().update(); + this->get_system().update(); + this->get_system().update(); } -void LoopManager::render() { - if (!this->game_running) return; - +// will be called every frame +void LoopManager::frame_update() { + this->scene_manager.load_next_scene(); this->get_system().update(); + //render this->get_system().update(); } bool LoopManager::on_shutdown(const ShutDownEvent & e) { this->game_running = false; + // propagate to possible user ShutDownEvent listeners return false; } - -void LoopManager::frame_update() { this->scene_manager.load_next_scene(); } diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index f94cea1..2319d65 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -25,7 +25,7 @@ public: * \brief Start the gameloop * * This is the start of the engine where the setup is called and then the loop keeps running until the game stops running. - * Developers need to call this function to run the game. + * The Game programmer needs to call this function to run the game. This should be done after creating and adding all scenes. */ void start(); @@ -51,13 +51,6 @@ private: */ void loop(); - /** - * \brief Function for handling input-related system calls. - * - * Processes user inputs from keyboard and mouse. - */ - void process_input(); - /** * \brief Per-frame update. * @@ -71,15 +64,9 @@ private: * This function updates physics and game logic based on LoopTimer's fixed_delta_time. */ virtual void fixed_update(); - /** - * \brief Function for executing render-related systems. - * - * Renders the current state of the game to the screen. - */ - virtual void render(); + //! Indicates whether the game is running. bool game_running = false; - private: //! Global context Mediator mediator; @@ -97,6 +84,7 @@ private: SDLContext & sdl_context = SDLContext::get_instance(); private: + /** * \brief Callback function for ShutDownEvent * diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 8725c33..a306eb7 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -6,7 +6,7 @@ #include "LoopTimerManager.h" using namespace crepe; - +using namespace std::chrono_literals; LoopTimerManager::LoopTimerManager(Mediator & mediator) : Manager(mediator) { this->mediator.loop_timer = *this; dbg_trace(); @@ -15,62 +15,57 @@ LoopTimerManager::LoopTimerManager(Mediator & mediator) : Manager(mediator) { void LoopTimerManager::start() { this->last_frame_time = std::chrono::steady_clock::now(); - this->elapsed_time = std::chrono::milliseconds(0); + this->elapsed_time = 0s; // by starting the elapsed_fixed_time at (0 - fixed_delta_time) in milliseconds it calls a fixed update at the start of the loop. this->elapsed_fixed_time - = -std::chrono::duration_cast(fixed_delta_time); - this->delta_time = std::chrono::milliseconds(0); + = -std::chrono::duration_cast(this->fixed_delta_time); + this->delta_time = 0s; } void LoopTimerManager::update() { - std::chrono::steady_clock::time_point current_frame_time + TimePoint_t current_frame_time = std::chrono::steady_clock::now(); // Convert to duration in seconds for delta time - this->delta_time = std::chrono::duration_cast>( - current_frame_time - last_frame_time); + this->delta_time = current_frame_time - last_frame_time; if (this->delta_time > this->maximum_delta_time) { this->delta_time = this->maximum_delta_time; } - if (this->delta_time.count() > 0.0) { + if (this->delta_time > 0s) { this->actual_fps = 1.0 / this->delta_time.count(); } else { this->actual_fps = 0; } - - this->elapsed_time += this->delta_time; + this->elapsed_time += std::chrono::duration_cast(this->delta_time); this->last_frame_time = current_frame_time; } -double LoopTimerManager::get_delta_time() const { - return this->delta_time.count() * this->time_scale; -} +Duration_t LoopTimerManager::get_delta_time() const {return this->delta_time * this->time_scale;} -double LoopTimerManager::get_current_time() const { return this->elapsed_time.count(); } +ElapsedTime_t LoopTimerManager::get_elapsed_time() const { return this->elapsed_time; } void LoopTimerManager::advance_fixed_elapsed_time() { - this->elapsed_fixed_time += this->fixed_delta_time; + this->elapsed_fixed_time += std::chrono::duration_cast(this->fixed_delta_time); } -void LoopTimerManager::set_target_fps(int fps) { +void LoopTimerManager::set_target_framerate(unsigned fps) { this->target_fps = fps; //check if fps is lower or equals 0 if (fps <= 0) return; // target time per frame in seconds - this->frame_target_time = std::chrono::duration(1.0) / this->target_fps; + this->frame_target_time = Duration_t(1s) / this->target_fps; } -int LoopTimerManager::get_fps() const { return this->actual_fps; } +unsigned LoopTimerManager::get_fps() const { return this->actual_fps; } void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; } -double LoopTimerManager::get_time_scale() const { return this->time_scale; } +float LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { - std::chrono::steady_clock::time_point current_frame_time + TimePoint_t current_frame_time = std::chrono::steady_clock::now(); - std::chrono::duration frame_duration = current_frame_time - this->last_frame_time; - + Duration_t frame_duration = current_frame_time - this->last_frame_time; // Check if frame duration is less than the target frame time if (frame_duration < this->frame_target_time) { std::chrono::microseconds delay_time @@ -83,16 +78,17 @@ void LoopTimerManager::enforce_frame_rate() { } } -double LoopTimerManager::get_lag() const { - return (this->elapsed_time - this->elapsed_fixed_time).count(); +Duration_t LoopTimerManager::get_lag() const { + return (this->elapsed_time - this->elapsed_fixed_time); } -double LoopTimerManager::get_scaled_fixed_delta_time() const { - return this->fixed_delta_time.count() * this->time_scale; + +Duration_t LoopTimerManager::get_scaled_fixed_delta_time() const { + return this->fixed_delta_time * this->time_scale; } -void LoopTimerManager::set_fixed_delta_time(double seconds) { - this->fixed_delta_time = std::chrono::duration(seconds); +void LoopTimerManager::set_fixed_delta_time(float seconds) { + this->fixed_delta_time = Duration_t(seconds); } -double LoopTimerManager::get_fixed_delta_time() const { - return this->fixed_delta_time.count(); +Duration_t LoopTimerManager::get_fixed_delta_time() const { + return this->fixed_delta_time; } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index ec44d52..c5f3cb0 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -5,7 +5,9 @@ #include "Manager.h" namespace crepe { - +typedef std::chrono::duration Duration_t; +typedef std::chrono::duration ElapsedTime_t; +typedef std::chrono::steady_clock::time_point TimePoint_t; /** * \brief Manages timing and frame rate for the game loop. * @@ -28,31 +30,31 @@ public: * * \return Delta time in seconds since the last frame. */ - double get_delta_time() const; + Duration_t get_delta_time() const; /** - * \brief Get the current game time. + * \brief Get the current elapsed time (total time passed ) * * \note The current game time may vary from real-world elapsed time. It is the cumulative * sum of each frame's delta time. * * \return Elapsed game time in seconds. */ - double get_current_time() const; + ElapsedTime_t get_elapsed_time() const; /** * \brief Set the target frames per second (FPS). * * \param fps The desired frames rendered per second. */ - void set_target_fps(int fps); + void set_target_framerate(unsigned fps); /** * \brief Get the current frames per second (FPS). * * \return Current FPS. */ - int get_fps() const; + unsigned get_fps() const; /** * \brief Get the current time scale. @@ -60,7 +62,7 @@ public: * \return The current time scale, where (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). * up the game. */ - double get_time_scale() const; + float get_time_scale() const; /** * \brief Set the time scale. @@ -76,11 +78,10 @@ public: * * This value is used in the LoopManager to determine how many times * the fixed_update should be called within a given interval. - * This value is also the timing value which is used in the fixed_loop to convert pixels to time. * * \return The unscaled fixed delta time in seconds. */ - double get_fixed_delta_time() const; + Duration_t get_fixed_delta_time() const; /** * \brief Set the fixed_delta_time in seconds. @@ -88,9 +89,9 @@ public: * \param seconds fixed_delta_time in seconds. * * The fixed_delta_time value is used to determine how many times per second the fixed_update and process_input functions are called. - * This value is also the timing value which is used in the fixed_loop to convert pixels to time. + * */ - void set_fixed_delta_time(double seconds); + void set_fixed_delta_time(float seconds); /** * \brief Retrieves the scaled fixed delta time in seconds. @@ -101,12 +102,11 @@ public: * * \return The fixed delta time, scaled by the current time scale, in seconds. */ - double get_scaled_fixed_delta_time() const; + Duration_t get_scaled_fixed_delta_time() const; private: //! Friend relation to use start,enforce_frame_rate,get_lag,update,advance_fixed_update. friend class LoopManager; - /** * \brief Start the loop timer. * @@ -128,7 +128,7 @@ private: * * \return Accumulated lag in seconds. */ - double get_lag() const; + Duration_t get_lag() const; /** * \brief Update the timer to the current frame. @@ -147,27 +147,27 @@ private: void advance_fixed_elapsed_time(); private: - //! Target frames per second + //! Target frames per second. int target_fps = 60; - //! Actual frames per second + //! Actual frames per second. int actual_fps = 0; - //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) - double time_scale = 1; - //! Maximum delta time in seconds to avoid large jumps - std::chrono::duration maximum_delta_time{0.25}; - //! Delta time for the current frame in seconds - std::chrono::duration delta_time{0.0}; + //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). + float time_scale = 1; + //! Maximum delta time in seconds to avoid large jumps. + Duration_t maximum_delta_time{0.25}; + //! Delta time for the current frame in seconds. + Duration_t delta_time{0.0}; //! Target time per frame in seconds - std::chrono::duration frame_target_time - = std::chrono::duration(1.0) / target_fps; - //! Fixed delta time for fixed updates in seconds - std::chrono::duration fixed_delta_time = std::chrono::duration(1.0) / 50.0; - //! Total elapsed game time in seconds - std::chrono::duration elapsed_time{0.0}; - //! Total elapsed time for fixed updates in seconds - std::chrono::duration elapsed_fixed_time{0.0}; - //! Time of the last frame - std::chrono::steady_clock::time_point last_frame_time; + Duration_t frame_target_time + = Duration_t(1.0) / target_fps; + //! Fixed delta time for fixed updates in seconds. + Duration_t fixed_delta_time = Duration_t(1.0) / 50.0; + //! Total elapsed game time in microseconds. + ElapsedTime_t elapsed_time{0}; + //! Total elapsed time for fixed updates in microseconds. + ElapsedTime_t elapsed_fixed_time{0}; + //! Time of the last frame. + TimePoint_t last_frame_time; }; } // namespace crepe diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index eb8a7a5..ad51cc6 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -11,6 +11,7 @@ namespace crepe { class ComponentManager; class SceneManager; + class LoopTimerManager; class EventManager; /** diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 499f618..690b45b 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -13,7 +13,7 @@ void AnimatorSystem::update() { LoopTimerManager & timer = this->mediator.loop_timer; RefVector animations = mgr.get_components_by_type(); - double elapsed_time = timer.get_current_time(); + unsigned long long elapsed_time = timer.get_elapsed_time().count(); for (Animator & a : animations) { if (!a.active) continue; diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp index c44ebda..4e0ecdc 100644 --- a/src/test/LoopManagerTest.cpp +++ b/src/test/LoopManagerTest.cpp @@ -16,7 +16,6 @@ protected: public: MOCK_METHOD(void, fixed_update, (), (override)); MOCK_METHOD(void, frame_update, (), (override)); - MOCK_METHOD(void, render, (), (override)); }; TestGameLoop test_loop; @@ -25,10 +24,9 @@ protected: TEST_F(LoopManagerTest, FixedUpdate) { // Arrange - test_loop.loop_timer.set_target_fps(60); + test_loop.loop_timer.set_target_framerate(60); // Set expectations for the mock calls - EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); @@ -47,10 +45,9 @@ TEST_F(LoopManagerTest, FixedUpdate) { } TEST_F(LoopManagerTest, ScaledFixedUpdate) { // Arrange - test_loop.loop_timer.set_target_fps(60); + test_loop.loop_timer.set_target_framerate(60); // Set expectations for the mock calls - EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); @@ -69,9 +66,8 @@ TEST_F(LoopManagerTest, ScaledFixedUpdate) { } TEST_F(LoopManagerTest, ShutDown) { // Arrange - test_loop.loop_timer.set_target_fps(60); + test_loop.loop_timer.set_target_framerate(60); - EXPECT_CALL(test_loop, render).Times(::testing::AtLeast(1)); EXPECT_CALL(test_loop, frame_update).Times(::testing::AtLeast(1)); EXPECT_CALL(test_loop, fixed_update).Times(::testing::AtLeast(1)); // Start the loop in a separate thread @@ -80,6 +76,4 @@ TEST_F(LoopManagerTest, ShutDown) { test_loop.event_manager.trigger_event(ShutDownEvent{}); // Wait for the loop thread to finish loop_thread.join(); - - // Test finished } diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp index c6655d9..1216e5e 100644 --- a/src/test/LoopTimerTest.cpp +++ b/src/test/LoopTimerTest.cpp @@ -17,7 +17,7 @@ protected: }; TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { // Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) - loop_timer.set_target_fps(60); + loop_timer.set_target_framerate(60); auto start_time = steady_clock::now(); loop_timer.enforce_frame_rate(); @@ -30,33 +30,33 @@ TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { } TEST_F(LoopTimerTest, SetTargetFps) { // Set the target FPS to 120 - loop_timer.set_target_fps(120); + loop_timer.set_target_framerate(120); // Calculate the expected frame time (~8.33ms per frame) - auto expected_frame_time = std::chrono::duration(1.0 / 120.0); + Duration_t expected_frame_time = std::chrono::duration(1.0 / 120.0); ASSERT_NEAR(loop_timer.frame_target_time.count(), expected_frame_time.count(), 0.001); } TEST_F(LoopTimerTest, DeltaTimeCalculation) { // Set the target FPS to 60 (16.67 ms per frame) - loop_timer.set_target_fps(60); + loop_timer.set_target_framerate(60); auto start_time = steady_clock::now(); loop_timer.update(); auto end_time = steady_clock::now(); // Check the delta time - double delta_time = loop_timer.get_delta_time(); + Duration_t delta_time = loop_timer.get_delta_time(); auto elapsed_time = duration_cast(end_time - start_time).count(); // Assert that delta_time is close to the elapsed time - ASSERT_NEAR(delta_time, elapsed_time, 1); + ASSERT_NEAR(delta_time.count(), elapsed_time, 1); } TEST_F(LoopTimerTest, getCurrentTime) { // Set the target FPS to 60 (16.67 ms per frame) - loop_timer.set_target_fps(60); + loop_timer.set_target_framerate(60); auto start_time = steady_clock::now(); @@ -68,8 +68,8 @@ TEST_F(LoopTimerTest, getCurrentTime) { auto end_time = steady_clock::now(); // Get the elapsed time in seconds as a double - auto elapsed_time - = duration_cast>(end_time - start_time).count(); + auto elapsed_time = std::chrono::duration_cast(end_time - start_time).count(); - ASSERT_NEAR(loop_timer.get_current_time(), elapsed_time, 0.001); + + ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5); } -- cgit v1.2.3 From e49893e8de74534494792955c50ea0eabaf3ba38 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 11 Dec 2024 15:01:46 +0100 Subject: WIP fix LoopTimerManager --- src/crepe/api/LoopManager.cpp | 19 +++++++------- src/crepe/manager/LoopTimerManager.cpp | 47 +++++++++++++++++----------------- src/crepe/manager/LoopTimerManager.h | 34 ++++++++++++------------ src/crepe/manager/Mediator.h | 6 ++--- src/crepe/system/AISystem.cpp | 8 +++--- src/test/LoopTimerTest.cpp | 10 +++++--- 6 files changed, 64 insertions(+), 60 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 4ca9928..aa4a21a 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -43,20 +43,19 @@ void LoopManager::setup() { void LoopManager::loop() { try { + while (game_running) { + this->loop_timer.update(); - while (game_running) { - this->loop_timer.update(); + while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { + this->fixed_update(); + this->loop_timer.advance_fixed_elapsed_time(); + } - while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) { - this->fixed_update(); - this->loop_timer.advance_fixed_elapsed_time(); + this->frame_update(); + this->loop_timer.enforce_frame_rate(); } - - this->frame_update(); - this->loop_timer.enforce_frame_rate(); - } }catch(const exception & e){ - Log::logf(Log::Level::ERROR, "Exception caught in main loop: %s", e.what()); + Log::logf(Log::Level::ERROR, "Exception caught in main loop: {}", e.what()); this->event_manager.trigger_event(ShutDownEvent{}); } } diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index a306eb7..92a2150 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -6,7 +6,9 @@ #include "LoopTimerManager.h" using namespace crepe; +using namespace std::chrono; using namespace std::chrono_literals; + LoopTimerManager::LoopTimerManager(Mediator & mediator) : Manager(mediator) { this->mediator.loop_timer = *this; dbg_trace(); @@ -15,15 +17,14 @@ LoopTimerManager::LoopTimerManager(Mediator & mediator) : Manager(mediator) { void LoopTimerManager::start() { this->last_frame_time = std::chrono::steady_clock::now(); - this->elapsed_time = 0s; + this->elapsed_time = elapsed_time_t{0}; // by starting the elapsed_fixed_time at (0 - fixed_delta_time) in milliseconds it calls a fixed update at the start of the loop. - this->elapsed_fixed_time - = -std::chrono::duration_cast(this->fixed_delta_time); - this->delta_time = 0s; + // this->elapsed_fixed_time = -this->fixed_delta_time; + this->delta_time = duration_t{0}; } void LoopTimerManager::update() { - TimePoint_t current_frame_time + time_point_t current_frame_time = std::chrono::steady_clock::now(); // Convert to duration in seconds for delta time this->delta_time = current_frame_time - last_frame_time; @@ -32,20 +33,20 @@ void LoopTimerManager::update() { this->delta_time = this->maximum_delta_time; } if (this->delta_time > 0s) { - this->actual_fps = 1.0 / this->delta_time.count(); + this->actual_fps = 1.0 / duration_cast(this->delta_time).count(); } else { this->actual_fps = 0; } - this->elapsed_time += std::chrono::duration_cast(this->delta_time); + this->elapsed_time += duration_cast(this->delta_time); this->last_frame_time = current_frame_time; } -Duration_t LoopTimerManager::get_delta_time() const {return this->delta_time * this->time_scale;} +duration_t LoopTimerManager::get_delta_time() const {return this->delta_time * this->time_scale;} -ElapsedTime_t LoopTimerManager::get_elapsed_time() const { return this->elapsed_time; } +elapsed_time_t LoopTimerManager::get_elapsed_time() const { return this->elapsed_time; } void LoopTimerManager::advance_fixed_elapsed_time() { - this->elapsed_fixed_time += std::chrono::duration_cast(this->fixed_delta_time); + this->elapsed_fixed_time += std::chrono::duration_cast(this->fixed_delta_time); } void LoopTimerManager::set_target_framerate(unsigned fps) { @@ -53,7 +54,7 @@ void LoopTimerManager::set_target_framerate(unsigned fps) { //check if fps is lower or equals 0 if (fps <= 0) return; // target time per frame in seconds - this->frame_target_time = Duration_t(1s) / this->target_fps; + this->frame_target_time = duration_t(1s) / this->target_fps; } unsigned LoopTimerManager::get_fps() const { return this->actual_fps; } @@ -63,32 +64,30 @@ void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; float LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { - TimePoint_t current_frame_time - = std::chrono::steady_clock::now(); - Duration_t frame_duration = current_frame_time - this->last_frame_time; + time_point_t current_frame_time = std::chrono::steady_clock::now(); + duration_t frame_duration = current_frame_time - this->last_frame_time; + // Check if frame duration is less than the target frame time if (frame_duration < this->frame_target_time) { - std::chrono::microseconds delay_time - = std::chrono::duration_cast(this->frame_target_time - - frame_duration); - - if (delay_time.count() > 0) { + duration_t delay_time = this->frame_target_time - frame_duration; + if (delay_time > 0s) { std::this_thread::sleep_for(delay_time); } } } -Duration_t LoopTimerManager::get_lag() const { - return (this->elapsed_time - this->elapsed_fixed_time); +duration_t LoopTimerManager::get_lag() const { + return this->elapsed_time - this->elapsed_fixed_time; } -Duration_t LoopTimerManager::get_scaled_fixed_delta_time() const { +duration_t LoopTimerManager::get_scaled_fixed_delta_time() const { return this->fixed_delta_time * this->time_scale; } + void LoopTimerManager::set_fixed_delta_time(float seconds) { - this->fixed_delta_time = Duration_t(seconds); + this->fixed_delta_time = duration_t(seconds); } -Duration_t LoopTimerManager::get_fixed_delta_time() const { +duration_t LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time; } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index c5f3cb0..ad522f7 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -5,9 +5,10 @@ #include "Manager.h" namespace crepe { -typedef std::chrono::duration Duration_t; -typedef std::chrono::duration ElapsedTime_t; -typedef std::chrono::steady_clock::time_point TimePoint_t; + +typedef std::chrono::duration duration_t; +typedef std::chrono::duration elapsed_time_t; + /** * \brief Manages timing and frame rate for the game loop. * @@ -30,7 +31,7 @@ public: * * \return Delta time in seconds since the last frame. */ - Duration_t get_delta_time() const; + duration_t get_delta_time() const; /** * \brief Get the current elapsed time (total time passed ) @@ -40,7 +41,7 @@ public: * * \return Elapsed game time in seconds. */ - ElapsedTime_t get_elapsed_time() const; + elapsed_time_t get_elapsed_time() const; /** * \brief Set the target frames per second (FPS). @@ -81,7 +82,7 @@ public: * * \return The unscaled fixed delta time in seconds. */ - Duration_t get_fixed_delta_time() const; + duration_t get_fixed_delta_time() const; /** * \brief Set the fixed_delta_time in seconds. @@ -102,7 +103,7 @@ public: * * \return The fixed delta time, scaled by the current time scale, in seconds. */ - Duration_t get_scaled_fixed_delta_time() const; + duration_t get_scaled_fixed_delta_time() const; private: //! Friend relation to use start,enforce_frame_rate,get_lag,update,advance_fixed_update. @@ -128,7 +129,7 @@ private: * * \return Accumulated lag in seconds. */ - Duration_t get_lag() const; + duration_t get_lag() const; /** * \brief Update the timer to the current frame. @@ -154,20 +155,21 @@ private: //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). float time_scale = 1; //! Maximum delta time in seconds to avoid large jumps. - Duration_t maximum_delta_time{0.25}; + duration_t maximum_delta_time{0.25}; //! Delta time for the current frame in seconds. - Duration_t delta_time{0.0}; + duration_t delta_time{0.0}; //! Target time per frame in seconds - Duration_t frame_target_time - = Duration_t(1.0) / target_fps; + duration_t frame_target_time{1.0 / target_fps}; //! Fixed delta time for fixed updates in seconds. - Duration_t fixed_delta_time = Duration_t(1.0) / 50.0; + duration_t fixed_delta_time{1.0 / 50.0}; //! Total elapsed game time in microseconds. - ElapsedTime_t elapsed_time{0}; + elapsed_time_t elapsed_time{0}; //! Total elapsed time for fixed updates in microseconds. - ElapsedTime_t elapsed_fixed_time{0}; + elapsed_time_t elapsed_fixed_time{0}; + + typedef std::chrono::steady_clock::time_point time_point_t; //! Time of the last frame. - TimePoint_t last_frame_time; + time_point_t last_frame_time; }; } // namespace crepe diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index dfb37dc..b529f2c 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -5,17 +5,15 @@ // TODO: remove these singletons: #include "../facade/SDLContext.h" -#include "SaveManager.h" - namespace crepe { class ComponentManager; class SceneManager; +class EventManager; +class LoopTimerManager; class SaveManager; class ResourceManager; -class LoopTimerManager; -class EventManager; /** * Struct to pass references to classes that would otherwise need to be singletons down to * other classes within the engine hierarchy. Made to prevent constant changes to subclasses to diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index e2e36a5..ffb1bcd 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,21 +1,23 @@ #include #include -#include "api/LoopTimer.h" +#include "manager/LoopTimerManager.h" #include "manager/ComponentManager.h" #include "manager/Mediator.h" #include "AISystem.h" using namespace crepe; +using namespace std::chrono; void AISystem::update() { const Mediator & mediator = this->mediator; ComponentManager & mgr = mediator.component_manager; RefVector ai_components = mgr.get_components_by_type(); + LoopTimerManager & loop_timer = mediator.loop_timer; //TODO: Use fixed loop dt (this is not available at master at the moment) - double dt = LoopTimer::get_instance().get_delta_time(); + duration_t dt = loop_timer.get_delta_time(); // Loop through all AI components for (AI & ai : ai_components) { @@ -42,7 +44,7 @@ void AISystem::update() { // Calculate the acceleration (using the above calculated force) vec2 acceleration = force / rigidbody.data.mass; // Finally, update Rigidbody's velocity - rigidbody.data.linear_velocity += acceleration * dt; + rigidbody.data.linear_velocity += acceleration * duration_cast(dt).count(); } } diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp index 1216e5e..f99f109 100644 --- a/src/test/LoopTimerTest.cpp +++ b/src/test/LoopTimerTest.cpp @@ -15,6 +15,7 @@ protected: void SetUp() override { loop_timer.start(); } }; + TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { // Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) loop_timer.set_target_framerate(60); @@ -28,15 +29,17 @@ TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { // For 60 FPS, the target frame time is around 16.67ms ASSERT_NEAR(elapsed_ms, 16.7, 1); } + TEST_F(LoopTimerTest, SetTargetFps) { // Set the target FPS to 120 loop_timer.set_target_framerate(120); // Calculate the expected frame time (~8.33ms per frame) - Duration_t expected_frame_time = std::chrono::duration(1.0 / 120.0); + duration_t expected_frame_time = std::chrono::duration(1.0 / 120.0); ASSERT_NEAR(loop_timer.frame_target_time.count(), expected_frame_time.count(), 0.001); } + TEST_F(LoopTimerTest, DeltaTimeCalculation) { // Set the target FPS to 60 (16.67 ms per frame) loop_timer.set_target_framerate(60); @@ -46,7 +49,7 @@ TEST_F(LoopTimerTest, DeltaTimeCalculation) { auto end_time = steady_clock::now(); // Check the delta time - Duration_t delta_time = loop_timer.get_delta_time(); + duration_t delta_time = loop_timer.get_delta_time(); auto elapsed_time = duration_cast(end_time - start_time).count(); @@ -68,8 +71,9 @@ TEST_F(LoopTimerTest, getCurrentTime) { auto end_time = steady_clock::now(); // Get the elapsed time in seconds as a double - auto elapsed_time = std::chrono::duration_cast(end_time - start_time).count(); + auto elapsed_time = std::chrono::duration_cast(end_time - start_time).count(); ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5); } + -- cgit v1.2.3 From 9390bc838dbcb7126b07d8b109697f96d713f34d Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 11 Dec 2024 15:14:34 +0100 Subject: feedback changed and merge working --- src/crepe/manager/LoopTimerManager.cpp | 15 +++++++-------- src/crepe/manager/LoopTimerManager.h | 2 +- src/test/LoopManagerTest.cpp | 7 ++----- 3 files changed, 10 insertions(+), 14 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 5a6cc76..ea4619f 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -18,13 +18,12 @@ void LoopTimerManager::start() { this->last_frame_time = std::chrono::steady_clock::now(); this->elapsed_time = elapsed_time_t{0}; - // by starting the elapsed_fixed_time at (0 - fixed_delta_time) in milliseconds it calls a fixed update at the start of the loop. - // this->elapsed_fixed_time = -this->fixed_delta_time; + this->elapsed_fixed_time = elapsed_time_t{0}; this->delta_time = duration_t{0}; } void LoopTimerManager::update() { - TimePoint_t current_frame_time + time_point_t current_frame_time = std::chrono::steady_clock::now(); // Convert to duration in seconds for delta time this->delta_time = current_frame_time - last_frame_time; @@ -41,12 +40,12 @@ void LoopTimerManager::update() { this->last_frame_time = current_frame_time; } -Duration_t LoopTimerManager::get_delta_time() const {return this->delta_time * this->time_scale;} +duration_t LoopTimerManager::get_delta_time() const {return this->delta_time * this->time_scale;} elapsed_time_t LoopTimerManager::get_elapsed_time() const { return this->elapsed_time; } void LoopTimerManager::advance_fixed_elapsed_time() { - this->elapsed_fixed_time += std::chrono::duration_cast(this->fixed_delta_time); + this->elapsed_fixed_time += std::chrono::duration_cast(this->fixed_delta_time); } void LoopTimerManager::set_target_framerate(unsigned fps) { @@ -64,9 +63,9 @@ void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; float LoopTimerManager::get_time_scale() const { return this->time_scale; } void LoopTimerManager::enforce_frame_rate() { - TimePoint_t current_frame_time + time_point_t current_frame_time = std::chrono::steady_clock::now(); - Duration_t frame_duration = current_frame_time - this->last_frame_time; + duration_t frame_duration = current_frame_time - this->last_frame_time; // Check if frame duration is less than the target frame time if (frame_duration < this->frame_target_time) { duration_t delay_time = this->frame_target_time - frame_duration; @@ -88,6 +87,6 @@ void LoopTimerManager::set_fixed_delta_time(float seconds) { this->fixed_delta_time = duration_t(seconds); } -Duration_t LoopTimerManager::get_fixed_delta_time() const { +duration_t LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time; } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index ad522f7..0eda156 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -6,7 +6,7 @@ namespace crepe { -typedef std::chrono::duration duration_t; +typedef std::chrono::duration duration_t; typedef std::chrono::duration elapsed_time_t; /** diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp index 4e0ecdc..cf7a454 100644 --- a/src/test/LoopManagerTest.cpp +++ b/src/test/LoopManagerTest.cpp @@ -28,7 +28,7 @@ TEST_F(LoopManagerTest, FixedUpdate) { // Set expectations for the mock calls EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); - EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); + EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(49)); // Start the loop in a separate thread std::thread loop_thread([&]() { test_loop.start(); }); @@ -49,7 +49,7 @@ TEST_F(LoopManagerTest, ScaledFixedUpdate) { // Set expectations for the mock calls EXPECT_CALL(test_loop, frame_update).Times(::testing::Exactly(60)); - EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); + EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(49)); // Start the loop in a separate thread std::thread loop_thread([&]() { test_loop.start(); }); @@ -67,9 +67,6 @@ TEST_F(LoopManagerTest, ScaledFixedUpdate) { TEST_F(LoopManagerTest, ShutDown) { // Arrange test_loop.loop_timer.set_target_framerate(60); - - EXPECT_CALL(test_loop, frame_update).Times(::testing::AtLeast(1)); - EXPECT_CALL(test_loop, fixed_update).Times(::testing::AtLeast(1)); // Start the loop in a separate thread std::thread loop_thread([&]() { test_loop.start(); }); std::this_thread::sleep_for(std::chrono::milliseconds(1)); -- cgit v1.2.3 From 1087daecae46cd7acc3f64c5169e56f59953b599 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 11 Dec 2024 18:33:06 +0100 Subject: fps to unsigned --- src/crepe/manager/LoopTimerManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 0eda156..91403e4 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -149,9 +149,9 @@ private: private: //! Target frames per second. - int target_fps = 60; + unsigned target_fps = 60; //! Actual frames per second. - int actual_fps = 0; + unsigned actual_fps = 0; //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). float time_scale = 1; //! Maximum delta time in seconds to avoid large jumps. -- cgit v1.2.3 From f7b4866811c63ae24c366d9452e53d24e504336f Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Thu, 12 Dec 2024 19:47:59 +0100 Subject: fps fix + regression test --- src/crepe/manager/LoopTimerManager.cpp | 3 +-- src/crepe/manager/LoopTimerManager.h | 6 +++--- src/test/LoopTimerTest.cpp | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 9819632..9d24c2b 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -1,6 +1,5 @@ #include #include - #include "../util/Log.h" #include "LoopTimerManager.h" @@ -31,7 +30,7 @@ void LoopTimerManager::update() { this->delta_time = this->maximum_delta_time; } if (this->delta_time > 0s) { - this->actual_fps = 1.0 / duration_cast(this->delta_time).count(); + this->actual_fps = static_cast(1.0 / this->delta_time.count()); } else { this->actual_fps = 0; } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 91403e4..c943d41 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -6,7 +6,7 @@ namespace crepe { -typedef std::chrono::duration duration_t; +typedef std::chrono::duration duration_t; typedef std::chrono::duration elapsed_time_t; /** @@ -149,9 +149,9 @@ private: private: //! Target frames per second. - unsigned target_fps = 60; + unsigned int target_fps = 60; //! Actual frames per second. - unsigned actual_fps = 0; + unsigned int actual_fps = 0; //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). float time_scale = 1; //! Maximum delta time in seconds to avoid large jumps. diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp index 5e1eccf..c468567 100644 --- a/src/test/LoopTimerTest.cpp +++ b/src/test/LoopTimerTest.cpp @@ -76,3 +76,19 @@ TEST_F(LoopTimerTest, getCurrentTime) { ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5); } +TEST_F(LoopTimerTest, getFPS) { + // Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) + loop_timer.set_target_framerate(60); + + auto start_time = steady_clock::now(); + loop_timer.enforce_frame_rate(); + + auto elapsed_time = steady_clock::now() - start_time; + loop_timer.update(); + unsigned int fps = loop_timer.get_fps(); + auto elapsed_ms = duration_cast(elapsed_time).count(); + + // For 60 FPS, the target frame time is around 16.67ms + ASSERT_NEAR(elapsed_ms, 16.7, 1); + ASSERT_NEAR(fps, 60, 2); +} -- cgit v1.2.3 From 15c25ba41d0e128c61b38c1751bf5eb36b5a040c Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Thu, 12 Dec 2024 19:51:10 +0100 Subject: made return unsigned int --- src/crepe/manager/LoopTimerManager.cpp | 2 +- src/crepe/manager/LoopTimerManager.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/crepe/manager/LoopTimerManager.h') diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 9d24c2b..57956f2 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -1,6 +1,6 @@ +#include "../util/Log.h" #include #include -#include "../util/Log.h" #include "LoopTimerManager.h" diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index c943d41..76b02d3 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -55,7 +55,7 @@ public: * * \return Current FPS. */ - unsigned get_fps() const; + unsigned int get_fps() const; /** * \brief Get the current time scale. -- cgit v1.2.3