aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/manager
diff options
context:
space:
mode:
authorheavydemon21 <nielsstunnebrink1@gmail.com>2024-12-11 19:50:53 +0100
committerheavydemon21 <nielsstunnebrink1@gmail.com>2024-12-11 19:50:53 +0100
commite324ccb9b385b22db99575826a86501faba3a49d (patch)
tree8f245afc5662ac11a9e6433f3d7fa5f8f8c0e0a3 /src/crepe/manager
parent9732dd4d51fa4a5115b639b090cca96574719380 (diff)
parent59954bfc14cdb32997a3fb09e6ee1b393a4dc027 (diff)
Merge branch 'master' into niels/UI
Diffstat (limited to 'src/crepe/manager')
-rw-r--r--src/crepe/manager/CMakeLists.txt2
-rw-r--r--src/crepe/manager/EventManager.cpp6
-rw-r--r--src/crepe/manager/EventManager.h23
-rw-r--r--src/crepe/manager/LoopTimerManager.cpp91
-rw-r--r--src/crepe/manager/LoopTimerManager.h175
-rw-r--r--src/crepe/manager/Mediator.h10
-rw-r--r--src/crepe/manager/SceneManager.cpp3
7 files changed, 282 insertions, 28 deletions
diff --git a/src/crepe/manager/CMakeLists.txt b/src/crepe/manager/CMakeLists.txt
index 480c8ee..f73e165 100644
--- a/src/crepe/manager/CMakeLists.txt
+++ b/src/crepe/manager/CMakeLists.txt
@@ -4,6 +4,7 @@ target_sources(crepe PUBLIC
Manager.cpp
SaveManager.cpp
SceneManager.cpp
+ LoopTimerManager.cpp
ResourceManager.cpp
)
@@ -17,6 +18,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
SaveManager.h
SceneManager.h
SceneManager.hpp
+ LoopTimerManager.h
ResourceManager.h
ResourceManager.hpp
)
diff --git a/src/crepe/manager/EventManager.cpp b/src/crepe/manager/EventManager.cpp
index 20f0dd3..6aa49ee 100644
--- a/src/crepe/manager/EventManager.cpp
+++ b/src/crepe/manager/EventManager.cpp
@@ -3,11 +3,9 @@
using namespace crepe;
using namespace std;
-EventManager & EventManager::get_instance() {
- static EventManager instance;
- return instance;
+EventManager::EventManager(Mediator & mediator) : Manager(mediator) {
+ this->mediator.event_manager = *this;
}
-
void EventManager::dispatch_events() {
for (auto & event : this->events_queue) {
this->handle_event(event.type, event.channel, *event.event.get());
diff --git a/src/crepe/manager/EventManager.h b/src/crepe/manager/EventManager.h
index ba5e98b..639e37f 100644
--- a/src/crepe/manager/EventManager.h
+++ b/src/crepe/manager/EventManager.h
@@ -8,6 +8,8 @@
#include "../api/Event.h"
#include "../api/EventHandler.h"
+#include "Manager.h"
+
namespace crepe {
//! Event listener unique ID
@@ -22,27 +24,19 @@ typedef size_t subscription_t;
typedef size_t event_channel_t;
/**
- * \class EventManager
* \brief Manages event subscriptions, triggers, and queues, enabling decoupled event handling.
*
* The `EventManager` acts as a centralized event system. It allows for registering callbacks
* for specific event types, triggering events synchronously, queueing events for later
* processing, and managing subscriptions via unique identifiers.
*/
-class EventManager {
+class EventManager : public Manager {
public:
static constexpr const event_channel_t CHANNEL_ALL = -1;
-
/**
- * \brief Get the singleton instance of the EventManager.
- *
- * This method returns the unique instance of the EventManager, creating it if it
- * doesn't already exist. Ensures only one instance is active in the program.
- *
- * \return Reference to the singleton instance of the EventManager.
+ * \param mediator A reference to a Mediator object used for transfering managers.
*/
- static EventManager & get_instance();
-
+ EventManager(Mediator & mediator);
/**
* \brief Subscribe to a specific event type.
*
@@ -108,13 +102,6 @@ public:
private:
/**
- * \brief Default constructor for the EventManager.
- *
- * Constructor is private to enforce the singleton pattern.
- */
- EventManager() = default;
-
- /**
* \struct QueueEntry
* \brief Represents an entry in the event queue.
*/
diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp
new file mode 100644
index 0000000..9819632
--- /dev/null
+++ b/src/crepe/manager/LoopTimerManager.cpp
@@ -0,0 +1,91 @@
+#include <chrono>
+#include <thread>
+
+#include "../util/Log.h"
+
+#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();
+}
+
+void LoopTimerManager::start() {
+ this->last_frame_time = std::chrono::steady_clock::now();
+
+ this->elapsed_time = elapsed_time_t{0};
+ this->elapsed_fixed_time = elapsed_time_t{0};
+ this->delta_time = duration_t{0};
+}
+
+void LoopTimerManager::update() {
+ 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;
+
+ if (this->delta_time > this->maximum_delta_time) {
+ this->delta_time = this->maximum_delta_time;
+ }
+ if (this->delta_time > 0s) {
+ this->actual_fps = 1.0 / duration_cast<seconds>(this->delta_time).count();
+ } else {
+ this->actual_fps = 0;
+ }
+ 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;
+}
+
+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<elapsed_time_t>(this->fixed_delta_time);
+}
+
+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 = duration_t(1s) / this->target_fps;
+}
+
+unsigned LoopTimerManager::get_fps() const { return this->actual_fps; }
+
+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() {
+ 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) {
+ 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_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);
+}
+
+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
new file mode 100644
index 0000000..91403e4
--- /dev/null
+++ b/src/crepe/manager/LoopTimerManager.h
@@ -0,0 +1,175 @@
+#pragma once
+
+#include <chrono>
+
+#include "Manager.h"
+
+namespace crepe {
+
+typedef std::chrono::duration<double> duration_t;
+typedef std::chrono::duration<unsigned long long, std::micro> elapsed_time_t;
+
+/**
+ * \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:
+ /**
+ * \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.
+ *
+ * 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.
+ */
+ duration_t get_delta_time() const;
+
+ /**
+ * \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.
+ */
+ elapsed_time_t get_elapsed_time() const;
+
+ /**
+ * \brief Set the target frames per second (FPS).
+ *
+ * \param fps The desired frames rendered per second.
+ */
+ void set_target_framerate(unsigned fps);
+
+ /**
+ * \brief Get the current frames per second (FPS).
+ *
+ * \return Current FPS.
+ */
+ unsigned get_fps() const;
+
+ /**
+ * \brief Get the current time scale.
+ *
+ * \return The current time scale, where (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up).
+ * up the game.
+ */
+ float get_time_scale() const;
+
+ /**
+ * \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 time_scale The desired time scale (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up).
+ */
+ void set_time_scale(double time_scale);
+
+ /**
+ * \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.
+ */
+ duration_t get_fixed_delta_time() const;
+
+ /**
+ * \brief Set the 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(float 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.
+ */
+ 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.
+ *
+ * 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 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.
+ */
+ duration_t 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 Progress the elapsed fixed time by the fixed delta time interval.
+ *
+ * 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_elapsed_time();
+
+private:
+ //! Target frames per second.
+ unsigned target_fps = 60;
+ //! Actual frames per second.
+ 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.
+ 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
+ duration_t frame_target_time{1.0 / target_fps};
+ //! Fixed delta time for fixed updates in seconds.
+ duration_t fixed_delta_time{1.0 / 50.0};
+ //! Total elapsed game time in microseconds.
+ elapsed_time_t elapsed_time{0};
+ //! Total elapsed time for fixed updates in microseconds.
+ elapsed_time_t elapsed_fixed_time{0};
+
+ typedef std::chrono::steady_clock::time_point time_point_t;
+ //! Time of the last frame.
+ time_point_t last_frame_time;
+};
+
+} // namespace crepe
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h
index 628154a..a336410 100644
--- a/src/crepe/manager/Mediator.h
+++ b/src/crepe/manager/Mediator.h
@@ -2,17 +2,15 @@
#include "../util/OptionalRef.h"
-// TODO: remove these singletons:
-#include "EventManager.h"
-
namespace crepe {
class ComponentManager;
class SceneManager;
+class EventManager;
+class LoopTimerManager;
class SaveManager;
class ResourceManager;
class SDLContext;
-class LoopTimer;
/**
* Struct to pass references to classes that would otherwise need to be singletons down to
@@ -30,10 +28,10 @@ struct Mediator {
OptionalRef<SDLContext> sdl_context;
OptionalRef<ComponentManager> component_manager;
OptionalRef<SceneManager> scene_manager;
+ OptionalRef<EventManager> event_manager;
+ OptionalRef<LoopTimerManager> loop_timer;
OptionalRef<SaveManager> save_manager;
- OptionalRef<EventManager> event_manager = EventManager::get_instance();
OptionalRef<ResourceManager> resource_manager;
- OptionalRef<LoopTimer> timer;
};
} // namespace crepe
diff --git a/src/crepe/manager/SceneManager.cpp b/src/crepe/manager/SceneManager.cpp
index 50a9fbb..d4ca90b 100644
--- a/src/crepe/manager/SceneManager.cpp
+++ b/src/crepe/manager/SceneManager.cpp
@@ -32,4 +32,7 @@ void SceneManager::load_next_scene() {
// Load the new scene
scene->load_scene();
+
+ //clear the next scene
+ next_scene.clear();
}