aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crepe/api/LoopManager.cpp45
-rw-r--r--src/crepe/api/LoopManager.h18
-rw-r--r--src/crepe/manager/LoopTimerManager.cpp56
-rw-r--r--src/crepe/manager/LoopTimerManager.h64
-rw-r--r--src/crepe/manager/Mediator.h1
-rw-r--r--src/crepe/system/AnimatorSystem.cpp2
-rw-r--r--src/test/LoopManagerTest.cpp12
-rw-r--r--src/test/LoopTimerTest.cpp20
8 files changed, 99 insertions, 119 deletions
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<ShutDownEvent>(
[this](const ShutDownEvent & event) { return this->on_shutdown(event); });
}
-
-void LoopManager::process_input() {
- this->get_system<InputSystem>().update();
- this->event_manager.dispatch_events();
-}
-
void LoopManager::start() {
this->setup();
this->loop();
}
-void LoopManager::fixed_update() {
- this->get_system<ScriptSystem>().update();
- this->get_system<PhysicsSystem>().update();
- this->get_system<CollisionSystem>().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>(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<InputSystem>().update();
+ this->event_manager.dispatch_events();
+ this->get_system<ScriptSystem>().update();
+ this->get_system<PhysicsSystem>().update();
+ this->get_system<CollisionSystem>().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<AnimatorSystem>().update();
+ //render
this->get_system<RenderSystem>().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();
@@ -52,13 +52,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.
*
* Updates the game state based on the elapsed time since the last frame.
@@ -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<std::chrono::milliseconds>(fixed_delta_time);
- this->delta_time = std::chrono::milliseconds(0);
+ = -std::chrono::duration_cast<ElapsedTime_t>(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<std::chrono::duration<double>>(
- 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<ElapsedTime_t>(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<ElapsedTime_t>(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<double>(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<double> 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<double>(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<float> Duration_t;
+typedef std::chrono::duration<unsigned long long, std::micro> 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<double> maximum_delta_time{0.25};
- //! Delta time for the current frame in seconds
- std::chrono::duration<double> 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<double> frame_target_time
- = std::chrono::duration<double>(1.0) / target_fps;
- //! Fixed delta time for fixed updates in seconds
- std::chrono::duration<double> fixed_delta_time = std::chrono::duration<double>(1.0) / 50.0;
- //! Total elapsed game time in seconds
- std::chrono::duration<double> elapsed_time{0.0};
- //! Total elapsed time for fixed updates in seconds
- std::chrono::duration<double> 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<Animator> animations = mgr.get_components_by_type<Animator>();
- 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>(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<double>(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_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<seconds>(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<std::chrono::duration<double>>(end_time - start_time).count();
+ auto elapsed_time = std::chrono::duration_cast<ElapsedTime_t>(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);
}