Make xSpriteAnimation orchestrable and register every animation into the app when started

This commit is contained in:
Adrien Marquès 2019-11-06 22:48:25 +01:00
parent 2cbf3bc91b
commit 57025d9ef3
7 changed files with 70 additions and 73 deletions

View File

@ -1,6 +1,7 @@
#ifndef DEF_XSDL_H #ifndef DEF_XSDL_H
#define DEF_XSDL_H #define DEF_XSDL_H
#include "../xSDL/xOrchestrable.h"
#include "../xSDL/xApplication.h" #include "../xSDL/xApplication.h"
#include "../xSDL/xController.h" #include "../xSDL/xController.h"
#include "../xSDL/xElement.h" #include "../xSDL/xElement.h"

View File

@ -303,7 +303,18 @@ void xApplication::schedule(){
// poll events // poll events
SDL_Event event; SDL_Event event;
while( SDL_PollEvent(&event) != 0 ) 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<xOrchestrable*>::iterator it;
for( it = _orchestrables.begin() ; it != _orchestrables.end() ; it++ ){
xOrchestrable* orchestrable = *it;
orchestrable->tick(ticks);
}
_mutex_orchestrate.unlock();
// wait to satisfy FPS // wait to satisfy FPS
this->syncFps(); this->syncFps();
@ -312,6 +323,18 @@ void xApplication::schedule(){
this->render(); 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 /** synchronizes according to FPS
* to be used at the end of the UI loop */ * to be used at the end of the UI loop */
void xApplication::syncFps(){ void xApplication::syncFps(){

View File

@ -4,13 +4,14 @@
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h" #include "SDL_image.h"
#include <vector> #include <vector>
#include <map> #include <set>
#include <string> #include <string>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <stdexcept> #include <stdexcept>
#include "xElement.h" #include "xElement.h"
#include "xController.h" #include "xController.h"
#include "xOrchestrable.h"
using namespace std; using namespace std;
enum xAppState { enum xAppState {
@ -19,8 +20,6 @@
STOPPED STOPPED
}; };
#define EventListener void(*)(SDL_Event*)
class xApplication{ class xApplication{
public: public:
@ -52,6 +51,10 @@
void setFps(const uint32_t fps=0); void setFps(const uint32_t fps=0);
void schedule(); void schedule();
// manage orchestrables
void addOrchestrable(xOrchestrable* o);
void removeOrchestrable(xOrchestrable* o);
xAppState state; xAppState state;
private: private:
/** Singleton */ /** Singleton */
@ -70,6 +73,9 @@
// sprites // sprites
set<xElement*> _sprites; set<xElement*> _sprites;
// execution pool
set<xOrchestrable*> _orchestrables;
// sdl objects // sdl objects
SDL_Window *_window; SDL_Window *_window;
SDL_Rect _winrect; SDL_Rect _winrect;
@ -79,6 +85,7 @@
// thread safety // thread safety
mutex _mutex_draw; mutex _mutex_draw;
mutex _mutex_orchestrate;
}; };
#endif #endif

1
xSDL/xOrchestrable.cpp Normal file
View File

@ -0,0 +1 @@
#include "xOrchestrable.h"

11
xSDL/xOrchestrable.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef DEF_XORCHESTRABLE_H
#define DEF_XORCHESTRABLE_H
#include <stdint.h>
// abstract class for orchestrables
struct xOrchestrable {
virtual void tick(const uint32_t ticks) = 0;
};
#endif

View File

@ -8,11 +8,9 @@ xSpriteAnimation::~xSpriteAnimation(){
_mutex.unlock(); _mutex.unlock();
} }
/** builds an animation */ /** builds an animation */
xSpriteAnimation::xSpriteAnimation(const char *url, SDL_Rect dest) xSpriteAnimation::xSpriteAnimation(const char *url, SDL_Rect dest)
: xSprite( url ){ : xSprite( url ){
this->dimensions(dest); this->dimensions(dest);
} }
@ -23,24 +21,23 @@ xSpriteAnimation::xSpriteAnimation(SDL_Surface *s, SDL_Rect dest)
this->dimensions(dest); this->dimensions(dest);
} }
/** adds an animation frame */ /** adds an animation frame */
void xSpriteAnimation::addFrame(SDL_Rect clip){ void xSpriteAnimation::addFrame(SDL_Rect clip){
_mutex.try_lock(); _mutex_frames.try_lock();
_frames.push_back( (SDL_Rect){ _frames.push_back( (SDL_Rect){
clip.x, clip.x,
clip.y, clip.y,
clip.w, clip.w,
clip.h clip.h
} ); } );
_mutex.unlock(); _mutex_frames.unlock();
} }
/** clears all frames */ /** clears all frames */
void xSpriteAnimation::clearFrames(){ void xSpriteAnimation::clearFrames(){
_mutex.try_lock(); _mutex_frames.try_lock();
_frames.erase(_frames.begin(), _frames.end()); _frames.erase(_frames.begin(), _frames.end());
_mutex.unlock(); _mutex_frames.unlock();
} }
/** draw to scene */ /** draw to scene */
@ -56,61 +53,24 @@ void xSpriteAnimation::draw(SDL_Renderer* renderer){
} }
/** animation process */ /** animation process */
void xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags){ void xSpriteAnimation::tick(const uint32_t ticks){
uint32_t timer = 0; _mutex_frames.try_lock();
bool way = true; uint32_t time_index = ticks / _interval;
uint32_t start = 0; 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 // update current frame clip
// xSA->_mutex.try_lock(); _src = _frames.at(frame_index);
xSA->_src = xSA->_frames.at(i); _mutex_frames.unlock();
// 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;
} }
/** adds the animation to the render */ /** adds the animation to the render */
void xSpriteAnimation::start(int t, int flags){ void xSpriteAnimation::start(uint32_t interval){
_timeout = t; _interval = interval;
_flags = flags; xApplication::get()->addOrchestrable(this);
// launch animation
_animation = new thread(xSpriteAnimationProcess, this, t, flags);
// don't wait for the thread to end
_animation->detach();
} }
/** stops the animation */ /** stops the animation */
void xSpriteAnimation::stop(){ void xSpriteAnimation::stop(){
// stop animation thread xApplication::get()->removeOrchestrable(this);
delete _animation;
if( _animation->joinable() )
_animation->join();
_animation = NULL;
} }

