osb/source/game/StarGameTimers.cpp
2023-06-20 14:33:09 +10:00

163 lines
3.4 KiB
C++

#include "StarGameTimers.hpp"
#include "StarJsonExtra.hpp"
#include "StarDataStreamExtra.hpp"
namespace Star {
GameTimer::GameTimer() : time(), timer() {}
GameTimer::GameTimer(float time) : time(time) {
reset();
}
bool GameTimer::tick(float dt) {
timer = approach(0.0f, timer, dt);
return timer == 0.0f;
}
bool GameTimer::ready() const {
return timer == 0.0f;
}
bool GameTimer::wrapTick(float dt) {
auto res = tick(dt);
if (res)
reset();
return res;
}
void GameTimer::reset() {
timer = time;
}
void GameTimer::setDone() {
timer = 0.0f;
}
void GameTimer::invert() {
timer = time - timer;
}
float GameTimer::percent() const {
if (time)
return timer / time;
else
return 0.0f;
}
DataStream& operator>>(DataStream& ds, GameTimer& gt) {
ds >> gt.time;
ds >> gt.timer;
return ds;
}
DataStream& operator<<(DataStream& ds, GameTimer const& gt) {
ds << gt.time;
ds << gt.timer;
return ds;
}
SlidingWindow::SlidingWindow() : windowSize(1.0f), resolution(1) {}
SlidingWindow::SlidingWindow(float windowSize, size_t resolution, float initialValue)
: windowSize(windowSize), resolution(resolution) {
sampleTimer = GameTimer(windowSize / resolution);
window = std::vector<float>(resolution);
reset(initialValue);
}
void SlidingWindow::reset(float initialValue) {
sampleTimer.reset();
currentIndex = 0;
currentMin = initialValue;
currentMax = initialValue;
currentAverage = initialValue;
std::fill(window.begin(), window.end(), initialValue);
}
void SlidingWindow::update(function<float()> sampleFunction) {
if (sampleTimer.wrapTick()) {
processUpdate(sampleFunction());
}
}
void SlidingWindow::update(float newValue) {
if (sampleTimer.wrapTick()) {
processUpdate(newValue);
}
}
void SlidingWindow::processUpdate(float newValue) {
++currentIndex;
currentIndex = currentIndex % resolution;
window[currentIndex] = newValue;
currentMin = std::numeric_limits<float>::max();
currentMax = 0;
float total = 0;
for (float v : window) {
total += v;
currentMin = std::min(currentMin, v);
currentMax = std::max(currentMax, v);
}
currentAverage = total / resolution;
}
float SlidingWindow::min() {
return currentMin;
}
float SlidingWindow::max() {
return currentMax;
}
float SlidingWindow::average() {
return currentAverage;
}
EpochTimer::EpochTimer() : m_elapsedTime(0.0) {}
EpochTimer::EpochTimer(Json json) {
m_lastSeenEpochTime = json.get("lastEpochTime").optDouble();
m_elapsedTime = json.getDouble("elapsedTime");
}
Json EpochTimer::toJson() const {
return JsonObject{{"lastEpochTime", jsonFromMaybe(m_lastSeenEpochTime)}, {"elapsedTime", m_elapsedTime}};
}
void EpochTimer::update(double newEpochTime) {
if (!m_lastSeenEpochTime) {
m_lastSeenEpochTime = newEpochTime;
} else {
// Don't allow elapsed time to go backwards in the case of the epoch time
// being lost or wrong.
double difference = newEpochTime - *m_lastSeenEpochTime;
if (difference > 0)
m_elapsedTime += difference;
m_lastSeenEpochTime = newEpochTime;
}
}
double EpochTimer::elapsedTime() const {
return m_elapsedTime;
}
void EpochTimer::setElapsedTime(double elapsedTime) {
m_elapsedTime = elapsedTime;
}
DataStream& operator>>(DataStream& ds, EpochTimer& et) {
ds >> et.m_lastSeenEpochTime;
ds >> et.m_elapsedTime;
return ds;
}
DataStream& operator<<(DataStream& ds, EpochTimer const& et) {
ds << et.m_lastSeenEpochTime;
ds << et.m_elapsedTime;
return ds;
}
}