#include "xSpriteAnimation.h" /** clean SDL objects and frames */ xSpriteAnimation::~xSpriteAnimation(){ _mutex.try_lock(); SDL_FreeSurface( _surface ); _frames.erase( _frames.begin(), _frames.end() ); _mutex.unlock(); } /** builds an animation */ xSpriteAnimation::xSpriteAnimation(const char *url, SDL_Rect dest) : xSprite( url ){ this->dimensions(dest); } /** builds an animation from an existing surface */ xSpriteAnimation::xSpriteAnimation(SDL_Surface *s, SDL_Rect dest) : xSprite(s) { this->dimensions(dest); } /** adds an animation frame */ void xSpriteAnimation::addFrame(SDL_Rect clip){ _mutex.try_lock(); _frames.push_back( (SDL_Rect){ clip.x, clip.y, clip.w, clip.h } ); _mutex.unlock(); } /** clears all frames */ void xSpriteAnimation::clearFrames(){ _mutex.try_lock(); _frames.erase(_frames.begin(), _frames.end()); _mutex.unlock(); } /** draw to scene */ void xSpriteAnimation::draw(SDL_Renderer* renderer){ _mutex.try_lock(); SDL_RenderCopy( renderer, SDL_CreateTextureFromSurface(renderer, this->surface()), this->src(), this->dst() ); _mutex.unlock(); } /** 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(); // 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; } /** 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(); } /** stops the animation */ void xSpriteAnimation::stop(){ // stop animation thread delete _animation; if( _animation->joinable() ) _animation->join(); _animation = NULL; }