create orchestrable xSpriteGroup (no more xSprite alone)

This commit is contained in:
Adrien Marquès 2020-02-02 16:18:12 +01:00
parent ab2f170def
commit 7a6022e694
5 changed files with 132 additions and 81 deletions

View File

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

View File

@ -2,7 +2,7 @@
/** clean SDL objects */ /** clean SDL objects */
xSprite::~xSprite(){ xSprite::~xSprite(){
_mutex.try_lock(); _mutex.lock();
SDL_FreeSurface( _surface ); SDL_FreeSurface( _surface );
_mutex.unlock(); _mutex.unlock();
} }
@ -24,7 +24,7 @@ xSprite::xSprite(const char *url, SDL_Rect clip){
/** update sprite to rhb color */ /** update sprite to rhb color */
void xSprite::setSurface(const int rgba[]){ void xSprite::setSurface(const int rgba[]){
_mutex.try_lock(); _mutex.lock();
if( _surface != NULL ){ if( _surface != NULL ){
SDL_FreeSurface( _surface ); SDL_FreeSurface( _surface );
_surface = NULL; _surface = NULL;
@ -42,7 +42,7 @@ void xSprite::setSurface(const int rgba[]){
/** update sprite to image */ /** update sprite to image */
void xSprite::setSurface(const char *url){ void xSprite::setSurface(const char *url){
_mutex.try_lock(); _mutex.lock();
if( _surface != NULL ){ if( _surface != NULL ){
SDL_FreeSurface( _surface ); SDL_FreeSurface( _surface );
_surface = NULL; _surface = NULL;
@ -58,7 +58,7 @@ void xSprite::setSurface(const char *url){
/** copies an existing surface */ /** copies an existing surface */
void xSprite::setSurface(SDL_Surface *s){ void xSprite::setSurface(SDL_Surface *s){
_mutex.try_lock(); _mutex.lock();
if( _surface != NULL ){ if( _surface != NULL ){
SDL_FreeSurface( _surface ); SDL_FreeSurface( _surface );
_surface = NULL; _surface = NULL;
@ -73,72 +73,29 @@ void xSprite::setSurface(SDL_Surface *s){
_mutex.unlock(); _mutex.unlock();
} }
/** add new animation frame with new clip */ /** set sprite 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){ void xSprite::setClip(SDL_Rect clip){
_mutex.try_lock(); _mutex.lock();
_frames.clear(); _clip = clip;
_frames.push_back(clip);
_mutex.unlock(); _mutex.unlock();
} }
/** set sprite projection */ /** set sprite projection */
void xSprite::project(SDL_Rect dest){ void xSprite::project(SDL_Rect dest){
_mutex.try_lock(); _mutex.lock();
_projection = dest; _projection = dest;
_mutex.unlock(); _mutex.unlock();
} }
/** draws to renderer */ /** draws to renderer */
void xSprite::draw(SDL_Renderer* renderer){ void xSprite::draw(SDL_Renderer* renderer){
_mutex.try_lock(); _mutex.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, _surface), SDL_CreateTextureFromSurface(renderer, _surface),
&_frames.at(_active_clip), &_clip,
&_projection &_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

@ -6,12 +6,11 @@
#include <mutex> #include <mutex>
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h" #include "SDL_image.h"
#include "xElement.h" #include "xDrawable.h"
#include "xOrchestrable.h"
#include "xApplication.h" #include "xApplication.h"
using namespace std; using namespace std;
class xSprite : public xElement, public xOrchestrable { class xSprite : public xDrawable{
public: public:
// color sprite // color sprite
@ -27,41 +26,19 @@
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
// animation
void addFrame(SDL_Rect clip);
void clearFrames();
// sets the sprite clip // sets the sprite clip
// + clears animation frames
void setClip(SDL_Rect clip); void setClip(SDL_Rect clip);
// set projection into scene // set projection into scene
void project(SDL_Rect dest); void project(SDL_Rect dest);
// implement xElement // implement xDrawable
virtual void draw(SDL_Renderer* renderer) override; virtual void draw(SDL_Renderer* renderer) override;
private:
// orchestrable process
void tick(const uint32_t ticks);
// animation handles
void animate(uint32_t interval);
void freeze();
protected:
SDL_Surface* _surface = NULL; SDL_Surface* _surface = NULL;
SDL_Rect _clip;
SDL_Rect _projection; SDL_Rect _projection;
// 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;
// active clip for animation ; equal to 0 if not an animated sprite
size_t _active_clip = 0;
uint32_t _animation_interval;
mutex _mutex; mutex _mutex;
}; };

64
xSDL/xSpriteGroup.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "xSpriteGroup.h"
/** clean SDL objects */
xSpriteGroup::~xSpriteGroup(){
_mutex.lock();
_sprites.clear();
_mutex.unlock();
}
/** default constructor */
xSpriteGroup::xSpriteGroup(){
}
/** adds a sprite to the group */
void xSpriteGroup::add(xSprite* sprite){
_mutex.lock();
_sprites.insert(sprite);
_mutex.unlock();
}
/** removes a sprite from the group */
void xSpriteGroup::remove(xSprite* sprite){
_mutex.lock();
_sprites.erase(sprite);
_mutex.unlock();
}
/** set absolute move for each sprite */
void xSpriteGroup::moveTo(int x, int y){
_mutex.lock();
_move.x = x;
_move.y = y;
_mutex.unlock();
}
/** draws to renderer */
void xSpriteGroup::draw(SDL_Renderer* renderer){
_mutex.lock();
set<xSprite*>::iterator it;
for( it = _sprites.begin() ; it != _sprites.end() ; it++ ){
(*it)->draw(renderer);
}
_mutex.unlock();
}
/** animation process */
void xSpriteGroup::tick(const uint32_t ticks){
_mutex.lock();
uint32_t time_index = ticks / _animation_interval;
_active_sprite = time_index % _sprites.size();
_mutex.unlock();
}
/** orchestrate the animation */
void xSpriteGroup::animate(uint32_t interval){
_animation_interval = interval;
xApplication::get()->addOrchestrable(this);
}
/** stops orchestrating the animation */
void xSpriteGroup::freeze(){
xApplication::get()->removeOrchestrable(this);
}

52
xSDL/xSpriteGroup.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef DEF_XSPRITEGROUP_H
#define DEF_XSPRITEGROUP_H
#include <string>
#include <vector>
#include <mutex>
#include "SDL.h"
#include "SDL_image.h"
#include "xDrawable.h"
#include "xOrchestrable.h"
#include "xApplication.h"
#include "xSprite.h"
using namespace std;
class xSpriteGroup : public xDrawable, public xOrchestrable {
public:
xSpriteGroup();
virtual ~xSpriteGroup();
// manage sprite list
void add(xSprite* sprite);
void remove(xSprite* sprite);
void clear();
// set absolute move for each sprite
void moveTo(int x, int y);
// implement xDrawable
virtual void draw(SDL_Renderer* renderer) override;
// implement xOrchestrable
void tick(const uint32_t ticks);
// animation handles
void animate(uint32_t interval);
void freeze();
protected:
SDL_Rect _move;
set<xSprite*> _sprites;
// active sprite for animation ; equal to 0 if not an animated sprite
size_t _active_sprite = 0;
uint32_t _animation_interval;
mutex _mutex;
};
#endif