Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarPeriodic.hpp
blob: 4940c1df7f9a45907a24949b8c3535d924689373 (plain)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#pragma once

#include "StarMathCommon.hpp"
#include "StarRandom.hpp"

namespace Star {

// Perform some action every X ticks.  Setting the tick count to 0 means never
// perform the action, 1 performs the action every call, 2 performs the action
// every other call, and so forth.
class Periodic {
public:
  Periodic(unsigned everyXSteps = 1)
    : m_counter(0), m_everyXSteps(everyXSteps) {}

  unsigned stepCount() const {
    return m_everyXSteps;
  }

  void setStepCount(unsigned everyXSteps) {
    m_everyXSteps = everyXSteps;
    if (everyXSteps != 0)
      m_counter = clamp<unsigned>(m_counter, 0, m_everyXSteps - 1);
    else
      m_counter = 0;
  }

  // Will the next tick() return true?
  bool ready() const {
    return m_everyXSteps != 0 && m_counter == 0;
  }

  bool tick() {
    if (m_everyXSteps == 0)
      return false;

    if (m_counter == 0) {
      m_counter = m_everyXSteps - 1;
      return true;
    } else {
      --m_counter;
      return false;
    }
  }

  template <typename Function>
  void tick(Function&& function) {
    if (tick())
      function();
  }

private:
  unsigned m_counter;
  unsigned m_everyXSteps;
};

// Perform some action with a given period over an amount of some value (like
// time) with optional randomness.
class RatePeriodic {
public:
  RatePeriodic(double period = 1, double noise = 0)
    : m_period(period), m_noise(noise), m_counter(period + Random::randf(-noise, noise)), m_elapsed(0.0) {}

  double period() const {
    return m_period;
  }

  double noise() const {
    return m_noise;
  }

  template <typename Function>
  void update(double amount, Function&& function) {
    double subAmount = min(amount, m_counter);
    m_counter -= subAmount;
    amount -= subAmount;
    m_elapsed += subAmount;

    if (m_counter <= 0.0) {
      m_counter = m_period + Random::randf(-m_noise, m_noise);
      function(m_elapsed);
      m_elapsed = 0.0;
      if (amount > 0.0)
        update(amount, forward<Function>(function));
    }
  }

private:
  double m_period;
  double m_noise;
  double m_counter;
  double m_elapsed;
};

}