#include "xSprite.h" /** clean SDL objects */ xSprite::~xSprite(){ _mutex.try_lock(); SDL_FreeSurface( _surface ); _mutex.unlock(); } /** color sprite */ xSprite::xSprite(const int rgba[]){ this->setSurface(rgba); } /** image sprite */ xSprite::xSprite(const char *url){ this->setSurface(url); } /** image sprite with clip */ xSprite::xSprite(const char *url, SDL_Rect clip){ this->setSurface(url); this->setClip(clip); } /** update sprite to rhb color */ void xSprite::setSurface(const int rgba[]){ _mutex.try_lock(); if( _surface != NULL ){ SDL_FreeSurface( _surface ); _surface = NULL; } _surface = SDL_CreateRGBSurface(0, 0, 0, 32, rgba[0], rgba[1], rgba[2], rgba[3]); if( _surface == NULL ) { throw runtime_error("[xSprite] setSurface(rgba) -> NULL surface"); } _mutex.unlock(); } /** update sprite to image */ void xSprite::setSurface(const char *url){ _mutex.try_lock(); if( _surface != NULL ){ SDL_FreeSurface( _surface ); _surface = NULL; } _surface = IMG_Load(url); if( _surface == NULL ) { throw runtime_error("[xSprite] setSurface(url) -> NULL surface"); } _mutex.unlock(); } /** copies an existing surface */ void xSprite::setSurface(SDL_Surface *s){ _mutex.try_lock(); if( _surface != NULL ){ SDL_FreeSurface( _surface ); _surface = NULL; } _surface = s; if( _surface == NULL ) { throw runtime_error("[xSprite] setSurface(surface) -> NULL surface"); } _mutex.unlock(); } /** add new animation frame with new clip */ void xSprite::addFrame(SDL_Rect clip){ _mutex.try_lock(); _frames.push_back(clip); _mutex.unlock(); } /** clear every animation frames */ void xSprite::clearFrames(){ _mutex.try_lock(); _frames.clear(); _mutex.unlock(); } /** set sprite clip and clears animation frames */ void xSprite::setClip(SDL_Rect clip){ _mutex.try_lock(); _frames.clear(); _frames.push_back(clip); _mutex.unlock(); } /** set sprite projection */ void xSprite::project(SDL_Rect dest){ _mutex.try_lock(); _projection = dest; _mutex.unlock(); } /** draws to renderer */ void xSprite::draw(SDL_Renderer* renderer){ _mutex.try_lock(); // no clip -> use surface dimensions if( _frames.size() <= 0 ){ setClip( (SDL_Rect){0, 0, _surface->w, _surface->h} ); } // only 1 clip -> use it if( _frames.size() == 1 ){ _active_clip = 0; } SDL_RenderCopy( renderer, SDL_CreateTextureFromSurface(renderer, _surface), &_frames.at(_active_clip), &_projection ); _mutex.unlock(); } /** animation process */ void xSprite::tick(const uint32_t ticks){ _mutex.try_lock(); uint32_t time_index = ticks / _animation_interval; _active_clip = time_index % _frames.size(); _mutex.unlock(); } /** orchestrate the animation */ void xSprite::animate(uint32_t interval){ _animation_interval = interval; xApplication::get()->addOrchestrable(this); } /** stops orchestrating the animation */ void xSprite::freeze(){ xApplication::get()->removeOrchestrable(this); }