View File

@ -2,18 +2,14 @@
#define DEF_XSPRITEANIMATION_H #define DEF_XSPRITEANIMATION_H
#include "SDL.h" #include "SDL.h"
#include <vector>
#include "xSprite.h" #include "xSprite.h"
#include "xApplication.h" #include "xApplication.h"
#include "xElement.h" #include "xElement.h"
#include <vector> #include "xOrchestrable.h"
#include <thread>
using namespace std; using namespace std;
#define SPRITE_ANIM_ONCE 0b1 class xSpriteAnimation : public xSprite, public xOrchestrable {
#define SPRITE_ANIM_INFINITE 0b10
#define SPRITE_ANIM_REVERSE 0b100
class xSpriteAnimation : public xSprite {
public: public:
// spritesheet with sprite size // spritesheet with sprite size
@ -25,22 +21,20 @@
void clearFrames(); void clearFrames();
// animation control handles // animation control handles
void start(int t, int flags=SPRITE_ANIM_ONCE); void start(uint32_t delay);
void stop(); void stop();
// implement xElement // implement xElement
void draw(SDL_Renderer* renderer) override; void draw(SDL_Renderer* renderer) override;
// implement xOrchestrable
void tick(const uint32_t ticks);
protected: protected:
vector<SDL_Rect> _frames; vector<SDL_Rect> _frames;
mutex _mutex_frames;
// animation // animation
int _timeout; uint32_t _interval;
int _flags;
// animation thread
thread *_animation;
friend void xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags);
}; };