TODO: インターバル
名前の通り。N秒ごとになにかする。改善の余地あり。
参照
code:interval.cpp
struct Interval
{
// ディスパッチ用のタグ
// 何回発火したかの値を返す版
inline static constexpr struct CountTag
{
} Count{};
// 何回発火したかの値を step した版
inline static constexpr struct CountRangeTag
{
} CountRange{};
// 何秒前に発火したかの正の値の配列を返す版
inline static constexpr struct TimesTag
{
} FireTimes{};
Interval(double m_intervalSec)
: m_intervalSec(m_intervalSec) {}
size_t update(CountTag = Count, double deltaTime = Scene::DeltaTime()) {
m_accumulatedTimeSec += deltaTime;
if (m_intervalSec == 0.0) { return 1; }
size_t count = m_accumulatedTimeSec / m_intervalSec;
m_accumulatedTimeSec = Math::Fmod(m_accumulatedTimeSec, m_intervalSec);
return count;
}
// 何回発火したかの値で std::views::iota した版
auto update(CountRangeTag, double deltaTime = Scene::DeltaTime()) {
m_accumulatedTimeSec += deltaTime;
if (m_intervalSec == 0.0) { return std::views::iota(size_t(1)); }
size_t count = m_accumulatedTimeSec / m_intervalSec;
m_accumulatedTimeSec = Math::Fmod(m_accumulatedTimeSec, m_intervalSec);
return std::views::iota(count);
}
// 何秒前に発火したかの正の値の配列
// generator にシたほうがいいかもしれない
Array<double> update(TimesTag, double deltaTime = Scene::DeltaTime()) {
m_accumulatedTimeSec += deltaTime;
if (m_intervalSec == 0.0) { return {0}; }
size_t count = m_accumulatedTimeSec / m_intervalSec;
m_accumulatedTimeSec = Math::Fmod(m_accumulatedTimeSec, m_intervalSec);
Array<double> res(count);
size_t i = 0;
std::generate(res.rbegin(), res.rend(), &() { return i++ * m_intervalSec; }); return res;
}
private:
double m_intervalSec = 0.0;
double m_accumulatedTimeSec = 0.0;
};
void Main() {
Interval interval{0.001};
while (System::Update())
{
// .update(Interval::Count) と同じ
for (auto&& c : step(interval.update())) { Print << c; }
for (auto&& c : interval.update(Interval::CountRange)) { Print << c; }
for (auto&& t : interval.update(Interval::FireTimes)) { Print << t; }
}
}