diff options
author | hop311 <hop3114@gmail.com> | 2023-12-28 16:16:41 +0100 |
---|---|---|
committer | hop311 <hop3114@gmail.com> | 2023-12-28 16:16:41 +0100 |
commit | 12a47833bbe72d50271bde15c7579c1e801863c2 (patch) | |
tree | 8f67577b0101c06e2a7cc4d4c277d686d16d3d75 /src/openvic-simulation/misc | |
parent | 56a865d7d0868b785eb6b9b723f0e52f65e6457d (diff) |
Clock refactor + misc small fixes
Diffstat (limited to 'src/openvic-simulation/misc')
-rw-r--r-- | src/openvic-simulation/misc/GameAdvancementHook.cpp | 72 | ||||
-rw-r--r-- | src/openvic-simulation/misc/GameAdvancementHook.hpp | 47 | ||||
-rw-r--r-- | src/openvic-simulation/misc/SimulationClock.cpp | 69 | ||||
-rw-r--r-- | src/openvic-simulation/misc/SimulationClock.hpp | 59 |
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(); + }; +} |