diff --git a/include/xSDL.h b/include/xSDL.h index 68eb5a2..78e9e0d 100644 --- a/include/xSDL.h +++ b/include/xSDL.h @@ -6,6 +6,5 @@ #include "../xSDL/xController.h" #include "../xSDL/xElement.h" #include "../xSDL/xSprite.h" - #include "../xSDL/xSpriteAnimation.h" #endif \ No newline at end of file diff --git a/xSDL/xSprite.cpp b/xSDL/xSprite.cpp index cf2b091..0d79e7e 100644 --- a/xSDL/xSprite.cpp +++ b/xSDL/xSprite.cpp @@ -7,28 +7,19 @@ xSprite::~xSprite(){ _mutex.unlock(); } -/** empty sprite */ -xSprite::xSprite(){ - _type = "basic"; -} - /** color sprite */ xSprite::xSprite(const int rgba[]){ - _type = "basic"; this->setSurface(rgba); } /** image sprite */ xSprite::xSprite(const char *url){ - _type = "basic"; - this->setSurface(url); } - -/** texture copy sprite */ -xSprite::xSprite(SDL_Surface *s){ - _type = "basic"; - this->setSurface(s); +/** image sprite with clip */ +xSprite::xSprite(const char *url, SDL_Rect clip){ + this->setSurface(url); + this->setClip(clip); } /** update sprite to rhb color */ @@ -41,8 +32,6 @@ void xSprite::setSurface(const int rgba[]){ _surface = SDL_CreateRGBSurface(0, 0, 0, 32, rgba[0], rgba[1], rgba[2], rgba[3]); - // On cree la texture a partir de la surface - // _surface = SDL_CreateTextureFromSurface(_manager->renderer(), surf); if( _surface == NULL ) { throw runtime_error("[xSprite] setSurface(rgba) -> NULL surface"); } @@ -67,8 +56,7 @@ void xSprite::setSurface(const char *url){ _mutex.unlock(); } -/* [SETTEXTURE] Modification de la texture texture -=========================================================*/ +/** copies an existing surface */ void xSprite::setSurface(SDL_Surface *s){ _mutex.try_lock(); if( _surface != NULL ){ @@ -85,128 +73,72 @@ void xSprite::setSurface(SDL_Surface *s){ _mutex.unlock(); } -/** move sprite with a (x,y) velocity - * - int[0]: new - * - int[1]: can move on y - */ -// bool* xSprite::move(double xSpeed, double ySpeed){ -// _mutex.try_lock(); - -// bool result[2] = {false, false}; - -// /* logic variables */ -// int incrx = x; -// int incry = y; -// bool moveFasterOnY = abs(x) <= abs(y); - -// int signofx = (x==0) ? 0 : x / abs(x); -// int signofy = (y==0) ? 0 : y / abs(y); - -// // while velocity not null -// while( incrx != 0 || incry != 0 ){ - -// result[0] = incrx; -// result[1] = incry; - -// /* (3) Si on peut aller a la destination */ -// // if( !_manager->hit(this, incrx, incry) ){ -// // _dst.x += incrx; -// // _dst.y += incry; - -// // // cerr << ">>> not locked <<<" << endl; - -// // result[0] = incrx; -// // result[1] = incry; - -// // _mutex.unlock(); -// // return result; -// // } - - - -// /* (4) Sinon, on decremente les deplacements 'alternativement' */ -// if( moveFasterOnY ){ // Si on a plus de mouvement horizontal -// if( signofx != 0 && incrx != 0 ) // si la vel. sur x n'est pas nulle -// incrx -= signofx; // on diminue la vel. sur x -// else if( signofy != 0 && incry != 0 ) // sinon si vel. sur y n'est pas nulle -// incry -= signofy; // on diminue la vel. sur y -// else // sinon, velocite nulle -// return result; // On arrete de chercher - -// }else{ // Si on a plus de mouvement vertical -// if( signofy != 0 && incry != 0 ) // si la vel. sur y n'est pas nulle -// incry -= signofy; // on diminue la vel. sur y -// else if( signofx != 0 && incrx != 0 ) // sinon si vel. sur x n'est pas nulle -// incrx -= signofx; // on diminue la vel. sur x -// else // sinon, velocite nulle -// return result; // On arrete de chercher -// } - -// // if( !_manager->hit(this, 0, 1) ){ -// // cerr << "locked from (" << _dst.x << ", " << _dst.y << ") to (" << incrx << ", " << incry << ")" << endl; -// // } -// } - -// // retour -// _mutex.unlock(); -// return result; -// } - -/** get/set sprite type */ -string xSprite::getType(){ return _type; } -void xSprite::setType(string newtype){ _type = newtype; } - -/** set default dimensions */ -void xSprite::dimensions(){ +/** add new animation frame with new clip */ +void xSprite::addFrame(SDL_Rect clip){ _mutex.try_lock(); - /* extract surface lengths*/ - int w = _surface->w; - int h = _surface->h; - - _dst = (SDL_Rect){0, 0, w, h}; - _src = (SDL_Rect){0, 0, w, h}; + _frames.push_back(clip); _mutex.unlock(); } -/** set surface dimensions */ -void xSprite::dimensions(SDL_Rect r){ +/** clear every animation frames */ +void xSprite::clearFrames(){ _mutex.try_lock(); - /* extract surface lengths */ - int w = _surface->w; - int h = _surface->h; - _src = (SDL_Rect){0, 0, w, h}; - - /* store destination dimensions */ - _dst = (SDL_Rect){r.x, r.y, r.w, r.h}; + _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 surface dimensions + clip */ -void xSprite::dimensions(SDL_Rect r, SDL_Rect clip){ +/** set sprite projection */ +void xSprite::project(SDL_Rect dest){ _mutex.try_lock(); - _src = (SDL_Rect){clip.x, clip.y, clip.w, clip.h}; - _dst = (SDL_Rect){r.x, r.y, r.w, r.h}; + _projection = dest; _mutex.unlock(); } -/** returns the surface */ -SDL_Surface *xSprite::surface(){ return _surface; } - -/** return destination dimensions */ -SDL_Rect *xSprite::dst(){ return &_dst; } - -/** return source dimensions */ -SDL_Rect *xSprite::src(){ return &_src; } - - /** 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, this->surface()), - this->src(), - this->dst() + 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); } \ No newline at end of file diff --git a/xSDL/xSprite.h b/xSDL/xSprite.h index f1c8224..f911853 100644 --- a/xSDL/xSprite.h +++ b/xSDL/xSprite.h @@ -7,53 +7,62 @@ #include "SDL.h" #include "SDL_image.h" #include "xElement.h" + #include "xOrchestrable.h" + #include "xApplication.h" using namespace std; - class xSprite : public xElement { + class xSprite : public xElement, public xOrchestrable { public: - xSprite(); // empty - xSprite(const int rgba[]); // color sprite - xSprite(const char *url); // image sprite - xSprite(SDL_Surface *s); // copy sprite - ~xSprite(); + // color sprite + xSprite(const int rgba[]); + // image sprite + xSprite(const char *url); + // image with default clip + xSprite(const char *url, SDL_Rect clip); + virtual ~xSprite(); // replace surface void setSurface(const int rgba[]); // color sprite void setSurface(const char *url); // image sprite void setSurface(SDL_Surface *t); // copy surface - // move the sprite - // const bool* move(double xSpeed, double ySpeed); + // animation + void addFrame(SDL_Rect clip); + void clearFrames(); - // action to apply on collision - // virtual void onCollide(vector from, xSprite* by); + // sets the sprite clip + // + clears animation frames + void setClip(SDL_Rect clip); - // get/set sprite type - string getType(); - void setType(string newtype); - - // set dimensions - void dimensions(); // defauts - void dimensions(SDL_Rect r); - void dimensions(SDL_Rect r, SDL_Rect clip); // w/ clip - - // getters - SDL_Surface *surface(); - SDL_Rect *dst(); - SDL_Rect *src(); + // set projection into scene + void project(SDL_Rect dest); // implement xElement virtual void draw(SDL_Renderer* renderer) override; + // orchestrable process + void tick(const uint32_t ticks); + + // animation handles + void animate(uint32_t interval); + void freeze(); + protected: - string _type; + SDL_Surface* _surface = NULL; + SDL_Rect _projection; - SDL_Surface* _surface = NULL; - SDL_Rect _dst; - SDL_Rect _src; + // surface clips + // [0] : no clip, use default surface dimensions + // [1] : global clip, use it every time + // [2+]: clips are used for animation + vector _frames; - mutex _mutex; + // active clip for animation ; equal to 0 if not an animated sprite + size_t _active_clip = 0; + uint32_t _animation_interval; + + mutex _mutex; }; diff --git a/xSDL/xSpriteAnimation.cpp b/xSDL/xSpriteAnimation.cpp deleted file mode 100644 index a55e50c..0000000 --- a/xSDL/xSpriteAnimation.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#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_frames.try_lock(); - _frames.push_back( (SDL_Rect){ - clip.x, - clip.y, - clip.w, - clip.h - } ); - _mutex_frames.unlock(); -} - -/** clears all frames */ -void xSpriteAnimation::clearFrames(){ - _mutex_frames.try_lock(); - _frames.erase(_frames.begin(), _frames.end()); - _mutex_frames.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 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 - _src = _frames.at(frame_index); - _mutex_frames.unlock(); -} - - -/** adds the animation to the render */ -void xSpriteAnimation::start(uint32_t interval){ - _interval = interval; - xApplication::get()->addOrchestrable(this); -} - -/** stops the animation */ -void xSpriteAnimation::stop(){ - xApplication::get()->removeOrchestrable(this); -} \ No newline at end of file diff --git a/xSDL/xSpriteAnimation.h b/xSDL/xSpriteAnimation.h deleted file mode 100644 index 62e68c3..0000000 --- a/xSDL/xSpriteAnimation.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef DEF_XSPRITEANIMATION_H - #define DEF_XSPRITEANIMATION_H - - #include "SDL.h" - #include - #include "xSprite.h" - #include "xApplication.h" - #include "xElement.h" - #include "xOrchestrable.h" - using namespace std; - - class xSpriteAnimation : public xSprite, public xOrchestrable { - - public: - // spritesheet with sprite size - xSpriteAnimation(const char *url, SDL_Rect dest); - xSpriteAnimation(SDL_Surface *s, SDL_Rect dest); - ~xSpriteAnimation(); - - void addFrame(SDL_Rect clip); - void clearFrames(); - - // animation control handles - 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 _frames; - mutex _mutex_frames; - - // animation - uint32_t _interval; - - }; - -#endif \ No newline at end of file