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/xElement.h"
#include "../xSDL/xSprite.h"
#include "../xSDL/xSpriteAnimation.h"
#endif

View File

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

View File

@ -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<bool> 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<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