Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
Adrien Marquès | 4ca0312479 | |
Adrien Marquès | 414fbf6404 | |
Adrien Marquès | 5266b5d115 | |
Adrien Marquès | 2b81a72542 | |
Adrien Marquès | 47429e5081 | |
Adrien Marquès | cb1a862b6f | |
Adrien Marquès | 0b7e7a2948 | |
Adrien Marquès | d1e6a1e9dc | |
Adrien Marquès | cc276e1c2a | |
Adrien Marquès | 49deb9e868 | |
Adrien Marquès | 7a6022e694 | |
Adrien Marquès | ab2f170def | |
Adrien Marquès | 44de8cb3ea | |
Adrien Marquès | 12871d93dc |
|
@ -19,11 +19,8 @@ The class `xApplication` is a singleton representing your application, its windo
|
|||
|
||||
The interface `xElement` represents any graphical feature to be drawn on the screen. Any number of `xElement` can be pushed to or pulled from the application at any time in order to show them or not.
|
||||
|
||||
The interface `xOrchestrable` represents any class that can be called during the application scheduling. Any number of `xOrchestrable` can be added or removed from the application at any time in order to execute them or not.
|
||||
|
||||
The class `xSprite` represents a sprite that can is a rectangle that can draw either as a single color, an image, or a copy of another sprite. It can be moved over time. Also, it allows you to set a custom clip if this is an image sprite.
|
||||
|
||||
The class `xSpriteAnimation` derives from an image sprite, which clip can change over time. These clips are called _frames_ and have to be set beforehand, when ready you can start or stop the animation with a specified delay between frames. Every `xSpriteAnimation` is scheduled on the same dedicated animation thread.
|
||||
|
||||
|
||||
The concurrency model is led simple :
|
||||
- the main loop schedules rendering and user input
|
||||
- the animation loop schedules animation frame shifts
|
||||
The class `xSpriteAnimation` derives from an image sprite, which clip can change over time. These clips are called _frames_ and have to be set beforehand. It is also an orchestrable (i.e. animates on application ticks), you can start or stop the animation with a specified time interval. Every `xSpriteAnimation` is scheduled by the `xApplication`.
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "../xSDL/xOrchestrable.h"
|
||||
#include "../xSDL/xApplication.h"
|
||||
#include "../xSDL/xController.h"
|
||||
#include "../xSDL/xElement.h"
|
||||
#include "../xSDL/xDrawable.h"
|
||||
#include "../xSDL/xSprite.h"
|
||||
#include "../xSDL/xSpriteAnimation.h"
|
||||
#include "../xSDL/xSpriteGroup.h"
|
||||
|
||||
#endif
|
|
@ -139,7 +139,7 @@ bool xApplication::setImage(const char *url){
|
|||
|
||||
|
||||
// // Anti conflit inter-thread
|
||||
// _mutex_hit.try_lock();
|
||||
// _mutex_hit.lock();
|
||||
|
||||
// /* (1) On recupere le SDL_Rect destination du sprite courant */
|
||||
// int xIndex = -1;
|
||||
|
@ -224,7 +224,7 @@ bool xApplication::setImage(const char *url){
|
|||
// bool xApplication::hit(string current, int movex, int movey){
|
||||
// if( !this->status() ) return true;
|
||||
|
||||
// _mutex_hit.try_lock();
|
||||
// _mutex_hit.lock();
|
||||
|
||||
// /* (1) On recupere le SDL_Rect destination du sprite courant */
|
||||
// xSprite *sprite = NULL;
|
||||
|
@ -245,29 +245,29 @@ bool xApplication::setImage(const char *url){
|
|||
|
||||
|
||||
/** adds new sprite to draw */
|
||||
void xApplication::push(xElement* sprite){
|
||||
_mutex_draw.try_lock();
|
||||
void xApplication::push(xDrawable* sprite){
|
||||
_mutex_draw.lock();
|
||||
_sprites.insert(sprite);
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** removes a sprite to draw (from its address) */
|
||||
void xApplication::pull(xElement* sprite){
|
||||
_mutex_draw.try_lock();
|
||||
void xApplication::pull(xDrawable* sprite){
|
||||
_mutex_draw.lock();
|
||||
_sprites.erase(sprite);
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** clears the scene */
|
||||
void xApplication::clear(){
|
||||
_mutex_draw.try_lock();
|
||||
_mutex_draw.lock();
|
||||
_sprites.clear();
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** Update the scene */
|
||||
void xApplication::render(){
|
||||
_mutex_draw.try_lock();
|
||||
_mutex_draw.lock();
|
||||
|
||||
/* 1. clear scene */
|
||||
SDL_RenderClear(_renderer);
|
||||
|
@ -281,9 +281,8 @@ void xApplication::render(){
|
|||
|
||||
|
||||
/* 4. draw every sprite */
|
||||
set<xElement*>::iterator it;
|
||||
for( it = _sprites.begin() ; it != _sprites.end() ; it++ ){
|
||||
xElement* sprite = *it;
|
||||
for( set<xDrawable*>::iterator it = _sprites.begin() ; it != _sprites.end() ; it++ ){
|
||||
xDrawable* sprite = *it;
|
||||
sprite->draw(_renderer);
|
||||
}
|
||||
|
||||
|
@ -308,7 +307,7 @@ void xApplication::schedule(){
|
|||
const uint32_t ticks = SDL_GetTicks();
|
||||
|
||||
// trigger tick() on registered orchestrables
|
||||
_mutex_orchestrate.try_lock();
|
||||
_mutex_orchestrate.lock();
|
||||
set<xOrchestrable*>::iterator it;
|
||||
for( it = _orchestrables.begin() ; it != _orchestrables.end() ; it++ ){
|
||||
xOrchestrable* orchestrable = *it;
|
||||
|
@ -324,13 +323,13 @@ void xApplication::schedule(){
|
|||
}
|
||||
|
||||
void xApplication::addOrchestrable(xOrchestrable* o){
|
||||
_mutex_orchestrate.try_lock();
|
||||
_mutex_orchestrate.lock();
|
||||
_orchestrables.insert(o);
|
||||
_mutex_orchestrate.unlock();
|
||||
}
|
||||
|
||||
void xApplication::removeOrchestrable(xOrchestrable* o){
|
||||
_mutex_orchestrate.try_lock();
|
||||
_mutex_orchestrate.lock();
|
||||
_orchestrables.erase(o);
|
||||
_mutex_orchestrate.unlock();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <stdexcept>
|
||||
#include "xElement.h"
|
||||
#include "xDrawable.h"
|
||||
#include "xController.h"
|
||||
#include "xOrchestrable.h"
|
||||
using namespace std;
|
||||
|
@ -41,8 +41,8 @@
|
|||
// bool hit(string current, int movex=0, int movey=0); // Gestion des collisions
|
||||
|
||||
/** scene */
|
||||
void push(xElement* sprite);
|
||||
void pull(xElement *sprite);
|
||||
void push(xDrawable* sprite);
|
||||
void pull(xDrawable *sprite);
|
||||
void clear();
|
||||
|
||||
void render();
|
||||
|
@ -64,24 +64,24 @@
|
|||
void syncFps();
|
||||
|
||||
// fps management
|
||||
uint32_t _lasttick;
|
||||
uint32_t _fpstime;
|
||||
uint32_t _lasttick { 0 };
|
||||
uint32_t _fpstime { (int) 1000.0/60 };
|
||||
|
||||
// event management
|
||||
xController _controller;
|
||||
|
||||
// sprites
|
||||
set<xElement*> _sprites;
|
||||
set<xDrawable*> _sprites;
|
||||
|
||||
// execution pool
|
||||
set<xOrchestrable*> _orchestrables;
|
||||
|
||||
// sdl objects
|
||||
SDL_Window *_window;
|
||||
SDL_Rect _winrect;
|
||||
SDL_Window *_window { NULL };
|
||||
SDL_Rect _winrect { 0, 0, 0, 0 };
|
||||
|
||||
SDL_Renderer *_renderer;
|
||||
SDL_Texture *_texture;
|
||||
SDL_Renderer *_renderer { NULL };
|
||||
SDL_Texture *_texture { NULL };
|
||||
|
||||
// thread safety
|
||||
mutex _mutex_draw;
|
||||
|
|
|
@ -12,29 +12,24 @@ xController::~xController(){
|
|||
void xController::handleEvent(SDL_Event* event){
|
||||
_mutex.lock();
|
||||
|
||||
map<SDL_EventType, EventHandler>::iterator found = _handlers.find( (SDL_EventType) event->type );
|
||||
|
||||
// ignore no handler found
|
||||
if( found == _handlers.end() ){
|
||||
_mutex.unlock();
|
||||
return;
|
||||
for( set<xEventHandler*>::iterator it = _handlers.begin() ; it != _handlers.end() ; it++ ){
|
||||
xEventHandler* handler = (*it);
|
||||
handler->handle(event);
|
||||
}
|
||||
|
||||
(*found->second)(event);
|
||||
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
// bind a new handler
|
||||
void xController::attachEvent(SDL_EventType t, EventHandlerArg){
|
||||
void xController::attachEvent(xEventHandler* handler){
|
||||
_mutex.lock();
|
||||
_handlers[ t ] = handler;
|
||||
_handlers.insert(handler);
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
// removes an existing handler
|
||||
void xController::detachEvent(SDL_EventType t){
|
||||
void xController::detachEvent(xEventHandler* handler){
|
||||
_mutex.lock();
|
||||
_handlers.erase(t);
|
||||
_handlers.erase(handler);
|
||||
_mutex.unlock();
|
||||
}
|
|
@ -3,11 +3,10 @@
|
|||
|
||||
#include "SDL.h"
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
#include <set>
|
||||
#include "xEventHandler.h"
|
||||
|
||||
#define EventHandlerArg void(* handler)(SDL_Event*)
|
||||
#define EventHandler void(*)(SDL_Event*)
|
||||
using namespace std;
|
||||
|
||||
class xController{
|
||||
|
||||
|
@ -19,12 +18,12 @@
|
|||
void handleEvent(SDL_Event* event);
|
||||
|
||||
// manage handlers
|
||||
void attachEvent(SDL_EventType t, EventHandlerArg);
|
||||
void detachEvent(SDL_EventType t);
|
||||
void attachEvent(xEventHandler* handler);
|
||||
void detachEvent(xEventHandler* handler);
|
||||
|
||||
private:
|
||||
// event handlers
|
||||
map<SDL_EventType, EventHandler> _handlers;
|
||||
set<xEventHandler*> _handlers;
|
||||
|
||||
// thread safety
|
||||
mutex _mutex;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "xDrawable.h"
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "SDL.h"
|
||||
|
||||
struct xElement {
|
||||
struct xDrawable {
|
||||
virtual void draw(SDL_Renderer* renderer) = 0;
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
#include "xElement.h"
|
|
@ -0,0 +1 @@
|
|||
#include "xEventHandler.h"
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef DEF_XEVENT_HANDLER_H
|
||||
#define DEF_XEVENT_HANDLER_H
|
||||
|
||||
#include "SDL.h"
|
||||
using namespace std;
|
||||
|
||||
class xEventHandler {
|
||||
|
||||
public:
|
||||
|
||||
// handles the event
|
||||
virtual void handle(SDL_Event* event) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
199
xSDL/xSprite.cpp
199
xSDL/xSprite.cpp
|
@ -2,38 +2,56 @@
|
|||
|
||||
/** clean SDL objects */
|
||||
xSprite::~xSprite(){
|
||||
_mutex.try_lock();
|
||||
_mutex.lock();
|
||||
SDL_FreeSurface( _surface );
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** empty sprite */
|
||||
xSprite::xSprite(){
|
||||
_type = "basic";
|
||||
/** copy constructor */
|
||||
xSprite::xSprite(const xSprite& other){
|
||||
// copy surface
|
||||
if( other._surface != NULL ){
|
||||
this->setSurface( SDL_ConvertSurface(other._surface, other._surface->format, SDL_SWSURFACE) );
|
||||
}
|
||||
this->setClip(other._clip);
|
||||
this->project(other._projection);
|
||||
}
|
||||
|
||||
/** 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);
|
||||
}
|
||||
xSprite::xSprite(const char *url, int clip_x, int clip_y, int clip_w, int clip_h){
|
||||
this->setSurface(url);
|
||||
this->setClip(clip_x, clip_y, clip_w, clip_h);
|
||||
}
|
||||
|
||||
/** image sprite with clip and projection */
|
||||
xSprite::xSprite(const char *url, SDL_Rect clip, SDL_Rect projection){
|
||||
this->setSurface(url);
|
||||
this->setClip(clip);
|
||||
this->project(projection);
|
||||
}
|
||||
xSprite::xSprite(const char *url, int clip_x, int clip_y, int clip_w, int clip_h, int project_x, int project_y, int project_w, int project_h){
|
||||
this->setSurface(url);
|
||||
this->setClip(clip_x, clip_y, clip_w, clip_h);
|
||||
this->project(project_x, project_y, project_w, project_h);
|
||||
}
|
||||
|
||||
/** update sprite to rhb color */
|
||||
void xSprite::setSurface(const int rgba[]){
|
||||
_mutex.try_lock();
|
||||
_mutex.lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
|
@ -41,8 +59,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");
|
||||
}
|
||||
|
@ -53,7 +69,7 @@ void xSprite::setSurface(const int rgba[]){
|
|||
|
||||
/** update sprite to image */
|
||||
void xSprite::setSurface(const char *url){
|
||||
_mutex.try_lock();
|
||||
_mutex.lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
|
@ -67,10 +83,9 @@ 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();
|
||||
_mutex.lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
|
@ -84,129 +99,57 @@ 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(){
|
||||
_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};
|
||||
const SDL_Surface* xSprite::surface(){
|
||||
_mutex.lock();
|
||||
SDL_Surface* surface = _surface;
|
||||
_mutex.unlock();
|
||||
return surface;
|
||||
}
|
||||
|
||||
/** set surface dimensions */
|
||||
void xSprite::dimensions(SDL_Rect r){
|
||||
_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};
|
||||
/** set sprite clip */
|
||||
void xSprite::setClip(SDL_Rect clip){
|
||||
_mutex.lock();
|
||||
_clip = clip;
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** set surface dimensions + clip */
|
||||
void xSprite::dimensions(SDL_Rect r, SDL_Rect clip){
|
||||
_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};
|
||||
_mutex.unlock();
|
||||
void xSprite::setClip(int x, int y, int w, int h){
|
||||
setClip( (SDL_Rect){x, y, w, h} );
|
||||
}
|
||||
|
||||
/** 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; }
|
||||
/** gets sprite clip */
|
||||
const SDL_Rect xSprite::clip(){
|
||||
_mutex.lock();
|
||||
const SDL_Rect clip = _clip;
|
||||
_mutex.unlock();
|
||||
return clip;
|
||||
}
|
||||
|
||||
/** set sprite projection */
|
||||
void xSprite::project(SDL_Rect dest){
|
||||
_mutex.lock();
|
||||
_projection = dest;
|
||||
_mutex.unlock();
|
||||
}
|
||||
void xSprite::project(int x, int y, int w, int h){
|
||||
project( (SDL_Rect){x, y, w, h} );
|
||||
}
|
||||
/** gets sprite projection */
|
||||
const SDL_Rect xSprite::projection(){
|
||||
_mutex.lock();
|
||||
const SDL_Rect projection = _projection;
|
||||
_mutex.unlock();
|
||||
return projection;
|
||||
}
|
||||
|
||||
/** draws to renderer */
|
||||
void xSprite::draw(SDL_Renderer* renderer){
|
||||
_mutex.try_lock();
|
||||
_mutex.lock();
|
||||
|
||||
SDL_RenderCopy(
|
||||
renderer,
|
||||
SDL_CreateTextureFromSurface(renderer, this->surface()),
|
||||
this->src(),
|
||||
this->dst()
|
||||
SDL_CreateTextureFromSurface(renderer, _surface),
|
||||
&_clip,
|
||||
&_projection
|
||||
);
|
||||
_mutex.unlock();
|
||||
}
|
|
@ -6,54 +6,54 @@
|
|||
#include <mutex>
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include "xElement.h"
|
||||
#include "xDrawable.h"
|
||||
#include "xApplication.h"
|
||||
using namespace std;
|
||||
|
||||
class xSprite : public xElement {
|
||||
class xSprite : public xDrawable{
|
||||
|
||||
public:
|
||||
xSprite(); // empty
|
||||
xSprite(const int rgba[]); // color sprite
|
||||
xSprite(const char *url); // image sprite
|
||||
xSprite(SDL_Surface *s); // copy sprite
|
||||
~xSprite();
|
||||
// copy constructor
|
||||
xSprite(const xSprite& other);
|
||||
|
||||
// color sprite
|
||||
xSprite(const int rgba[]);
|
||||
// image sprite
|
||||
xSprite(const char *url);
|
||||
// image with default clip
|
||||
xSprite(const char *url, SDL_Rect clip);
|
||||
// image with default clip
|
||||
xSprite(const char *url, int clip_x, int clip_y, int clip_w, int clip_h);
|
||||
// image with default clip and projection
|
||||
xSprite(const char *url, SDL_Rect clip, SDL_Rect projection);
|
||||
// image with default clip and projection
|
||||
xSprite(const char *url, int clip_x, int clip_y, int clip_w, int clip_h, int project_x, int project_y, int project_w, int project_h);
|
||||
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
|
||||
const SDL_Surface* surface();
|
||||
|
||||
// move the sprite
|
||||
// const bool* move(double xSpeed, double ySpeed);
|
||||
// sets the sprite clip
|
||||
void setClip(SDL_Rect clip);
|
||||
void setClip(int x, int y, int w, int h);
|
||||
const SDL_Rect clip();
|
||||
|
||||
// action to apply on collision
|
||||
// virtual void onCollide(vector<bool> from, xSprite* by);
|
||||
// set projection into scene
|
||||
void project(SDL_Rect dest);
|
||||
void project(int x, int y, int w, int h);
|
||||
const SDL_Rect projection();
|
||||
|
||||
// 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();
|
||||
|
||||
// implement xElement
|
||||
// implement xDrawable
|
||||
virtual void draw(SDL_Renderer* renderer) override;
|
||||
private:
|
||||
SDL_Surface* _surface = NULL;
|
||||
SDL_Rect _clip { 0, 0, 0, 0 };
|
||||
SDL_Rect _projection { 0, 0, 0, 0 };
|
||||
|
||||
protected:
|
||||
string _type;
|
||||
|
||||
SDL_Surface* _surface = NULL;
|
||||
SDL_Rect _dst;
|
||||
SDL_Rect _src;
|
||||
|
||||
mutex _mutex;
|
||||
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
|
|
@ -0,0 +1,106 @@
|
|||
#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();
|
||||
}
|
||||
|
||||
/** apply relative displace for each sprite */
|
||||
void xSpriteGroup::displace(int x, int y, int w, int h){
|
||||
displace( (SDL_Rect){x,y,w,h} );
|
||||
}
|
||||
void xSpriteGroup::displace(SDL_Rect relative_displace){
|
||||
_mutex.lock();
|
||||
|
||||
for( set<xSprite*>::iterator it = _sprites.begin() ; it != _sprites.end() ; it++ ) {
|
||||
xSprite* sprite = (*it);
|
||||
const SDL_Rect actual_projection = sprite->projection();
|
||||
|
||||
sprite->project(
|
||||
actual_projection.x + relative_displace.x,
|
||||
actual_projection.y + relative_displace.y,
|
||||
actual_projection.w + relative_displace.w,
|
||||
actual_projection.h + relative_displace.h
|
||||
);
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** draws to renderer */
|
||||
void xSpriteGroup::draw(SDL_Renderer* renderer){
|
||||
_mutex.lock();
|
||||
|
||||
// only draw active sprite if animated
|
||||
if( _animated ){
|
||||
|
||||
// invalid active index
|
||||
if( _active_sprite >= _sprites.size() ) {
|
||||
_active_sprite = 0;
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
set<xSprite*>::iterator at_index = _sprites.begin();
|
||||
advance(at_index, _active_sprite);
|
||||
if( at_index == _sprites.end() ){
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
(*at_index)->draw(renderer);
|
||||
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// else draw every sprite
|
||||
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();
|
||||
const uint32_t time_index = ticks / _animation_interval;
|
||||
_active_sprite = time_index % _sprites.size();
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** orchestrate the animation */
|
||||
void xSpriteGroup::animate(uint32_t interval){
|
||||
_mutex.lock();
|
||||
_animated = true;
|
||||
_animation_interval = interval;
|
||||
_active_sprite = 0;
|
||||
xApplication::get()->addOrchestrable(this);
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** stops orchestrating the animation */
|
||||
void xSpriteGroup::freeze(){
|
||||
_mutex.lock();
|
||||
xApplication::get()->removeOrchestrable(this);
|
||||
_mutex.unlock();
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#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();
|
||||
|
||||
// apply relative displace for each sprite
|
||||
void displace(SDL_Rect relative_displace);
|
||||
void displace(int x, int y, int w, int h);
|
||||
|
||||
// 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:
|
||||
set<xSprite*> _sprites;
|
||||
|
||||
// if not animated, draw all sprites, else draw one at a time
|
||||
bool _animated = false;
|
||||
// active sprite for animation
|
||||
size_t _active_sprite = 0;
|
||||
uint32_t _animation_interval = 0;
|
||||
|
||||
mutex _mutex;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue