Merge SpriteAnimation into xSprite and interface improvements

- remove dead code
- a sprite with no clip uses the default surface dimensions to draw
- a sprite with a single clip uses it
- a sprite with multiple clips (i.e. frames) has the first as a default but when orchestrated iterates over clips in order
This commit is contained in:
Adrien Marquès 2019-11-08 21:28:36 +01:00
parent 12871d93dc
commit 44de8cb3ea
5 changed files with 91 additions and 268 deletions

View File

@ -6,6 +6,5 @@
#include "../xSDL/xController.h" #include "../xSDL/xController.h"
#include "../xSDL/xElement.h" #include "../xSDL/xElement.h"
#include "../xSDL/xSprite.h" #include "../xSDL/xSprite.h"
#include "../xSDL/xSpriteAnimation.h"
#endif #endif

View File

@ -7,28 +7,19 @@ xSprite::~xSprite(){
_mutex.unlock(); _mutex.unlock();
} }
/** empty sprite */
xSprite::xSprite(){
_type = "basic";
}
/** color sprite */ /** color sprite */
xSprite::xSprite(const int rgba[]){ xSprite::xSprite(const int rgba[]){
_type = "basic";
this->setSurface(rgba); this->setSurface(rgba);
} }
/** image sprite */ /** image sprite */
xSprite::xSprite(const char *url){ xSprite::xSprite(const char *url){
_type = "basic";
this->setSurface(url); this->setSurface(url);
} }
/** image sprite with clip */
/** texture copy sprite */ xSprite::xSprite(const char *url, SDL_Rect clip){
xSprite::xSprite(SDL_Surface *s){ this->setSurface(url);
_type = "basic"; this->setClip(clip);
this->setSurface(s);
} }
/** update sprite to rhb color */ /** 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]); _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 ) { if( _surface == NULL ) {
throw runtime_error("[xSprite] setSurface(rgba) -> NULL surface"); throw runtime_error("[xSprite] setSurface(rgba) -> NULL surface");
} }
@ -67,8 +56,7 @@ void xSprite::setSurface(const char *url){
_mutex.unlock(); _mutex.unlock();
} }
/* [SETTEXTURE] Modification de la texture texture /** copies an existing surface */
=========================================================*/
void xSprite::setSurface(SDL_Surface *s){ void xSprite::setSurface(SDL_Surface *s){
_mutex.try_lock(); _mutex.try_lock();
if( _surface != NULL ){ if( _surface != NULL ){
@ -85,128 +73,72 @@ void xSprite::setSurface(SDL_Surface *s){
_mutex.unlock(); _mutex.unlock();
} }
/** move sprite with a (x,y) velocity /** add new animation frame with new clip */
* - int[0]: new void xSprite::addFrame(SDL_Rect clip){
* - 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(){
_mutex.try_lock(); _mutex.try_lock();
/* extract surface lengths*/ _frames.push_back(clip);
int w = _surface->w;
int h = _surface->h;
_dst = (SDL_Rect){0, 0, w, h};
_src = (SDL_Rect){0, 0, w, h};
_mutex.unlock(); _mutex.unlock();
} }
/** set surface dimensions */ /** clear every animation frames */
void xSprite::dimensions(SDL_Rect r){ void xSprite::clearFrames(){
_mutex.try_lock(); _mutex.try_lock();
/* extract surface lengths */ _frames.clear();
int w = _surface->w; _mutex.unlock();
int h = _surface->h; }
_src = (SDL_Rect){0, 0, w, h}; /** set sprite clip and clears animation frames */
void xSprite::setClip(SDL_Rect clip){
/* store destination dimensions */ _mutex.try_lock();
_dst = (SDL_Rect){r.x, r.y, r.w, r.h}; _frames.clear();
_frames.push_back(clip);
_mutex.unlock(); _mutex.unlock();
} }
/** set surface dimensions + clip */ /** set sprite projection */
void xSprite::dimensions(SDL_Rect r, SDL_Rect clip){ void xSprite::project(SDL_Rect dest){
_mutex.try_lock(); _mutex.try_lock();
_src = (SDL_Rect){clip.x, clip.y, clip.w, clip.h}; _projection = dest;
_dst = (SDL_Rect){r.x, r.y, r.w, r.h};
_mutex.unlock(); _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 */ /** draws to renderer */
void xSprite::draw(SDL_Renderer* renderer){ void xSprite::draw(SDL_Renderer* renderer){
_mutex.try_lock(); _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( SDL_RenderCopy(
renderer, renderer,
SDL_CreateTextureFromSurface(renderer, this->surface()), SDL_CreateTextureFromSurface(renderer, _surface),
this->src(), &_frames.at(_active_clip),
this->dst() &_projection
); );
_mutex.unlock(); _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);
}

View File

@ -7,53 +7,62 @@
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h" #include "SDL_image.h"
#include "xElement.h" #include "xElement.h"
#include "xOrchestrable.h"
#include "xApplication.h"
using namespace std; using namespace std;
class xSprite : public xElement { class xSprite : public xElement, public xOrchestrable {
public: public:
xSprite(); // empty // color sprite
xSprite(const int rgba[]); // color sprite xSprite(const int rgba[]);
xSprite(const char *url); // image sprite // image sprite
xSprite(SDL_Surface *s); // copy sprite xSprite(const char *url);
~xSprite(); // image with default clip
xSprite(const char *url, SDL_Rect clip);
virtual ~xSprite();
// replace surface // replace surface
void setSurface(const int rgba[]); // color sprite void setSurface(const int rgba[]); // color sprite
void setSurface(const char *url); // image sprite void setSurface(const char *url); // image sprite
void setSurface(SDL_Surface *t); // copy surface void setSurface(SDL_Surface *t); // copy surface
// move the sprite // animation
// const bool* move(double xSpeed, double ySpeed); void addFrame(SDL_Rect clip);
void clearFrames();
// action to apply on collision // sets the sprite clip
// virtual void onCollide(vector<bool> from, xSprite* by); // + clears animation frames
void setClip(SDL_Rect clip);
// get/set sprite type // set projection into scene
string getType(); void project(SDL_Rect dest);
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();
// implement xElement // implement xElement
virtual void draw(SDL_Renderer* renderer) override; 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: protected:
string _type; SDL_Surface* _surface = NULL;
SDL_Rect _projection;
SDL_Surface* _surface = NULL; // surface clips
SDL_Rect _dst; // [0] : no clip, use default surface dimensions
SDL_Rect _src; // [1] : global clip, use it every time
// [2+]: clips are used for animation
vector<SDL_Rect> _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;
}; };

View File

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

View File

@ -1,41 +0,0 @@
#ifndef DEF_XSPRITEANIMATION_H
#define DEF_XSPRITEANIMATION_H
#include "SDL.h"
#include <vector>
#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<SDL_Rect> _frames;
mutex _mutex_frames;
// animation
uint32_t _interval;
};
#endif