aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/manager/LoopTimerManager.h
blob: 2f1e6b6f9d14e1309b41d60d4e0e96a3d018a473 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#pragma once

#include <chrono>

#include "Manager.h"

namespace crepe {

class Engine;

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.
 * 
 * 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 int 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 Engine;
	/**
	 * \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 int target_fps = 60;
	//! Actual frames per second.
	unsigned 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).
	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