diff options
| -rw-r--r-- | src/crepe/api/LoopManager.cpp | 19 | ||||
| -rw-r--r-- | src/crepe/manager/LoopTimerManager.cpp | 47 | ||||
| -rw-r--r-- | src/crepe/manager/LoopTimerManager.h | 34 | ||||
| -rw-r--r-- | src/crepe/manager/Mediator.h | 6 | ||||
| -rw-r--r-- | src/crepe/system/AISystem.cpp | 8 | ||||
| -rw-r--r-- | src/test/LoopTimerTest.cpp | 10 | 
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);  } +  |