diff --git a/include/xSDL.h b/include/xSDL.h index c0a8772..68eb5a2 100644 --- a/include/xSDL.h +++ b/include/xSDL.h @@ -1,6 +1,7 @@ #ifndef DEF_XSDL_H #define DEF_XSDL_H + #include "../xSDL/xOrchestrable.h" #include "../xSDL/xApplication.h" #include "../xSDL/xController.h" #include "../xSDL/xElement.h" diff --git a/xSDL/xApplication.cpp b/xSDL/xApplication.cpp index 260ce2a..bd6f6b5 100644 --- a/xSDL/xApplication.cpp +++ b/xSDL/xApplication.cpp @@ -303,7 +303,18 @@ void xApplication::schedule(){ // poll events SDL_Event event; while( SDL_PollEvent(&event) != 0 ) - this->_controller.handleEvent(&event); + _controller.handleEvent(&event); + + const uint32_t ticks = SDL_GetTicks(); + + // trigger tick() on registered orchestrables + _mutex_orchestrate.try_lock(); + set::iterator it; + for( it = _orchestrables.begin() ; it != _orchestrables.end() ; it++ ){ + xOrchestrable* orchestrable = *it; + orchestrable->tick(ticks); + } + _mutex_orchestrate.unlock(); // wait to satisfy FPS this->syncFps(); @@ -312,6 +323,18 @@ void xApplication::schedule(){ this->render(); } +void xApplication::addOrchestrable(xOrchestrable* o){ + _mutex_orchestrate.try_lock(); + _orchestrables.insert(o); + _mutex_orchestrate.unlock(); +} + +void xApplication::removeOrchestrable(xOrchestrable* o){ + _mutex_orchestrate.try_lock(); + _orchestrables.erase(o); + _mutex_orchestrate.unlock(); +} + /** synchronizes according to FPS * to be used at the end of the UI loop */ void xApplication::syncFps(){ diff --git a/xSDL/xApplication.h b/xSDL/xApplication.h index 2070623..bf47dd2 100644 --- a/xSDL/xApplication.h +++ b/xSDL/xApplication.h @@ -4,13 +4,14 @@ #include "SDL.h" #include "SDL_image.h" #include - #include + #include #include #include #include #include #include "xElement.h" #include "xController.h" + #include "xOrchestrable.h" using namespace std; enum xAppState { @@ -19,8 +20,6 @@ STOPPED }; - #define EventListener void(*)(SDL_Event*) - class xApplication{ public: @@ -52,6 +51,10 @@ void setFps(const uint32_t fps=0); void schedule(); + // manage orchestrables + void addOrchestrable(xOrchestrable* o); + void removeOrchestrable(xOrchestrable* o); + xAppState state; private: /** Singleton */ @@ -70,6 +73,9 @@ // sprites set _sprites; + // execution pool + set _orchestrables; + // sdl objects SDL_Window *_window; SDL_Rect _winrect; @@ -79,6 +85,7 @@ // thread safety mutex _mutex_draw; + mutex _mutex_orchestrate; }; #endif \ No newline at end of file diff --git a/xSDL/xOrchestrable.cpp b/xSDL/xOrchestrable.cpp new file mode 100644 index 0000000..7f40787 --- /dev/null +++ b/xSDL/xOrchestrable.cpp @@ -0,0 +1 @@ +#include "xOrchestrable.h" \ No newline at end of file diff --git a/xSDL/xOrchestrable.h b/xSDL/xOrchestrable.h new file mode 100644 index 0000000..ebe8272 --- /dev/null +++ b/xSDL/xOrchestrable.h @@ -0,0 +1,11 @@ +#ifndef DEF_XORCHESTRABLE_H + #define DEF_XORCHESTRABLE_H + + #include + + // abstract class for orchestrables + struct xOrchestrable { + virtual void tick(const uint32_t ticks) = 0; + }; + +#endif \ No newline at end of file diff --git a/xSDL/xSpriteAnimation.cpp b/xSDL/xSpriteAnimation.cpp index 78a0b08..a55e50c 100644 --- a/xSDL/xSpriteAnimation.cpp +++ b/xSDL/xSpriteAnimation.cpp @@ -8,11 +8,9 @@ xSpriteAnimation::~xSpriteAnimation(){ _mutex.unlock(); } - /** builds an animation */ xSpriteAnimation::xSpriteAnimation(const char *url, SDL_Rect dest) : xSprite( url ){ - this->dimensions(dest); } @@ -23,24 +21,23 @@ xSpriteAnimation::xSpriteAnimation(SDL_Surface *s, SDL_Rect dest) this->dimensions(dest); } - /** adds an animation frame */ void xSpriteAnimation::addFrame(SDL_Rect clip){ - _mutex.try_lock(); + _mutex_frames.try_lock(); _frames.push_back( (SDL_Rect){ clip.x, clip.y, clip.w, clip.h } ); - _mutex.unlock(); + _mutex_frames.unlock(); } /** clears all frames */ void xSpriteAnimation::clearFrames(){ - _mutex.try_lock(); + _mutex_frames.try_lock(); _frames.erase(_frames.begin(), _frames.end()); - _mutex.unlock(); + _mutex_frames.unlock(); } /** draw to scene */ @@ -56,61 +53,24 @@ void xSpriteAnimation::draw(SDL_Renderer* renderer){ } /** animation process */ -void xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags){ - uint32_t timer = 0; - bool way = true; - uint32_t start = 0; +void xSpriteAnimation::tick(const uint32_t ticks){ + _mutex_frames.try_lock(); + uint32_t time_index = ticks / _interval; + size_t frame_index = time_index % _frames.size(); - while( flags&SPRITE_ANIM_INFINITE ){ - - // for every frame (sprite) - for( uint32_t i = start ; i != xSA->_frames.size() ; i+=(way?1:-1) ){ - timer = SDL_GetTicks(); - - // update current frame clip - // xSA->_mutex.try_lock(); - xSA->_src = xSA->_frames.at(i); - // xSA->_mutex.unlock(); - - // xSA->manager()->update(); - - if( SDL_GetTicks()-timer < t ) - SDL_Delay( t - (SDL_GetTicks()-timer) ); - } - - // manage reverse flag - if( flags&SPRITE_ANIM_REVERSE ){ - way = !way; - start = (way) ? 0 : xSA->_frames.size()-1; - } - - } - - // end thread - return; + // update current frame clip + _src = _frames.at(frame_index); + _mutex_frames.unlock(); } /** adds the animation to the render */ -void xSpriteAnimation::start(int t, int flags){ - _timeout = t; - _flags = flags; - - // launch animation - _animation = new thread(xSpriteAnimationProcess, this, t, flags); - - // don't wait for the thread to end - _animation->detach(); +void xSpriteAnimation::start(uint32_t interval){ + _interval = interval; + xApplication::get()->addOrchestrable(this); } - - /** stops the animation */ void xSpriteAnimation::stop(){ - // stop animation thread - delete _animation; - if( _animation->joinable() ) - _animation->join(); - - _animation = NULL; + xApplication::get()->removeOrchestrable(this); } \ No newline at end of file diff --git a/xSDL/xSpriteAnimation.h b/xSDL/xSpriteAnimation.h index c3b246f..62e68c3 100644 --- a/xSDL/xSpriteAnimation.h +++ b/xSDL/xSpriteAnimation.h @@ -2,18 +2,14 @@ #define DEF_XSPRITEANIMATION_H #include "SDL.h" + #include #include "xSprite.h" #include "xApplication.h" #include "xElement.h" - #include - #include + #include "xOrchestrable.h" using namespace std; - #define SPRITE_ANIM_ONCE 0b1 - #define SPRITE_ANIM_INFINITE 0b10 - #define SPRITE_ANIM_REVERSE 0b100 - - class xSpriteAnimation : public xSprite { + class xSpriteAnimation : public xSprite, public xOrchestrable { public: // spritesheet with sprite size @@ -25,22 +21,20 @@ void clearFrames(); // animation control handles - void start(int t, int flags=SPRITE_ANIM_ONCE); + void start(uint32_t delay); void stop(); // implement xElement void draw(SDL_Renderer* renderer) override; + // implement xOrchestrable + void tick(const uint32_t ticks); protected: vector _frames; + mutex _mutex_frames; // animation - int _timeout; - int _flags; - - // animation thread - thread *_animation; - friend void xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags); + uint32_t _interval; };