lab.cpp/SDL#4/xSDL/xManager.cpp

509 lines
11 KiB
C++
Raw Normal View History

2016-03-12 23:22:28 +00:00
/* [CONSTRUCTOR] Constructeur de la classe
=========================================================*/
xManager::xManager(const char *t, int w, int h){
// default values
_lasttick = SDL_GetTicks();
2016-03-12 23:22:28 +00:00
_fpstime = 1000/60;
_window = NULL;
_renderer = NULL;
_texture = NULL;
_debug = (SDL_Rect){0, 0, 0, 0};
2016-03-12 23:22:28 +00:00
// Initialisation des sous-sys. SDL
2016-03-15 22:54:12 +00:00
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
2016-03-12 23:22:28 +00:00
// Creation de la fenetre
_window = SDL_CreateWindow(
t,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
w,
h,
2016-03-15 22:54:12 +00:00
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL
2016-03-12 23:22:28 +00:00
);
// Gestion erreur
if( _window == NULL )
return;
2016-03-15 22:54:12 +00:00
cerr << "WINDOW CREATED" << endl;
2016-03-12 23:22:28 +00:00
// On enregistre les dimensions de la fenetre
_winrect.x = 0; _winrect.y = 0;
2016-03-14 22:46:10 +00:00
_winrect.w = w; _winrect.h = h;
SDL_GetWindowSize(_window, &_winrect.w, &_winrect.h);
2016-03-12 23:22:28 +00:00
// Creation du renderer
_renderer = SDL_CreateRenderer(
_window,
-1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
2016-03-15 22:54:12 +00:00
// Gestion erreur
if( _renderer == NULL )
return;
cerr << "RENDERER CREATED" << endl;
2016-03-12 23:22:28 +00:00
}
/* [DESTROYER] Destructeur de la classe
=========================================================*/
xManager::~xManager(){
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow( _window );
SDL_Quit();
}
/* [STATUS] Retourne le status
=========================================================*/
bool xManager::status(){
return _window != NULL && _renderer != NULL;
}
/* [WINDOW] Retourne la fenetre
=========================================================*/
SDL_Window* xManager::window(){ return _window; }
/* [SCREEN] Retourne la fenetre
=========================================================*/
SDL_Renderer* xManager::renderer(){ return _renderer; }
/* [SETBACKGROUND] Modifie la couleur de fond
=========================================================*/
bool xManager::setBackground(Uint8 r, Uint8 g, Uint8 b, Uint8 a){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return false;
2016-03-12 23:22:28 +00:00
SDL_SetRenderDrawColor( _renderer, r, g, b, a );
return true;
}
/* [SETIMAGE] Met une image en fond
=========================================================*/
bool xManager::setImage(const char *url){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return false;
2016-03-12 23:22:28 +00:00
// On cree la texture associee
_texture = IMG_LoadTexture( _renderer, url );
return _texture != NULL;
}
2016-03-14 22:46:10 +00:00
2016-03-13 19:36:16 +00:00
/* [HIT] Retourne si une texture est en collision avec une autre
=========================================================*/
2016-03-14 22:46:10 +00:00
// bool xManager::hit(SDL_Texture *current, int movex, int movey){
// // Anti conflit inter-thread
// _mutex_hit.lock();
2016-03-13 23:06:33 +00:00
2016-03-14 22:46:10 +00:00
// /* (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;
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// if( xIndex == -1 ){
// _mutex_hit.unlock();
// return false;
// }
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// SDL_Rect a = (SDL_Rect){
// (*_dst[xIndex]).x+movex,
// (*_dst[xIndex]).y+movey,
// (*_dst[xIndex]).w,
// (*_dst[xIndex]).h
// };
// SDL_Rect b;
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// /* (2) On regarde si en dehors de la fenetre */
// for( int y = a.y ; y < a.y+a.h ; y++ )
// for( int x = a.x ; x < a.x+a.w ; x++ )
// if( x < _winrect.x || x > _winrect.x+_winrect.w || y < _winrect.y || y>_winrect.y+_winrect.h ){
// // On debloque la ressource
// _mutex_hit.unlock();
// return true;
// }
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// /* (3) On compare avec toutes les autres textures */
// for( int i = 0 ; i < _sprites.size() ; i++ ){
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// // Si c'est pas le sprite courant
// if( _sprites[i] != current ){
// // taille du sprite en cours
// b.x = (*_dst[i]).x;
// b.y = (*_dst[i]).y;
// b.w = (*_dst[i]).w;
// b.h = (*_dst[i]).h;
// for( int y = a.y ; y < a.y+a.h ; y++ )
// for( int x = a.x ; x < a.x+a.w ; x++ )
// if( x>=b.x && x<=b.x+b.w && y>=b.y && y<=b.y+b.h ){
// // On debloque la ressource
// _mutex_hit.unlock();
// return true;
// }
2016-03-14 22:46:10 +00:00
// }
// }
// // On debloque la ressource
// _mutex_hit.unlock();
// return false;
// }
/* [COLLIDE] Retourne si 2 objets sont en collision
=========================================================*/
bool xManager::collide(SDL_Rect a, SDL_Rect b){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return true;
bool notCollide =
(a.x >= b.x+b.w ) // Inclus a droite
|| (a.x+a.w <= b.x ) // Inclus a gauche
|| (a.y >= b.y+b.h ) // Inclus en haut
|| (a.y+a.h <= b.y ); // Inclus en bas
2016-03-15 22:54:12 +00:00
// bool collide = (
// ( ( a.x > b.x && a.x < b.x+b.w )
// || ( a.x+a.w > b.x && a.x+a.w < b.x+b.w ) )
// &&
// ( ( a.y > b.y && a.y < b.y+b.h )
// || ( a.y+a.h > b.y && a.y+a.h < b.y+b.h ) )
// );
return !notCollide;
}
/* [HIT] Retourne si une texture est en collision avec une autre
=========================================================*/
bool xManager::hit(xSprite* current, int movex, int movey){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return true;
// Anti conflit inter-thread
_mutex_hit.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;
/* (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
){
_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()) ){
// DEBUG
2016-03-15 22:54:12 +00:00
// if( i != 35 )
// cerr << "locked by sprite " << i << endl;
_debug = *(_sprites[i])->dst();
// _debug = (SDL_Rect){547-1, 531-1, 2, 2};
// cout << "YES collision" << endl;
_mutex_hit.unlock();
return true;
}
}
}
// On debloque la ressource
_mutex_hit.unlock();
return false;
}
2016-03-14 22:46:10 +00:00
/* [HIT] Retourne si une texture est en collision avec une autre
=========================================================*/
bool xManager::hit(string current, int movex, int movey){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return true;
2016-03-14 22:46:10 +00:00
_mutex_hit.lock();
/* (1) On recupere le SDL_Rect destination du sprite courant */
xSprite *sprite = NULL;
sprite = this->get(current);
2016-03-13 19:36:16 +00:00
2016-03-14 22:46:10 +00:00
// Gestion erreur
if( sprite == NULL ){
2016-03-14 22:46:10 +00:00
_mutex_hit.unlock();
return false;
2016-03-13 19:36:16 +00:00
}
2016-03-14 22:46:10 +00:00
// Retour du resultat
2016-03-13 23:06:33 +00:00
_mutex_hit.unlock();
return this->hit(sprite, movex, movey);
2016-03-13 19:36:16 +00:00
}
/* [GET] Renvoie le sprite
=========================================================*/
xSprite *xManager::get(string index){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return NULL;
// On cherche la texture avec l'index
for( int i = 0 ; i < _indexes.size() ; i++ )
if( _indexes[i] == index )
return _sprites[i];
return NULL;
}
2016-03-12 23:22:28 +00:00
/* [PUSH] Ajoute une texture au rendu principal
=========================================================*/
void xManager::push(string index, xSprite* sprite){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
2016-03-12 23:22:28 +00:00
// On bloque l'acces inter-thread
2016-03-13 23:06:33 +00:00
_mutex_push.lock();
2016-03-12 23:22:28 +00:00
_indexes.push_back( index );
_sprites.push_back( sprite );
2016-03-12 23:22:28 +00:00
// On debloque l'acces
2016-03-13 23:06:33 +00:00
_mutex_push.unlock();
2016-03-12 23:22:28 +00:00
}
/* [PULL] Retire une texture du rendu principal
=========================================================*/
2016-03-13 19:36:16 +00:00
void xManager::pull(string index){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
2016-03-12 23:22:28 +00:00
// On bloque l'acces inter-thread
2016-03-13 23:06:33 +00:00
_mutex_pull.lock();
2016-03-12 23:22:28 +00:00
// On cherche l'indice de la texture
int xIndex = -1;
2016-03-12 23:22:28 +00:00
for( int i = 0 ; i < _indexes.size() ; i++ )
if( _indexes[i] == index ) xIndex = i;
2016-03-12 23:22:28 +00:00
// Si on a rien trouve
if( xIndex == -1 )
2016-03-12 23:22:28 +00:00
return;
// On supprime la texture et ses dimensions
_indexes.erase( _indexes.begin() + xIndex );
_sprites.erase( _sprites.begin() + xIndex );
2016-03-13 19:36:16 +00:00
// On debloque l'acces
2016-03-13 23:06:33 +00:00
_mutex_pull.unlock();
2016-03-13 19:36:16 +00:00
}
/* [PULL] Retire une texture du rendu principal
=========================================================*/
void xManager::pull(xSprite* sprite){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
2016-03-13 19:36:16 +00:00
// On bloque l'acces inter-thread
2016-03-13 23:06:33 +00:00
_mutex_pull.lock();
2016-03-13 19:36:16 +00:00
// On cherche l'indice de la texture
int xIndex = -1;
for( int i = 0 ; i < _sprites.size() ; i++ )
if( _sprites[i] == sprite ) xIndex = i;
2016-03-13 19:36:16 +00:00
// Si on a rien trouve
if( xIndex == -1 )
return;
// On supprime la texture et ses dimensions
_indexes.erase( _indexes.begin() + xIndex );
_sprites.erase( _sprites.begin() + xIndex );
2016-03-12 23:22:28 +00:00
// On debloque l'acces
2016-03-13 23:06:33 +00:00
_mutex_pull.unlock();
2016-03-12 23:22:28 +00:00
}
/* [MANAGEFTP] Gestion de la vitesse de boucle
=========================================================*/
void xManager::manageFps(const int fps){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
/* (1) Definition de fps */
if( fps != 0 )
_fpstime = 1000/fps;
if( _lasttick == 0 )
_lasttick = SDL_GetTicks()-_fpstime;
/* (2) Utilisation en fin de boucle */
// 1 > Si trop rapide, on attends
if( SDL_GetTicks()-_lasttick < _fpstime )
SDL_Delay( _fpstime - (SDL_GetTicks()-_lasttick) );
// On enregistre le temps actuel
_lasttick = SDL_GetTicks();
}
2016-03-12 23:22:28 +00:00
/* [UPDATE] Mise a jour du rendu
=========================================================*/
void xManager::update(){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
2016-03-12 23:22:28 +00:00
// cout << "Update MAIN SPRITE +" << _sprites.size() << " added sprites.." << endl;
// On bloque l'acces inter-thread
2016-03-13 23:06:33 +00:00
_mutex_update.lock();
2016-03-12 23:22:28 +00:00
/* (1) On efface le rendu */
SDL_RenderClear(_renderer);
/* (2) On applique la couleur de fond */
SDL_RenderDrawRect(_renderer, &_winrect);
2016-03-12 23:22:28 +00:00
/* (3) On ajoute le rendu principal (si existe) */
if( _texture != NULL)
SDL_RenderCopy(_renderer, _texture, NULL, NULL);
/* (4) On ajoute toutes les textures pushees */
for( int i = 0 ; i < _sprites.size() ; i++ )
SDL_RenderCopy(
_renderer,
_sprites[i]->texture(),
_sprites[i]->src(),
_sprites[i]->dst()
);
2016-03-12 23:22:28 +00:00
// DEBUG
_debug = (SDL_Rect){_debug.x-1, _debug.y-1, _debug.w+2, _debug.h+2};
SDL_RenderDrawRect(_renderer, &_debug);
2016-03-12 23:22:28 +00:00
/* (n) On affiche le resultat */
SDL_RenderPresent(_renderer);
// On debloque l'acces
2016-03-13 23:06:33 +00:00
_mutex_update.unlock();
2016-03-12 23:22:28 +00:00
}
/* [ATTACHEVENT] Ajoute une fonction a un type d'evenement
2016-03-12 23:22:28 +00:00
=========================================================*/
void xManager::attachEvent(SDL_EventType t, void(*handler)(SDL_Event*)){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
2016-03-12 23:22:28 +00:00
// On attache le type d'evenement a la fonction
_events.push_back( t );
_handlers.push_back( handler );
2016-03-12 23:22:28 +00:00
}
/* [MANAGEEVENTS] Gestion des evenements
=========================================================*/
void xManager::manageEvents(SDL_Event *event){
2016-03-15 22:54:12 +00:00
if( !this->status() ) return;
// On lance les evenements en fonction de leur type
for( int i = 0 ; i < _events.size() ; i ++ )
if( event->type == _events[i] ) // si type ok
(*_handlers[i])(event); // on execute le handler
}
/* [DEBUG] Visualisation des donnees
=========================================================*/
void xManager::debug(){
for( int i = 0 ; i < _sprites.size() ; i++ ){
cerr << "INDEX: " << _indexes[i] << " AT " << i << endl;
cerr << " (" << (*_sprites[i]->dst()).x <<","<<(*_sprites[i]->dst()).y<<") -> (" << (*_sprites[i]->dst()).w << ", " << (*_sprites[i]->dst()).h << ")" << endl;
}
2016-03-12 23:22:28 +00:00
}