35#ifndef LIBTCOD_TIMER_HPP_
36#define LIBTCOD_TIMER_HPP_
38#include <SDL3/SDL_timer.h>
68class [[nodiscard]] Timer {
73 Timer() : last_time_{SDL_GetPerformanceCounter()} {}
84 float sync(
int desired_fps = 0) {
85 const uint64_t frequency = SDL_GetPerformanceFrequency();
86 uint64_t current_time = SDL_GetPerformanceCounter();
87 int64_t delta_time =
static_cast<int64_t
>(current_time - last_time_);
88 if (desired_fps > 0) {
89 const int64_t desired_delta_time = frequency / desired_fps;
90 const int64_t time_until_next_frame_ms =
91 (desired_delta_time - delta_time) * 1000 /
static_cast<int64_t
>(frequency);
92 if (time_until_next_frame_ms > 2) {
94 SDL_Delay(
static_cast<uint32_t
>(time_until_next_frame_ms) - 1);
96 while (delta_time < desired_delta_time) {
97 current_time = SDL_GetPerformanceCounter();
98 delta_time =
static_cast<int64_t
>(current_time - last_time_);
101 last_time_ = current_time;
102 const float delta_time_s = std::max(0.0f,
static_cast<float>(delta_time) / frequency);
104 double total_time = std::accumulate(samples_.begin(), samples_.end(), 0.0);
105 while (!samples_.empty() && (total_time > MAX_SAMPLES_TIME || samples_.size() >= MAX_SAMPLES_COUNT)) {
106 total_time -= samples_.front();
107 samples_.pop_front();
109 samples_.push_back(delta_time_s);
115 [[nodiscard]]
float get_mean_fps() const noexcept {
116 if (samples_.empty())
return 0;
117 const double total_time = std::accumulate(samples_.begin(), samples_.end(), 0.0);
118 if (total_time == 0)
return 0;
119 return 1.0f /
static_cast<float>(total_time /
static_cast<double>(samples_.size()));
124 [[nodiscard]]
float get_last_fps() const noexcept {
125 if (samples_.empty())
return 0;
126 if (samples_.back() == 0)
return 0;
127 return 1.0f / samples_.back();
132 [[nodiscard]]
float get_min_fps() const noexcept {
133 if (samples_.empty())
return 0;
134 const float sample = *std::max_element(samples_.begin(), samples_.end());
135 if (sample == 0)
return 0;
136 return 1.0f / sample;
141 [[nodiscard]]
float get_max_fps() const noexcept {
142 if (samples_.empty())
return 0;
143 const float sample = *std::min_element(samples_.begin(), samples_.end());
144 if (sample == 0)
return 0;
145 return 1.0f / sample;
150 [[nodiscard]]
float get_median_fps() const noexcept {
151 if (samples_.empty())
return 0;
152 std::vector<float> samples(samples_.begin(), samples_.end());
153 std::sort(samples.begin(), samples.end());
154 float median_sample = samples[samples.size() / 2];
155 if (samples.size() % 2 == 0 && samples.size() > 2) {
156 median_sample = (median_sample + samples[samples.size() / 2 + 1]) / 2.0f;
158 if (median_sample == 0)
return 0;
159 return 1.0f / median_sample;
163 static constexpr size_t MAX_SAMPLES_COUNT = 1024;
164 static constexpr double MAX_SAMPLES_TIME = 1.0;
167 std::deque<float> samples_;
The libtcod namespace.
Definition color.hpp:45