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

@ -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);
}
} }

@ -14,8 +14,33 @@ 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) { if(!this->isPaused) {
this->unpausedTime += delta; this->unpausedTime += delta;
// Timeout effect provider
auto itEffect = this->timeoutProvider.listeners.begin();
while(itEffect != this->timeoutProvider.listeners.end()) {
itEffect->data -= delta;
if(itEffect->data <= 0) {
itEffect->callback();
itEffect = this->timeoutProvider.listeners.erase(itEffect);
continue;
}
++itEffect;
}
// 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;
}
} }
} }

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "dawnlibs.hpp" #include "dawnlibs.hpp"
#include "event/Event.hpp" #include "event/Event.hpp"
#include "state/StateProvider.hpp"
namespace Dawn { namespace Dawn {
class ITimeManager { class ITimeManager {
@ -15,6 +16,9 @@ namespace Dawn {
float_t delta = 0.016f; float_t delta = 0.016f;
bool_t isPaused = false; bool_t isPaused = false;
StateProviderSet<float_t> timeoutProvider;
StateProviderSet<std::pair<float_t, float_t>> intervalProvider;
Event<> eventTimePaused; Event<> eventTimePaused;
Event<> eventTimeResumed; Event<> eventTimeResumed;
@ -47,4 +51,35 @@ namespace Dawn {
*/ */
virtual int64_t getTimestamp() = 0; 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
);
}
} }

@ -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;