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:
parent
12871d93dc
commit
44de8cb3ea
|
@ -6,6 +6,5 @@
|
|||
#include "../xSDL/xController.h"
|
||||
#include "../xSDL/xElement.h"
|
||||
#include "../xSDL/xSprite.h"
|
||||
#include "../xSDL/xSpriteAnimation.h"
|
||||
|
||||
#endif
|
176
xSDL/xSprite.cpp
176
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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue