Create project barebone
- Create makefile that compiles everything and xSDL as a shared library (.so) - Create xSDL base library (not stable) - Add vscode settings (include path) - Default main.h
This commit is contained in:
parent
a01d9f0fc0
commit
bbf5c25e8e
|
@ -0,0 +1,2 @@
|
|||
/build/
|
||||
/gitignore/
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"C_Cpp.default.includePath": [
|
||||
"/usr/include/SDL2/"
|
||||
],
|
||||
"files.associations": {
|
||||
"exception": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"string": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"deque": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"fstream": "cpp",
|
||||
"limits": "cpp",
|
||||
"sstream": "cpp",
|
||||
"system_error": "cpp",
|
||||
"new": "cpp",
|
||||
"array": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string_view": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"mutex": "cpp",
|
||||
"ostream": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "Enabled"
|
||||
}
|
29
README.md
29
README.md
|
@ -1,2 +1,29 @@
|
|||
# xmario
|
||||
## xSDL
|
||||
|
||||
```yaml
|
||||
package: xSDL
|
||||
language: c++
|
||||
version: 0.1.0
|
||||
author: xdrm-brackets
|
||||
```
|
||||
|
||||
xSDL is a simple 2D wrapper around the SDL2 to make your life easier.
|
||||
|
||||
### Documentation
|
||||
|
||||
The API aims to be straightforward as possible and tries to take advantage of patterns and principles to achieve its goal.
|
||||
|
||||
> xSDL can be compiled as a dynamic library (_e.g. lib.so_). The include header is located in _include/xSDL.h_. It can also be compiled directly within your application.
|
||||
|
||||
The class `xApplication` is a singleton representing your application, its window, renderer, etc. An `xApplication` features a `xController` that manages user input.
|
||||
|
||||
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 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
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DEF_XSDL_H
|
||||
#define DEF_XSDL_H
|
||||
|
||||
#include "../xSDL/xApplication.h"
|
||||
#include "../xSDL/xController.h"
|
||||
#include "../xSDL/xElement.h"
|
||||
#include "../xSDL/xSprite.h"
|
||||
#include "../xSDL/xSpriteAnimation.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef DEF_MAIN_H
|
||||
#define DEF_MAIN_H
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "include/xSDL.h"
|
||||
// #include "include/xMario.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define BLOC_WIDTH 32
|
||||
#define BLOC_HEIGHT 20
|
||||
#define FPS 40
|
||||
#define BLOC_SIZE 32
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
.PHONY: build/exe
|
||||
SDL_FLAGS=`pkg-config sdl2 SDL2_image --cflags --libs`
|
||||
FLAGS=-pthread -std=c++11 $(SDL_FLAGS) -Wall -Wextra
|
||||
CC=g++ $(FLAGS)
|
||||
CC_STATIC=$(CC) -fPIC
|
||||
CC_SHARED=g++ -shared
|
||||
CUR_DIR=$(shell pwd)
|
||||
|
||||
# get list of '.o' files to be generated for 'build/include/libxsdl.so' target
|
||||
XSDL_O_FILES=$(shell ls -l xSDL/*.cpp | awk '{print $$NF}' | sed 's/^xSDL\/\(.\+\)\.cpp$$/build\/static\/\1.o/g')
|
||||
|
||||
prepare:
|
||||
test -d build/ || mkdir build/
|
||||
test -d build/static || mkdir build/static
|
||||
test -d build/include || mkdir build/include
|
||||
|
||||
clean:
|
||||
test -d build/ && rm -r build/ || true
|
||||
|
||||
run:
|
||||
LD_LIBRARY_PATH="$(CUR_DIR)/build/include/:$LD_LIBRARY_PATH" ./build/exe;
|
||||
|
||||
# build executable
|
||||
build/exe: build/main.o build/include/libxsdl.so
|
||||
$(CC) -L$(CUR_DIR)/build/include/ -o $@ $< -lxsdl
|
||||
|
||||
# xSDL lib static objects
|
||||
build/static/%.o: xSDL/%.cpp
|
||||
$(CC_STATIC) -c $^ -o $@
|
||||
|
||||
# xSDL shared (dynamic) library
|
||||
build/include/libxsdl.so: $(XSDL_O_FILES)
|
||||
$(CC_SHARED) -Wl,-soname,libxsdl.so -o $@ $^
|
||||
|
||||
# xMario lib
|
||||
build/xMario.o: xMario/*.cpp
|
||||
$(CC) -o $@ $^
|
||||
|
||||
# build main
|
||||
build/main.o: main.cpp
|
||||
$(CC) -o $@ -c $^
|
|
@ -0,0 +1,347 @@
|
|||
#include "xApplication.h"
|
||||
|
||||
xApplication* xApplication::_instance = nullptr;
|
||||
|
||||
|
||||
/** Static singleton builder */
|
||||
xApplication* xApplication::create(const char *t, int w, int h){
|
||||
if( xApplication::_instance != nullptr ){
|
||||
throw runtime_error("[xApplication] instance already created");
|
||||
}
|
||||
|
||||
xApplication::_instance = new xApplication(t, w, h);
|
||||
|
||||
if( xApplication::_instance == nullptr ){
|
||||
throw runtime_error("[xApplication] cannot instanciate");
|
||||
}
|
||||
|
||||
return xApplication::_instance;
|
||||
}
|
||||
|
||||
/** Static singleton getter */
|
||||
xApplication* xApplication::get(){
|
||||
if( xApplication::_instance == nullptr ){
|
||||
throw runtime_error("[xApplication] instance not created yet");
|
||||
}
|
||||
|
||||
return xApplication::_instance;
|
||||
}
|
||||
|
||||
/** Private singleton constructor */
|
||||
xApplication::xApplication(const char *t, int w, int h){
|
||||
// default values
|
||||
_lasttick = SDL_GetTicks();
|
||||
_fpstime = 1000/60;
|
||||
_window = NULL;
|
||||
_renderer = NULL;
|
||||
_texture = NULL;
|
||||
|
||||
// init SDL subsystems
|
||||
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
|
||||
|
||||
// create window
|
||||
_window = SDL_CreateWindow(
|
||||
t,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
w,
|
||||
h,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL
|
||||
);
|
||||
if( _window == NULL ){
|
||||
throw runtime_error("[xApplication] cannot create SDL window");
|
||||
}
|
||||
|
||||
// store window dimensions
|
||||
_winrect.x = 0; _winrect.y = 0;
|
||||
_winrect.w = w; _winrect.h = h;
|
||||
SDL_GetWindowSize(_window, &_winrect.w, &_winrect.h);
|
||||
|
||||
// create renderer
|
||||
_renderer = SDL_CreateRenderer(
|
||||
_window,
|
||||
-1,
|
||||
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
|
||||
);
|
||||
if( _renderer == NULL ){
|
||||
throw runtime_error("[xApplication] cannot create SDL renderer");
|
||||
}
|
||||
}
|
||||
|
||||
/** clean resources */
|
||||
xApplication::~xApplication(){
|
||||
_sprites.clear();
|
||||
|
||||
SDL_DestroyTexture(_texture);
|
||||
SDL_DestroyRenderer(_renderer);
|
||||
SDL_DestroyWindow( _window );
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
/** SDL getters */
|
||||
SDL_Window* xApplication::window(){ return _window; }
|
||||
SDL_Renderer* xApplication::renderer(){ return _renderer; }
|
||||
|
||||
/** Set rgba background */
|
||||
void xApplication::setBackground(Uint8 r, Uint8 g, Uint8 b, Uint8 a){
|
||||
SDL_SetRenderDrawColor( _renderer, r, g, b, a );
|
||||
}
|
||||
|
||||
/** Sets image background */
|
||||
bool xApplication::setImage(const char *url){
|
||||
_texture = IMG_LoadTexture( _renderer, url );
|
||||
return _texture != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* [COLLIDE] Retourne si 2 objets sont en collision
|
||||
=========================================================*/
|
||||
// collisions <vector<bool>*>
|
||||
// [0] -> VRAI si collision a droite
|
||||
// [1] -> VRAI si collision a gauche
|
||||
// [2] -> VRAI si collision en haut
|
||||
// // [3] -> VRAI si collision en bas
|
||||
// bool xApplication::collide(SDL_Rect a, SDL_Rect b, vector<bool>& cols){
|
||||
// if( !this->status() ) return true;
|
||||
|
||||
// // Verification de collisions
|
||||
// bool outLeft = (a.x >= b.x+b.w ); // Trop a droite
|
||||
// bool outRight = (a.x+a.w <= b.x ); // Trop a gauche
|
||||
// bool outUp = (a.y >= b.y+b.h ); // Trop en haut
|
||||
// bool outDown = (a.y+a.h <= b.y ); // Trop en bas
|
||||
|
||||
|
||||
// // Calcule du bord en question
|
||||
// int distLeft = abs( (a.x+a.w) - b.x );
|
||||
// int distRight = abs( a.x - (b.x+b.w) );
|
||||
// int distBottom = abs( a.y - (b.y+b.h) );
|
||||
// int distTop = abs( (a.y+a.h) - b.y );
|
||||
|
||||
|
||||
// // Valeurs de retour pointeur
|
||||
// cols[0] = !outRight && distRight <= 1; // plus proche de droite
|
||||
// cols[1] = !outLeft && distLeft <= 2; // plus proche de gauche
|
||||
// cols[2] = !outUp && distTop <= 2; // plus proche du haut
|
||||
// cols[3] = !outDown && distBottom <= 1; // plus proche du bas
|
||||
|
||||
|
||||
// // On retourne si il y a collision ou pas
|
||||
// return !( outRight || outLeft || outUp || outDown );
|
||||
// }
|
||||
|
||||
// /* [HIT] Retourne si une texture est en collision avec une autre
|
||||
// =========================================================*/
|
||||
// bool xApplication::hit(xSprite* current, int movex, int movey){
|
||||
// if( !this->status() ) return true;
|
||||
|
||||
|
||||
// // Anti conflit inter-thread
|
||||
// _mutex_hit.try_lock();
|
||||
|
||||
// /* (1) On recupere le SDL_Rect destination du sprite courant */
|
||||
// int xIndex = -1;
|
||||
// for( int i = 0 ; i < _sprites.size() ; i++ )
|
||||
// if( _sprites[i] == current ){
|
||||
// xIndex = i;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if( xIndex == -1 ){
|
||||
// _mutex_hit.unlock();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
// SDL_Rect a = *current->dst();
|
||||
// a.x += movex;
|
||||
// a.y += movey;
|
||||
|
||||
// // Contiendra le sens de collision
|
||||
// vector<bool> collideFrom(4, false);
|
||||
// // Contiendra le sens de collision
|
||||
// vector<bool> collideTo(4, false);
|
||||
|
||||
|
||||
// /* (2) On regarde si en dehors de la fenetre */
|
||||
// if( (a.x < _winrect.x ) // Inclus a droite
|
||||
// || (a.x+a.w > _winrect.x+_winrect.w ) // Inclus a gauche
|
||||
// || (a.y < _winrect.y ) // Inclus en haut
|
||||
// || (a.y+a.h > _winrect.y+_winrect.h ) // Inclus en bas
|
||||
// ){
|
||||
// // Si on tombe, on meurt
|
||||
// if( a.y+a.h > _winrect.y+_winrect.h )
|
||||
// state = 2;
|
||||
|
||||
// cerr << _indexes[xIndex] << " collide with WINDOW" << endl;
|
||||
// _mutex_hit.unlock();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
// /* (3) On compare avec toutes les autres textures */
|
||||
// for( int i = 0 ; i < _sprites.size() ; i++ ){
|
||||
|
||||
// // Si c'est pas le sprite courant
|
||||
// if( _sprites[i] != current ){
|
||||
|
||||
// // On verifie que le sprite n'entre pas en collision
|
||||
// if( this->collide(a, *(_sprites[i])->dst(), collideTo) ){
|
||||
|
||||
|
||||
|
||||
// // On recupere la surface en collision inverse
|
||||
// collideFrom[0] = collideTo[1]; // On inverse Droite
|
||||
// collideFrom[1] = collideTo[0]; // et Gauche
|
||||
// collideFrom[2] = collideTo[3]; // On inverse Haut
|
||||
// collideFrom[3] = collideTo[2]; // et Bas
|
||||
|
||||
// // On lance les listeners de collision
|
||||
// _sprites[i]->onCollide(collideTo, current);
|
||||
// current->onCollide(collideFrom, _sprites[i]);
|
||||
|
||||
// _debug = *(_sprites[i])->dst();
|
||||
|
||||
// _mutex_hit.unlock();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// // On debloque la ressource
|
||||
// _mutex_hit.unlock();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// /* [HIT] Retourne si une texture est en collision avec une autre
|
||||
// =========================================================*/
|
||||
// bool xApplication::hit(string current, int movex, int movey){
|
||||
// if( !this->status() ) return true;
|
||||
|
||||
// _mutex_hit.try_lock();
|
||||
|
||||
// /* (1) On recupere le SDL_Rect destination du sprite courant */
|
||||
// xSprite *sprite = NULL;
|
||||
// sprite = this->get(current);
|
||||
|
||||
// // Gestion erreur
|
||||
// if( sprite == NULL ){
|
||||
// _mutex_hit.unlock();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // Retour du resultat
|
||||
// _mutex_hit.unlock();
|
||||
// return this->hit(sprite, movex, movey);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
/** adds new sprite to draw (with its identifier) */
|
||||
void xApplication::push(string id, xElement* sprite){
|
||||
_mutex_draw.try_lock();
|
||||
_sprites[id] = sprite;
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** removes a sprite to draw (from its identifier) */
|
||||
void xApplication::pull(string id){
|
||||
_mutex_draw.try_lock();
|
||||
_sprites.erase(id);
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** removes a sprite to draw (from its address) */
|
||||
void xApplication::pull(xElement* sprite){
|
||||
_mutex_draw.try_lock();
|
||||
|
||||
map<string, xElement*>::iterator it;
|
||||
for( it = _sprites.begin() ; it != _sprites.end() ; it++ ){
|
||||
if( sprite == it->second ){
|
||||
_sprites.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** clears the scene */
|
||||
void xApplication::clear(){
|
||||
_mutex_draw.try_lock();
|
||||
_sprites.clear();
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** Update the scene */
|
||||
void xApplication::render(){
|
||||
_mutex_draw.try_lock();
|
||||
|
||||
/* 1. clear scene */
|
||||
SDL_RenderClear(_renderer);
|
||||
|
||||
/* 2. apply background color */
|
||||
SDL_RenderDrawRect(_renderer, &_winrect);
|
||||
|
||||
/* 3. add image texture if set */
|
||||
if( _texture != NULL)
|
||||
SDL_RenderCopy(_renderer, _texture, NULL, NULL);
|
||||
|
||||
|
||||
/* 4. draw every sprite */
|
||||
map<string, xElement*>::iterator it = _sprites.begin();
|
||||
for( ; it != _sprites.end() ; it++ ){
|
||||
xElement* sprite = it->second;
|
||||
sprite->draw(_renderer);
|
||||
}
|
||||
|
||||
/* 5. commit renderer */
|
||||
SDL_RenderPresent(_renderer);
|
||||
|
||||
_mutex_draw.unlock();
|
||||
}
|
||||
|
||||
/** Sets FPS */
|
||||
void xApplication::setFps(const uint32_t fps){
|
||||
_fps = fps;
|
||||
}
|
||||
|
||||
/** schedules the main loop */
|
||||
void xApplication::schedule(){
|
||||
// poll events
|
||||
SDL_Event event;
|
||||
while( SDL_PollEvent(&event) != 0 )
|
||||
this->_controller.handleEvent(&event);
|
||||
|
||||
// wait to satisfy FPS
|
||||
this->syncFps(_fps);
|
||||
|
||||
// render
|
||||
this->render();
|
||||
}
|
||||
|
||||
/** synchronizes according to @fps
|
||||
* to be used at the end of the UI loop */
|
||||
void xApplication::syncFps(const int fps){
|
||||
// set fps
|
||||
if( fps != 0 )
|
||||
_fpstime = 1000/fps;
|
||||
|
||||
if( _lasttick == 0 )
|
||||
_lasttick = SDL_GetTicks()-_fpstime;
|
||||
|
||||
// wait if too fast
|
||||
if( SDL_GetTicks()-_lasttick < _fpstime )
|
||||
SDL_Delay( _fpstime - (SDL_GetTicks()-_lasttick) );
|
||||
|
||||
// store now
|
||||
_lasttick = SDL_GetTicks();
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef DEF_XENGINE_H
|
||||
#define DEF_XENGINE_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <stdexcept>
|
||||
#include "xElement.h"
|
||||
#include "xController.h"
|
||||
using namespace std;
|
||||
|
||||
enum xAppState {
|
||||
RUNNING,
|
||||
STOPPING,
|
||||
STOPPED
|
||||
};
|
||||
|
||||
#define EventListener void(*)(SDL_Event*)
|
||||
|
||||
class xApplication{
|
||||
|
||||
public:
|
||||
/** Singleton */
|
||||
static xApplication* create(const char *t, int w, int h);
|
||||
static xApplication* get();
|
||||
|
||||
~xApplication();
|
||||
|
||||
SDL_Window *window();
|
||||
SDL_Renderer *renderer();
|
||||
|
||||
void setBackground(Uint8 r=0xff, Uint8 g=0xff, Uint8 b=0xff, Uint8 a=0xff);
|
||||
bool setImage(const char *url);
|
||||
|
||||
|
||||
// bool collide(SDL_Rect a, SDL_Rect b, vector<bool>& cols); // Collision entre 2 SDL_Rect
|
||||
// bool hit(xSprite *current, int movex=0, int movey=0); // Gestion des collisions
|
||||
// bool hit(string current, int movex=0, int movey=0); // Gestion des collisions
|
||||
|
||||
/** scene */
|
||||
void push(string id, xElement* sprite);
|
||||
void pull(string id);
|
||||
void pull(xElement *sprite);
|
||||
void clear();
|
||||
|
||||
void render();
|
||||
|
||||
// manage main loop and thread loops
|
||||
void setFps(const uint32_t fps);
|
||||
void schedule();
|
||||
|
||||
xAppState state;
|
||||
private:
|
||||
/** Singleton */
|
||||
xApplication(const char *t, int w, int h);
|
||||
static xApplication* _instance;
|
||||
|
||||
void syncFps(const int fps=0);
|
||||
|
||||
// fps management
|
||||
uint32_t _fps = 60;
|
||||
uint32_t _lasttick;
|
||||
uint32_t _fpstime;
|
||||
|
||||
// event management
|
||||
xController _controller;
|
||||
|
||||
// sdl objects
|
||||
SDL_Window *_window;
|
||||
SDL_Rect _winrect;
|
||||
|
||||
SDL_Renderer *_renderer;
|
||||
SDL_Texture *_texture;
|
||||
|
||||
// sprites
|
||||
map<string, xElement*> _sprites;
|
||||
|
||||
// shared threads
|
||||
map<string, thread*> _pool;
|
||||
|
||||
// thread safety
|
||||
mutex _mutex_draw;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
#include "xController.h"
|
||||
|
||||
xController::xController():
|
||||
_handlers()
|
||||
{}
|
||||
|
||||
xController::~xController(){
|
||||
_handlers.clear();
|
||||
}
|
||||
|
||||
// called in scheduling
|
||||
void xController::handleEvent(SDL_Event* event){
|
||||
_mutex.lock();
|
||||
|
||||
map<SDL_EventType, EventListener>::iterator found = _handlers.find( (SDL_EventType) event->type );
|
||||
|
||||
// ignore no handler found
|
||||
if( found == _handlers.end() ){
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
(*found->second)(event);
|
||||
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
// bind a new handler
|
||||
void xController::attachEvent(SDL_EventType t, void(*handler)(SDL_Event*) ){
|
||||
_mutex.lock();
|
||||
_handlers[ t ] = handler;
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
// removes an existing handler
|
||||
void xController::detachEvent(SDL_EventType t, void(*handler)(SDL_Event*) ){
|
||||
_mutex.lock();
|
||||
_handlers.erase(t);
|
||||
_mutex.unlock();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef DEF_XCONTROLLER_H
|
||||
#define DEF_XCONTROLLER_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
#define EventListener void(*)(SDL_Event*)
|
||||
|
||||
class xController{
|
||||
|
||||
public:
|
||||
xController();
|
||||
~xController();
|
||||
|
||||
// called in scheduling
|
||||
void handleEvent(SDL_Event* event);
|
||||
|
||||
// manage handlers
|
||||
void attachEvent(SDL_EventType t, void(*handler)(SDL_Event*) );
|
||||
void detachEvent(SDL_EventType t, void(*handler)(SDL_Event*) );
|
||||
|
||||
private:
|
||||
// event handlers
|
||||
map<SDL_EventType, EventListener> _handlers;
|
||||
|
||||
// thread safety
|
||||
mutex _mutex;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1 @@
|
|||
#include "xElement.h"
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DEF_XELEMENT_H
|
||||
#define DEF_XELEMENT_H
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
struct xElement {
|
||||
virtual void draw(SDL_Renderer* renderer) = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,212 @@
|
|||
#include "xSprite.h"
|
||||
|
||||
/** clean SDL objects */
|
||||
xSprite::~xSprite(){
|
||||
_mutex.try_lock();
|
||||
SDL_FreeSurface( _surface );
|
||||
_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);
|
||||
}
|
||||
|
||||
/** update sprite to rhb color */
|
||||
void xSprite::setSurface(const int rgba[]){
|
||||
_mutex.try_lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
}
|
||||
|
||||
_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");
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** update sprite to image */
|
||||
void xSprite::setSurface(const char *url){
|
||||
_mutex.try_lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
}
|
||||
|
||||
_surface = IMG_Load(url);
|
||||
|
||||
if( _surface == NULL ) {
|
||||
throw runtime_error("[xSprite] setSurface(url) -> NULL surface");
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/* [SETTEXTURE] Modification de la texture texture
|
||||
=========================================================*/
|
||||
void xSprite::setSurface(SDL_Surface *s){
|
||||
_mutex.try_lock();
|
||||
if( _surface != NULL ){
|
||||
SDL_FreeSurface( _surface );
|
||||
_surface = NULL;
|
||||
}
|
||||
|
||||
_surface = s;
|
||||
|
||||
if( _surface == NULL ) {
|
||||
throw runtime_error("[xSprite] setSurface(surface) -> NULL surface");
|
||||
}
|
||||
|
||||
_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};
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** 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};
|
||||
_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();
|
||||
}
|
||||
|
||||
/** 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();
|
||||
SDL_RenderCopy(
|
||||
renderer,
|
||||
SDL_CreateTextureFromSurface(renderer, this->surface()),
|
||||
this->src(),
|
||||
this->dst()
|
||||
);
|
||||
_mutex.unlock();
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef DEF_XSPRITE_H
|
||||
#define DEF_XSPRITE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include "xElement.h"
|
||||
using namespace std;
|
||||
|
||||
class xSprite : public xElement {
|
||||
|
||||
public:
|
||||
xSprite(); // empty
|
||||
xSprite(const int rgba[]); // color sprite
|
||||
xSprite(const char *url); // image sprite
|
||||
xSprite(SDL_Surface *s); // copy sprite
|
||||
~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);
|
||||
|
||||
// action to apply on collision
|
||||
// virtual void onCollide(vector<bool> from, xSprite* by);
|
||||
|
||||
// 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
|
||||
virtual void draw(SDL_Renderer* renderer) override;
|
||||
|
||||
protected:
|
||||
string _type;
|
||||
|
||||
SDL_Surface* _surface = NULL;
|
||||
SDL_Rect _dst;
|
||||
SDL_Rect _src;
|
||||
|
||||
mutex _mutex;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,116 @@
|
|||
#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.try_lock();
|
||||
_frames.push_back( (SDL_Rect){
|
||||
clip.x,
|
||||
clip.y,
|
||||
clip.w,
|
||||
clip.h
|
||||
} );
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
/** clears all frames */
|
||||
void xSpriteAnimation::clearFrames(){
|
||||
_mutex.try_lock();
|
||||
_frames.erase(_frames.begin(), _frames.end());
|
||||
_mutex.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 xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags){
|
||||
uint32_t timer = 0;
|
||||
bool way = true;
|
||||
uint32_t start = 0;
|
||||
|
||||
while( flags&SPRITE_ANIM_INFINITE ){
|
||||
|
||||
// for every frame (sprite)
|
||||
for( uint32_t i = start ; i != xSA->_frames.size() ; i+=(way?1:-1) ){
|
||||
timer = SDL_GetTicks();
|
||||
|
||||
// update current frame clip
|
||||
// xSA->_mutex.try_lock();
|
||||
xSA->_src = xSA->_frames.at(i);
|
||||
// xSA->_mutex.unlock();
|
||||
|
||||
// xSA->manager()->update();
|
||||
|
||||
if( SDL_GetTicks()-timer < t )
|
||||
SDL_Delay( t - (SDL_GetTicks()-timer) );
|
||||
}
|
||||
|
||||
// manage reverse flag
|
||||
if( flags&SPRITE_ANIM_REVERSE ){
|
||||
way = !way;
|
||||
start = (way) ? 0 : xSA->_frames.size()-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// end thread
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** adds the animation to the render */
|
||||
void xSpriteAnimation::start(int t, int flags){
|
||||
_timeout = t;
|
||||
_flags = flags;
|
||||
|
||||
// launch animation
|
||||
_animation = new thread(xSpriteAnimationProcess, this, t, flags);
|
||||
|
||||
// don't wait for the thread to end
|
||||
_animation->detach();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** stops the animation */
|
||||
void xSpriteAnimation::stop(){
|
||||
// stop animation thread
|
||||
delete _animation;
|
||||
if( _animation->joinable() )
|
||||
_animation->join();
|
||||
|
||||
_animation = NULL;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef DEF_XSPRITEANIMATION_H
|
||||
#define DEF_XSPRITEANIMATION_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include "xSprite.h"
|
||||
#include "xApplication.h"
|
||||
#include "xElement.h"
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
using namespace std;
|
||||
|
||||
#define SPRITE_ANIM_ONCE 0b1
|
||||
#define SPRITE_ANIM_INFINITE 0b10
|
||||
#define SPRITE_ANIM_REVERSE 0b100
|
||||
|
||||
class xSpriteAnimation : public xSprite {
|
||||
|
||||
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(int t, int flags=SPRITE_ANIM_ONCE);
|
||||
void stop();
|
||||
|
||||
// implement xElement
|
||||
void draw(SDL_Renderer* renderer) override;
|
||||
|
||||
protected:
|
||||
vector<SDL_Rect> _frames;
|
||||
|
||||
// animation
|
||||
int _timeout;
|
||||
int _flags;
|
||||
|
||||
// animation thread
|
||||
thread *_animation;
|
||||
friend void xSpriteAnimationProcess(xSpriteAnimation *xSA, uint32_t t, int flags);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue