aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/misc
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/misc')
-rw-r--r--src/openvic-simulation/misc/GameAdvancementHook.cpp72
-rw-r--r--src/openvic-simulation/misc/GameAdvancementHook.hpp47
-rw-r--r--src/openvic-simulation/misc/SimulationClock.cpp69
-rw-r--r--src/openvic-simulation/misc/SimulationClock.hpp59
4 files changed, 128 insertions, 119 deletions
diff --git a/src/openvic-simulation/misc/GameAdvancementHook.cpp b/src/openvic-simulation/misc/GameAdvancementHook.cpp
deleted file mode 100644
index f4c0adc..0000000
--- a/src/openvic-simulation/misc/GameAdvancementHook.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "GameAdvancementHook.hpp"
-
-using namespace OpenVic;
-
-const std::vector<std::chrono::milliseconds> GameAdvancementHook::GAME_SPEEDS = {
- std::chrono::milliseconds { 3000 }, std::chrono::milliseconds { 2000 }, std::chrono::milliseconds { 1000 },
- std::chrono::milliseconds { 100 }, std::chrono::milliseconds { 1 }
-};
-
-GameAdvancementHook::GameAdvancementHook(
- AdvancementFunction tick_function, RefreshFunction update_function, bool start_paused, speed_t starting_speed
-)
- : trigger_function { tick_function }, refresh_function { update_function }, is_paused { start_paused } {
- last_polled_time = std::chrono::high_resolution_clock::now();
- set_simulation_speed(starting_speed);
-}
-
-void GameAdvancementHook::set_simulation_speed(speed_t speed) {
- if (speed < 0) {
- current_speed = 0;
- } else if (speed >= GAME_SPEEDS.size()) {
- current_speed = GAME_SPEEDS.size() - 1;
- } else {
- current_speed = speed;
- }
-}
-
-void GameAdvancementHook::increase_simulation_speed() {
- set_simulation_speed(current_speed + 1);
-}
-
-void GameAdvancementHook::decrease_simulation_speed() {
- set_simulation_speed(current_speed - 1);
-}
-
-bool GameAdvancementHook::can_increase_simulation_speed() const {
- return current_speed + 1 < GAME_SPEEDS.size();
-}
-
-bool GameAdvancementHook::can_decrease_simulation_speed() const {
- return current_speed > 0;
-}
-
-GameAdvancementHook& GameAdvancementHook::operator++() {
- increase_simulation_speed();
- return *this;
-};
-
-GameAdvancementHook& GameAdvancementHook::operator--() {
- decrease_simulation_speed();
- return *this;
-};
-
-void GameAdvancementHook::conditionally_advance_game() {
- if (!is_paused) {
- time_point_t currentTime = std::chrono::high_resolution_clock::now();
- if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - last_polled_time) >= GAME_SPEEDS[current_speed]) {
- last_polled_time = currentTime;
- if (trigger_function) {
- trigger_function();
- }
- }
- }
- if (refresh_function) {
- refresh_function();
- }
-}
-
-void GameAdvancementHook::reset() {
- is_paused = true;
- current_speed = 0;
-}
diff --git a/src/openvic-simulation/misc/GameAdvancementHook.hpp b/src/openvic-simulation/misc/GameAdvancementHook.hpp
deleted file mode 100644
index 75af718..0000000
--- a/src/openvic-simulation/misc/GameAdvancementHook.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include <chrono>
-#include <functional>
-#include <vector>
-#include "openvic-simulation/utility/Getters.hpp"
-
-namespace OpenVic {
- // Conditionally advances game with provided behaviour
- // Class governs game speed and pause state
- class GameAdvancementHook {
- public:
- using AdvancementFunction = std::function<void()>;
- using RefreshFunction = std::function<void()>;
- using speed_t = int8_t;
-
- // Minimum number of miliseconds before the simulation advances
- static const std::vector<std::chrono::milliseconds> GAME_SPEEDS;
-
- private:
- using time_point_t = std::chrono::time_point<std::chrono::high_resolution_clock>;
-
- time_point_t last_polled_time;
- // A function pointer that advances the simulation, intended to be a capturing
- // lambda or something similar. May need to be reworked later
- AdvancementFunction trigger_function;
- RefreshFunction refresh_function;
- speed_t PROPERTY_CUSTOM_NAME(current_speed, get_simulation_speed);
-
- public:
- bool is_paused;
-
- GameAdvancementHook(
- AdvancementFunction tick_function, RefreshFunction update_function, bool start_paused = true, speed_t starting_speed = 0
- );
-
- void set_simulation_speed(speed_t speed);
- void increase_simulation_speed();
- void decrease_simulation_speed();
- bool can_increase_simulation_speed() const;
- bool can_decrease_simulation_speed() const;
- GameAdvancementHook& operator++();
- GameAdvancementHook& operator--();
- void conditionally_advance_game();
- void reset();
- };
-}
diff --git a/src/openvic-simulation/misc/SimulationClock.cpp b/src/openvic-simulation/misc/SimulationClock.cpp
new file mode 100644
index 0000000..324811c
--- /dev/null
+++ b/src/openvic-simulation/misc/SimulationClock.cpp
@@ -0,0 +1,69 @@
+#include "SimulationClock.hpp"
+
+#include <algorithm>
+
+using namespace OpenVic;
+
+SimulationClock::SimulationClock(
+ tick_function_t new_tick_function, update_function_t new_update_function,
+ state_changed_function_t new_state_changed_function
+) : tick_function { new_tick_function ? std::move(new_tick_function) : []() {} },
+ update_function { new_update_function ? std::move(new_update_function) : []() {} },
+ state_changed_function { new_state_changed_function ? std::move(new_state_changed_function) : []() {} } {
+ reset();
+}
+
+void SimulationClock::set_paused(bool new_paused) {
+ if (paused != new_paused) {
+ toggle_paused();
+ }
+}
+
+void SimulationClock::toggle_paused() {
+ paused = !paused;
+ state_changed_function();
+}
+
+void SimulationClock::set_simulation_speed(speed_t speed) {
+ speed = std::clamp(speed, MIN_SPEED, MAX_SPEED);
+ if (current_speed != speed) {
+ current_speed = speed;
+ state_changed_function();
+ }
+}
+
+void SimulationClock::increase_simulation_speed() {
+ set_simulation_speed(current_speed + 1);
+}
+
+void SimulationClock::decrease_simulation_speed() {
+ set_simulation_speed(current_speed - 1);
+}
+
+bool SimulationClock::can_increase_simulation_speed() const {
+ return current_speed < MAX_SPEED;
+}
+
+bool SimulationClock::can_decrease_simulation_speed() const {
+ return current_speed > MIN_SPEED;
+}
+
+void SimulationClock::conditionally_advance_game() {
+ if (!paused) {
+ const time_point_t current_time = std::chrono::high_resolution_clock::now();
+ const std::chrono::milliseconds time_since_last_tick =
+ std::chrono::duration_cast<std::chrono::milliseconds>(current_time - last_tick_time);
+ if (time_since_last_tick >= GAME_SPEEDS[current_speed]) {
+ last_tick_time = current_time;
+ tick_function();
+ }
+ }
+ update_function();
+}
+
+void SimulationClock::reset() {
+ paused = true;
+ current_speed = 0;
+ last_tick_time = std::chrono::high_resolution_clock::now();
+ state_changed_function();
+}
diff --git a/src/openvic-simulation/misc/SimulationClock.hpp b/src/openvic-simulation/misc/SimulationClock.hpp
new file mode 100644
index 0000000..fbf7930
--- /dev/null
+++ b/src/openvic-simulation/misc/SimulationClock.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <chrono>
+#include <functional>
+#include <vector>
+
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ /* Conditionally advances game depending on speed and pause state. */
+ class SimulationClock {
+ public:
+ using tick_function_t = std::function<void()>;
+ using update_function_t = std::function<void()>;
+ using state_changed_function_t = std::function<void()>;
+ using speed_t = int8_t;
+
+ /* Minimum number of miliseconds before the simulation advances
+ * (in descending duration order, hence increasing speed order). */
+ static constexpr std::chrono::milliseconds GAME_SPEEDS[] {
+ std::chrono::milliseconds { 3000 }, std::chrono::milliseconds { 2000 }, std::chrono::milliseconds { 1000 },
+ std::chrono::milliseconds { 100 }, std::chrono::milliseconds { 1 }
+ };
+ static constexpr speed_t MIN_SPEED = 0, MAX_SPEED = std::size(GAME_SPEEDS) - 1;
+
+ private:
+ using time_point_t = std::chrono::time_point<std::chrono::high_resolution_clock>;
+
+ /* Advance simulation (triggered while unpaused at interval determined by speed). */
+ tick_function_t tick_function;
+ /* Refresh game state (triggered with every call to conditionally_advance_game). */
+ update_function_t update_function;
+ /* Callback for when speed or pause state is changed. */
+ state_changed_function_t state_changed_function;
+
+ time_point_t last_tick_time;
+ speed_t PROPERTY_CUSTOM_NAME(current_speed, get_simulation_speed);
+ bool PROPERTY_CUSTOM_PREFIX(paused, is);
+
+ public:
+
+ SimulationClock(
+ tick_function_t new_tick_function, update_function_t new_update_function,
+ state_changed_function_t new_state_changed_function
+ );
+
+ void set_paused(bool new_paused);
+ void toggle_paused();
+
+ void set_simulation_speed(speed_t speed);
+ void increase_simulation_speed();
+ void decrease_simulation_speed();
+ bool can_increase_simulation_speed() const;
+ bool can_decrease_simulation_speed() const;
+
+ void conditionally_advance_game();
+ void reset();
+ };
+}