aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/manager/LoopTimerManager.h
blob: 46a0dcb9bd318c2d16d28c7cb8dd3dca0068cb46 (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
#pragma once

#include <chrono>

#include "Manager.h"

namespace crepe {

/**
 * \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.
	 */
	double get_delta_time() const;

	/**
	 * \brief Get the current game time.
	 *
	 * \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;

	/**
	 * \brief Set the target frames per second (FPS).
	 *
	 * \param fps The desired frames rendered per second.
	 */
	void set_target_fps(int fps);

	/**
	 * \brief Get the current frames per second (FPS).
	 *
	 * \return Current FPS.
	 */
	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.
	 */
	double 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.
	 * 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;

	/**
	 * \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.
	 * 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);

	/**
	 * \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.
	 */
	double 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.
	 */
	double 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 Advance the game loop by a fixed update interval.
	 *
	 * This method progresses the game state by a consistent, fixed time step, allowing for
	 * stable updates independent of frame rate fluctuations.
	 */
	void advance_fixed_update();

private:
	//! Target frames per second
	int target_fps = 60;
	//! 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};
	//! 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;
};

} // namespace crepe