xmario/xSDL/xSprite.cpp

144 lines
2.9 KiB
C++

#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);
}