aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/misc/SimulationClock.hpp
blob: fbf793080ce3564afa200b23a8da1716e1935b64 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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();
   };
}