#pragma once #include #include "Manager.h" namespace crepe { class Engine; typedef std::chrono::duration duration_t; typedef std::chrono::duration 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