aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/api/LoopTimer.h
blob: fb52a100004eced1eae481e41d33da9b3e86e000 (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
#pragma once

#include "manager/Manager.h"
#include <chrono>

namespace crepe {

class LoopTimer : public Manager {
public:
	/**
	 * \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 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_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 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 fixed delta time for consistent updates.
	 *
	 * Fixed delta time is used for operations that require uniform time steps, such as physics
	 * calculations.
	 *
	 * \return Fixed delta time in seconds.
	 */
	double get_fixed_delta_time() const;

	/**
	 * \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 Construct a new LoopTimer object.
	 *
	 * Private constructor for singleton pattern to restrict instantiation outside the class.
	 */
	LoopTimer(Mediator & mediator);

	/**
	 * \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:
	//! Current frames per second
	int fps = 50;
	//! Current game scale
	double game_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) / 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