aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/crepe/api/LoopManager.cpp60
-rw-r--r--src/crepe/api/LoopManager.h66
-rw-r--r--src/crepe/api/LoopTimer.cpp58
-rw-r--r--src/crepe/api/LoopTimer.h81
-rw-r--r--src/crepe/facade/SDLContext.cpp3
-rw-r--r--src/crepe/facade/SDLContext.h13
-rw-r--r--src/example/CMakeLists.txt1
-rw-r--r--src/example/gameloop.cpp7
-rw-r--r--src/makefile7
9 files changed, 292 insertions, 4 deletions
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
new file mode 100644
index 0000000..5c79920
--- /dev/null
+++ b/src/crepe/api/LoopManager.cpp
@@ -0,0 +1,60 @@
+
+#include "../system/RenderSystem.h"
+#include "../system/ScriptSystem.h"
+#include "../facade/SDLContext.h"
+
+#include "LoopManager.h"
+#include "LoopTimer.h"
+
+namespace crepe {
+
+void LoopManager::process_input() {
+ SDLContext::get_instance().handle_events(this->game_running);
+}
+void LoopManager::start(){
+ this->setup();
+ this->loop();
+}
+void LoopManager::set_running(bool running) { this->game_running = running; }
+
+void LoopManager::fixed_update() {
+}
+
+void LoopManager::loop() {
+ LoopTimer & timer = LoopTimer::get_instance();
+ timer.start();
+
+ while (game_running) {
+ timer.update();
+
+ while (timer.get_lag() >= timer.get_fixed_delta_time()) {
+ process_input();
+ fixed_update();
+ timer.advance_fixed_update();
+ }
+
+ update();
+ render();
+
+ timer.enforce_frame_rate();
+ }
+}
+
+
+void LoopManager::setup() {
+ this->game_running = true;
+ LoopTimer::get_instance().start();
+ LoopTimer::get_instance().set_fps(60);
+}
+
+void LoopManager::render() {
+ if (game_running) {
+ RenderSystem::get_instance().update();
+ }
+}
+
+void LoopManager::update() {
+ LoopTimer & timer = LoopTimer::get_instance();
+}
+
+} // namespace crepe
diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h
new file mode 100644
index 0000000..8899bfd
--- /dev/null
+++ b/src/crepe/api/LoopManager.h
@@ -0,0 +1,66 @@
+#pragma once
+
+namespace crepe {
+
+class LoopManager {
+ public:
+ void start();
+
+ private:
+ /**
+ * \brief Setup function for one-time initialization.
+ *
+ * This function initializes necessary components for the game.
+ */
+ void setup();
+ /**
+ * \brief Main game loop function.
+ *
+ * This function runs the main loop, handling game updates and rendering.
+ */
+ 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.
+ */
+ void update();
+
+ /**
+ * \brief Late update which is called after update().
+ *
+ * This function can be used for final adjustments before rendering.
+ */
+ void late_update();
+
+ /**
+ * \brief Fixed update executed at a fixed rate.
+ *
+ * This function updates physics and game logic based on LoopTimer's fixed_delta_time.
+ */
+ void fixed_update();
+ /**
+ * \brief Set game running variable
+ *
+ * \param running running (false = game shutdown, true = game running)
+ */
+ void set_running(bool running);
+ /**
+ * \brief Function for executing render-related systems.
+ *
+ * Renders the current state of the game to the screen.
+ */
+ void render();
+
+ bool game_running = false;
+ };
+
+} // namespace crepe
diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp
new file mode 100644
index 0000000..98ce08d
--- /dev/null
+++ b/src/crepe/api/LoopTimer.cpp
@@ -0,0 +1,58 @@
+
+#include "../facade/SDLContext.h"
+
+#include "LoopTimer.h"
+
+using namespace crepe;
+LoopTimer::LoopTimer() {}
+
+LoopTimer & LoopTimer::get_instance() {
+ static LoopTimer instance;
+ return instance;
+}
+
+void LoopTimer::start() {
+ last_frame_time = SDLContext::get_instance().get_ticks();
+ elapsed_time = 0;
+ elapsed_fixed_time = 0;
+ delta_time = 0;
+}
+
+void LoopTimer::update() {
+ uint64_t current_frame_time = SDLContext::get_instance().get_ticks();
+ delta_time = (current_frame_time - last_frame_time) / 1000.0;
+
+ if (delta_time > maximum_delta_time) {
+ delta_time = maximum_delta_time;
+ }
+ delta_time = game_scale;
+ elapsed_time += delta_time;
+ last_frame_time = current_frame_time;
+}
+
+double LoopTimer::get_delta_time() const { return delta_time; }
+int LoopTimer::get_current_time() const { return elapsed_time; }
+
+void LoopTimer::advance_fixed_update() { elapsed_fixed_time += fixed_delta_time; }
+
+double LoopTimer::get_fixed_delta_time() const { return fixed_delta_time; }
+
+void LoopTimer::set_fps(int fps) {
+ this->fps = fps;
+ frame_target_time = 1.0 / fps;
+}
+
+int LoopTimer::get_fps() const { return fps; }
+void LoopTimer::set_game_scale(double value) { game_scale = value; };
+double LoopTimer::get_game_scale() const { return game_scale; }
+void LoopTimer::enforce_frame_rate() {
+ uint64_t current_frame_time = SDLContext::get_instance().get_ticks();
+ double frame_duration = (current_frame_time - last_frame_time) / 1000.0;
+
+ if (frame_duration < frame_target_time) {
+ uint32_t delay_time
+ = (uint32_t) ((frame_target_time - frame_duration) / 1000.0);
+ SDLContext::get_instance().delay(delay_time);
+ }
+}
+double LoopTimer::get_lag() const { return elapsed_time - elapsed_fixed_time; }
diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h
new file mode 100644
index 0000000..5b7d3f2
--- /dev/null
+++ b/src/crepe/api/LoopTimer.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <cstdint>
+
+namespace crepe{
+class LoopTimer {
+public:
+/**
+ * \brief Get the singleton instance of LoopTimer.
+ *
+ * \return A reference to the LoopTimer instance.
+ */
+static LoopTimer& get_instance();
+
+/**
+ * \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 the real-world elapsed time.
+ * It is the cumulative sum of each frame's delta time.
+ *
+ * \return Elapsed game time in milliseconds.
+ */
+int get_current_time() const;
+
+/**
+ * \brief Set the target frames per second (FPS).
+ *
+ * \param fps The number of frames that should be rendered per second.
+ */
+void set_fps(int fps);
+
+/**
+ * \brief Get the current frames per second (FPS).
+ *
+ * \return Current FPS.
+ */
+int get_fps() const;
+
+/**
+ * \brief Get the current game scale.
+ *
+ * \return The current game scale, where 0 = paused, 1 = normal speed, and values > 1 speed up the game.
+ */
+double get_game_scale() const;
+
+/**
+ * \brief Set the game scale.
+ *
+ * \param game_scale The desired game scale (0 = pause, 1 = normal speed, > 1 = speed up).
+ */
+void set_game_scale(double game_scale);
+
+private:
+friend class LoopManager;
+void start();
+void enforce_frame_rate();
+double get_fixed_delta_time() const;
+double get_lag() const;
+LoopTimer();
+void update();
+void advance_fixed_update();
+private:
+int fps = 50; ///< Current frames per second
+double game_scale = 1; ///< Current game scale
+double maximum_delta_time = 0.25; ///< Maximum delta time to avoid large jumps
+double delta_time = 0; ///< Delta time for the current frame
+double frame_target_time = 1.0 / fps; ///< Target time per frame in seconds
+double fixed_delta_time = 0.02; ///< Fixed delta time for fixed updates
+double elapsed_time = 0; ///< Total elapsed game time
+double elapsed_fixed_time = 0; ///< Total elapsed time for fixed updates
+uint64_t last_frame_time = 0; ///< Time of the last frame
+};
+
+} // namespace crepe
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp
index c4c96e2..17ced0c 100644
--- a/src/crepe/facade/SDLContext.cpp
+++ b/src/crepe/facade/SDLContext.cpp
@@ -191,3 +191,6 @@ int SDLContext::get_height(const Texture & ctx) const {
SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h);
return h;
}
+void SDLContext::delay(int ms) const{
+ SDL_Delay(ms);
+}
diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h
index e358c21..6c57ef9 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -58,13 +58,22 @@ private:
private:
//! Will only use get_ticks
friend class AnimatorSystem;
-
+ friend class LoopTimer;
/**
* \brief Gets the current SDL ticks since the program started.
* \return Current ticks in milliseconds as a constant uint64_t.
*/
uint64_t get_ticks() const;
-
+ /**
+ * \brief Pauses the execution for a specified duration.
+ *
+ * This function uses SDL's delay function to halt the program execution
+ * for a given number of milliseconds, allowing for frame rate control
+ * or other timing-related functionality.
+ *
+ * \param ms Duration of the delay in milliseconds.
+ */
+ void delay(int ms) const;
private:
/**
* \brief Constructs an SDLContext instance.
diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt
index 36f9d4d..c8a4b85 100644
--- a/src/example/CMakeLists.txt
+++ b/src/example/CMakeLists.txt
@@ -28,4 +28,5 @@ add_example(proxy)
add_example(db)
add_example(ecs)
add_example(scene_manager)
+add_example(gameloop)
diff --git a/src/example/gameloop.cpp b/src/example/gameloop.cpp
new file mode 100644
index 0000000..6cd0301
--- /dev/null
+++ b/src/example/gameloop.cpp
@@ -0,0 +1,7 @@
+#include "crepe/api/LoopManager.h"
+using namespace crepe;
+int main(){
+ LoopManager gameloop;
+ gameloop.start();
+ return 1;
+}
diff --git a/src/makefile b/src/makefile
index b9c44c8..ce5a29f 100644
--- a/src/makefile
+++ b/src/makefile
@@ -94,8 +94,11 @@ LOEK += example/script.cpp
LOEK += test/audio.cpp
LOEK += test/dummy.cpp
JARO += test/PhysicsTest.cpp
-
-FMT := $(JARO) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2
+WOUTER += crepe/api/LoopManager.h
+WOUTER += crepe/api/LoopManager.cpp
+WOUTER += crepe/api/LoopTimer.h
+WOUTER += crepe/api/LoopTimer.cpp
+FMT := $(WOUTER) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2
format: FORCE
clang-tidy -p build/compile_commands.json --fix-errors $(FMT)