aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-12-11 15:01:46 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-12-11 15:01:46 +0100
commite49893e8de74534494792955c50ea0eabaf3ba38 (patch)
treec85a80001d4c17e467d69698defb628109559ecf
parent68bf20b491b4b7673c2ece7a6497b9faffd44eb1 (diff)
WIP fix LoopTimerManager
-rw-r--r--src/crepe/api/LoopManager.cpp19
-rw-r--r--src/crepe/manager/LoopTimerManager.cpp47
-rw-r--r--src/crepe/manager/LoopTimerManager.h34
-rw-r--r--src/crepe/manager/Mediator.h6
-rw-r--r--src/crepe/system/AISystem.cpp8
-rw-r--r--src/test/LoopTimerTest.cpp10
6 files changed, 64 insertions, 60 deletions
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>(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<ElapsedTime_t>(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<seconds>(this->delta_time).count();
} else {
this->actual_fps = 0;
}
- this->elapsed_time += std::chrono::duration_cast<ElapsedTime_t>(this->delta_time);
+ this->elapsed_time += duration_cast<elapsed_time_t>(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<ElapsedTime_t>(this->fixed_delta_time);
+ this->elapsed_fixed_time += std::chrono::duration_cast<elapsed_time_t>(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<std::chrono::microseconds>(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<float> Duration_t;
-typedef std::chrono::duration<unsigned long long, std::micro> ElapsedTime_t;
-typedef std::chrono::steady_clock::time_point TimePoint_t;
+
+typedef std::chrono::duration<float> duration_t;
+typedef std::chrono::duration<unsigned long long, std::micro> 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 <algorithm>
#include <cmath>
-#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> ai_components = mgr.get_components_by_type<AI>();
+ 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<seconds>(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<float>(1.0 / 120.0);
+ duration_t expected_frame_time = std::chrono::duration<float>(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<seconds>(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<ElapsedTime_t>(end_time - start_time).count();
+ auto elapsed_time = std::chrono::duration_cast<elapsed_time_t>(end_time - start_time).count();
ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5);
}
+