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
#define DEF_XSDL_H
#include "../xSDL/xOrchestrable.h"
#include "../xSDL/xApplication.h"
#include "../xSDL/xController.h"
#include "../xSDL/xElement.h"

View File

@ -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<xOrchestrable*>::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(){

View File

@ -4,13 +4,14 @@
#include "SDL.h"
#include "SDL_image.h"
#include <vector>
#include <map>
#include <set>
#include <string>
#include <mutex>
#include <thread>
#include <stdexcept>
#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<xElement*> _sprites;
// execution pool
set<xOrchestrable*> _orchestrables;
// sdl objects
SDL_Window *_window;
SDL_Rect _winrect;
@ -79,6 +85,7 @@
// thread safety
mutex _mutex_draw;
mutex _mutex_orchestrate;
};
#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();
}
/** 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;
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();
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();
// 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;
_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);
}

View File

@ -2,18 +2,14 @@
#define DEF_XSPRITEANIMATION_H
#include "SDL.h"
#include <vector>
#include "xSprite.h"
#include "xApplication.h"
#include "xElement.h"
#include <vector>
#include <thread>
#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<SDL_Rect> _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;
};