This commit is contained in:
2023-03-10 08:35:57 -08:00
parent f69312e9f9
commit 5c6436dd18
6 changed files with 161 additions and 106 deletions

Submodule lib/SDL updated: 87a83787a3...c9aec268fa

View File

@ -7,8 +7,6 @@
#include "state/State.hpp" #include "state/State.hpp"
namespace Dawn { namespace Dawn {
class SceneItemComponent;
template<typename D, typename...A> template<typename D, typename...A>
struct StateListener { struct StateListener {
std::function<void(A...)> callback; std::function<void(A...)> callback;
@ -17,37 +15,34 @@ namespace Dawn {
template<typename D, typename...A> template<typename D, typename...A>
struct StateProviderSet { struct StateProviderSet {
private: public:
std::vector<StateListener<D,A...>> listeners; std::vector<StateListener<D,A...>> listeners;
public: /**
* Attaches an effect listener that is invoked by a provider.
*
* @tparam T Context Type, usually the state listener itself.
* @param callback Callback method to be invoked by the provider.
* @param data Data to be stored with the StateListener.
* @param context Context for the state object.
* @return The unsubscribe method, when invoked, unsubs from the provider.
*/
template<class T>
std::function<void()> addEffect( std::function<void()> addEffect(
std::function<void(A...)> callback, std::function<void(A...)> callback,
D data D data,
T *context
) { ) {
struct StateListener<D, A...> l; struct StateListener<D, A...> l;
l.callback = callback; l.callback = callback;
l.data = data; l.data = data;
this->listeners.push_back(l); this->listeners.push_back(l);
l.callback();
return std::bind([&](struct StateListener<D, A...> listener) { return std::bind([&](struct StateListener<D, A...> listener) {
assertUnreachable(); auto it = std::find(listeners.begin(), listeners.end(), listener);
assertFalse(it == listeners.end());
listeners.erase(it);
}, l); }, l);
} }
}; };
class TimeProvider {
public:
StateProviderSet<float_t> effect;
};
std::function<void()> useTimeout(
std::function<void()> someCallback,
float_t timeout,
SceneItemComponent *context
) {
return (TimeProvider()).effect.addEffect(someCallback, timeout);
}
} }

View File

@ -1,32 +1,57 @@
// Copyright (c) 2022 Dominic Masters // Copyright (c) 2022 Dominic Masters
// //
// This software is released under the MIT License. // This software is released under the MIT License.
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#include "ITimeManager.hpp" #include "ITimeManager.hpp"
using namespace Dawn; using namespace Dawn;
ITimeManager::ITimeManager() { ITimeManager::ITimeManager() {
} }
void ITimeManager::update(float_t delta) { void ITimeManager::update(float_t delta) {
this->delta = delta; this->delta = delta;
this->time += delta; this->time += delta;
if(!this->isPaused) {
this->unpausedTime += delta; if(!this->isPaused) {
} this->unpausedTime += delta;
}
// Timeout effect provider
void ITimeManager::pause() { auto itEffect = this->timeoutProvider.listeners.begin();
if(this->isPaused) return; while(itEffect != this->timeoutProvider.listeners.end()) {
this->isPaused = true; itEffect->data -= delta;
this->eventTimePaused.invoke(); if(itEffect->data <= 0) {
} itEffect->callback();
itEffect = this->timeoutProvider.listeners.erase(itEffect);
void ITimeManager::resume() { continue;
if(!this->isPaused) return; }
this->isPaused = false; ++itEffect;
this->eventTimeResumed.invoke(); }
// Interval provider
auto itInterval = this->intervalProvider.listeners.begin();
while(itInterval != this->intervalProvider.listeners.end()) {
itInterval->data.second += delta;
if(itInterval->data.second >= itInterval->data.first) {
itInterval->callback();
itInterval->data.second = 0;
}
++itInterval;
}
}
}
void ITimeManager::pause() {
if(this->isPaused) return;
this->isPaused = true;
this->eventTimePaused.invoke();
}
void ITimeManager::resume() {
if(!this->isPaused) return;
this->isPaused = false;
this->eventTimeResumed.invoke();
} }

View File

@ -1,50 +1,85 @@
// Copyright (c) 2022 Dominic Masters // Copyright (c) 2022 Dominic Masters
// //
// This software is released under the MIT License. // This software is released under the MIT License.
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "dawnlibs.hpp" #include "dawnlibs.hpp"
#include "event/Event.hpp" #include "event/Event.hpp"
#include "state/StateProvider.hpp"
namespace Dawn {
class ITimeManager { namespace Dawn {
public: class ITimeManager {
float_t time = 0.0f; public:
float_t unpausedTime = 0.0f; float_t time = 0.0f;
float_t delta = 0.016f; float_t unpausedTime = 0.0f;
bool_t isPaused = false; float_t delta = 0.016f;
bool_t isPaused = false;
Event<> eventTimePaused;
Event<> eventTimeResumed; StateProviderSet<float_t> timeoutProvider;
StateProviderSet<std::pair<float_t, float_t>> intervalProvider;
/**
* Constructor for the Time Manager. Event<> eventTimePaused;
*/ Event<> eventTimeResumed;
ITimeManager();
/**
/** * Constructor for the Time Manager.
* Updates / Ticks the time manager instance. */
* ITimeManager();
* @param delta Time in seconds to tick the instance by.
*/ /**
void update(float_t delta); * Updates / Ticks the time manager instance.
*
/** * @param delta Time in seconds to tick the instance by.
* Pauses the game. */
*/ void update(float_t delta);
void pause();
/**
/** * Pauses the game.
* Resumes the game. */
*/ void pause();
void resume();
/**
/** * Resumes the game.
* Returns the current system timestamp. */
* void resume();
* @return Current timestamp.
*/ /**
virtual int64_t getTimestamp() = 0; * Returns the current system timestamp.
}; *
* @return Current timestamp.
*/
virtual int64_t getTimestamp() = 0;
};
/**
* Use timeout provider method. Invokes your callback after some specified
* time has passed.
*
* @tparam T Your context type (usually SceneItemComponent).
* @param someCallback Callback to be invoked.
* @param timeout Timeout to wait before the method is invoked.
* @param context Context of the component, just use (this).
* @return Method that when invoked will unsubscribe from the timeout.
*/
template<class T>
std::function<void()> useTimeout(
std::function<void()> someCallback,
float_t timeout,
T *context
) {
return context->getGame()->timeManager.timeoutProvider.addEffect(someCallback, timeout, context);
}
template<class T>
std::function<void()> useInterval(
std::function<void()> callback,
float_t interval,
T *context
) {
return context->getGame()->timeManager.intervalProvider.addEffect(
callback, std::pair<float_t, float_t>({ interval, 0 }), context
);
}
} }

View File

@ -30,9 +30,9 @@ void TicTacToeGame::onStart() {
++itTiles; ++itTiles;
} }
useTimeout([&]{ useInterval([&]{
std::cout << "Timeout" << std::endl; std::cout << "Interval" << std::endl;
}, 1000, this)(); }, 1.0f, this);
useEffect([&]{ useEffect([&]{
if(!gameOver) return; if(!gameOver) return;