#include "SpaceShip.h" struct Actor { Uint16 idY; Uint16 idX; }; struct Laser { Uint16 idY; Uint16 idX; Uint8 r; Uint8 g; Uint8 b; Uint8 a; }; SpaceShip::SpaceShip() :m_heartX(0), m_heartY(0), m_ally( false ), m_pos( {1100, 300, 42, 42} ), m_shH(0), m_shW(0), m_shape(0x0), m_solid(0x0), m_hiter(0x0), m_shieldLeft(0), m_shieldMax(0), m_shieldLast(0), m_shieldDelay(SHIELD_MAX_DELAY) { for ( int i(0); i < SHOT_NB; i++ ) m_loading[i] = 0; } SpaceShip::SpaceShip( bool ally ) :m_heartX(0), m_heartY(0), m_ally( ally ), m_pos( {1100, 300, 42, 42} ), m_shH(0), m_shW(0), m_shape(0x0), m_solid(0x0), m_hiter(0x0), m_shieldLeft(0), m_shieldMax(0), m_shieldLast(0), m_shieldDelay(SHIELD_MAX_DELAY) { //ctor ally setter } SpaceShip::~SpaceShip() { destroyTabs(); } void SpaceShip::giveHitManager( HitManager* theHitManager ) { m_hiter = theHitManager; } void SpaceShip::setPos( Sint16 x, Sint16 y ) { m_pos.x = x; m_pos.y = y; } SDL_Rect* SpaceShip::getPos() { return &m_pos; } SDL_Rect SpaceShip::getHeartPos() { SDL_Rect rep; rep.x = m_pos.x + 8 * m_heartX + 4; rep.y = m_pos.y + 8 * m_heartY + 4; return rep; } bool SpaceShip::getIsAlive() { return m_solid[m_heartY][m_heartX] > 0; } SDL_Rect* SpaceShip::getHitBox() { return &m_pos; } void SpaceShip::loadShape( std::string path ) { /// Reinitialisation // Déstruction structure et modèle destroyTabs(); // Initialisation des dimensions m_shH = 0; m_shW = 0; m_heartY = 0; m_heartX = 0; // Initialisation du bouclier m_shieldLeft = 0; m_shieldMax = 0; m_shieldLast = 0; m_shieldDelay = SHIELD_MAX_DELAY; /// Lecture du fichier // Création du flux std::ifstream flux( path.c_str() ); // Lecture du modèle std::queue tempo ; std::string line ; while ( std::getline(flux, line) ) { tempo.push( line ); if ( line.length() > m_shW ) m_shW = line.length(); } /// Ecriture du shape ET du solid // Dimensions du vaisseau m_shH = tempo.size(); m_pos.h = 8 * m_shH ; m_pos.w = 8 * m_shW ; // Création des tableaux statiques m_shape = new char*[ m_shH ]; for ( int i(0); i < m_shH; i ++ ) m_shape[i] = new char[ m_shW ]; m_solid = new Uint8*[ m_shH ]; for ( int i(0); i < m_shH; i ++ ) m_solid[i] = new Uint8[ m_shW ]; // Lecture des caractères for ( int i(0); i < m_shH; i++ ) { line = tempo.front(); for ( unsigned int j(0); j < m_shW; j++ ) { if ( j < line.length() && line[j] != ' ' ) { // Présence d'une pièce m_shape[i][j] = line.c_str()[j]; m_solid[i][j] = 255; // Détection du cœur if ( m_shape[i][j] == 'm' ){ m_heartY = i; m_heartX = j; } } else { // Pas de bloc à cet endroit m_shape[i][j] = ' '; m_solid[i][j] = 0; } } tempo.pop(); } /// Détection des actionneurs for ( int i(0); i < m_shH; i++ ) { for ( unsigned int j(0); j < m_shW - 1; j++ ) { // Détection d'une arme if ( m_shape[i][j] == '[' ) { switch ( m_shape[i][j + 1] ) { case '-': m_act[GUN_ID].push_back( { i, j + 1} ); break; case '<': m_act[DISPER_ID].push_back( { i, j + 1} ); break; case '|': m_act[CUTTER_ID].push_back( { i, j + 1} ); break; case 'O': m_act[PHOTO_ID].push_back( { i, j + 1} ); break; case '>': m_act[MISSILE_ID].push_back( { i, j + 1} ); break; case '{': m_act[BREXIT_ID].push_back( { i, j + 1} ); break; case '~': m_act[HECTO_ID].push_back( { i, j + 1} ); break; case '=': m_act[SNIPER_ID].push_back( { i, j + 1} ); break; default : break; } } // Détection d'un bouclier else if ( m_shape[i][j] == '(' && m_shape[i][j+1] == ')' ) { m_shieldMax += SHIELD_1_EARN_HP; m_shieldLeft += SHIELD_1_EARN_HP; m_shieldDelay -= SHIELD_1_EARN_DELAY; m_shields.push_back( { i, j } ); // Blocage du délai minimal if ( m_shieldDelay < SHIELD_MIN_DELAY ) m_shieldDelay = SHIELD_MIN_DELAY; } // Détection d'un pointeur else if ( j < m_shW - 2 && m_shape[i][j] == '{' && m_shape[i][j+2] == '}' ) { // Couleur Uint8 r(0), g(0), b(0); if ( m_shape[i][j+1] == 'y' ) { b = 255; g = 255; } else if ( m_shape[i][j+1] == 'r' ) { r = 255; } else if ( m_shape[i][j+1] == 'g' ) { g = 255; } else if ( m_shape[i][j+1] == 'b' ) { b = 255; } else { r = g = b = 255; } // Ajout du pointeur m_lasers.push_back( { i, j + 1, r, g, b, 128 } ); } } } /// Inversion du vaisseau si il est allié if ( m_ally ){ char sw_c; Uint8 sw_s; // Inversion des composants for ( unsigned int i(0); i < m_shH; i++ ) { for ( unsigned int j(0); j < m_shW / 2; j++ ) { sw_c = m_shape[i][j]; m_shape[i][j] = m_shape[i][m_shW - j - 1]; m_shape[i][m_shW - j - 1] = sw_c; sw_s = m_solid[i][j]; m_solid[i][j] = m_solid[i][m_shW - j - 1]; m_solid[i][m_shW - j - 1] = sw_s; } } // Inversion du cockpit m_heartX = m_shW - m_heartX - 1; // Inversion des armes for ( unsigned int i(0); i < SHOT_NB; i++) { for ( unsigned int k(0); k < m_act[i].size(); k++ ){ m_act[i][k].idX = m_shW - 1 - m_act[i][k].idX; } } // Inversion des boucliers for ( unsigned int k(0); k < m_shields.size(); k++ ){ m_shields[k].idX = m_shW - 1 - m_shields[k].idX; } // Inversion des boucliers for ( unsigned int k(0); k < m_lasers.size(); k++ ){ m_lasers[k].idX = m_shW - 1 - m_lasers[k].idX; } // Traitement des caractères orientés for ( unsigned int i(0); i < m_shH; i++ ) { for ( unsigned int j(0); j < m_shW; j++ ) { switch ( m_shape[i][j] ){ case '<': m_shape[i][j] = '>'; break; case '>': m_shape[i][j] = '<'; break; case ']': m_shape[i][j] = '['; break; case '[': m_shape[i][j] = ']'; break; case ')': m_shape[i][j] = '('; break; case '(': m_shape[i][j] = ')'; break; case '}': m_shape[i][j] = '{'; break; case '{': m_shape[i][j] = '}'; break; case '/': m_shape[i][j] = '\\'; break; case '\\': m_shape[i][j] = '/'; break; default : break; } } } } } Uint32 SpaceShip::countCPU() { Uint32 c( 0 ); // CPU des blocs for ( unsigned int i(0); i < m_shH; i++ ) { for ( unsigned int j(0); j < m_shW; j++ ) { if ( m_shape[i][j] != ' ' ) c += PART_CPU; } } // CPU des armes Uint32 weapCpu[SHOT_NB] = ACTOR_CPU; for ( unsigned int i(1); i < SHOT_NB; i++ ) { c += m_act[i].size() * weapCpu[i]; } // CPU des boucliers c += SHIELD_CPU * m_shields.size(); // Fin return c; } bool SpaceShip::hasShield() { return m_shields.size() > 0; } bool SpaceShip::hasWeapon( int weapId ) { return m_act[ weapId ].size() > 0; } void SpaceShip::draw( SDL_Surface* screen ) { // N'affiche rien si déjà mort if ( !getIsAlive() ) return ; // Enveloppe du bouclier Uint8 shieldLvl(128); if ( m_shieldLeft > 0 ) { shieldLvl = m_shieldLeft * 255 / m_shieldMax ; for ( int i(-2); i < m_shH + 2; i++ ) { stringRGBA( screen, m_pos.x - 16, m_pos.y + 8 * i, "+", 0, shieldLvl, shieldLvl, 255 ); stringRGBA( screen, m_pos.x + m_pos.w + 8, m_pos.y + 8 * i, "+", 0, shieldLvl, shieldLvl, 255 ); } for ( int j(-1); j <= m_shW; j++ ) { stringRGBA( screen, m_pos.x + 8 * j, m_pos.y - 16, "+", 0, shieldLvl, shieldLvl, 255 ); stringRGBA( screen, m_pos.x + 8 * j, m_pos.y + m_pos.h + 8, "+", 0, shieldLvl, shieldLvl, 255 ); } } // Balayae du carénage for ( int i(0); i < m_shH; i++ ) { for ( int j(0); j < m_shW; j++ ) { // Existence d'une pièce if ( m_solid[i][j] > 0 ) { char s[2]; s[0] = m_shape[i][j]; s[1] = 0; // Energie de bouclier disponible if ( m_shieldLeft > 0 ) { stringRGBA( screen, m_pos.x + 8 * j, m_pos.y + 8 * i, s, 255 - shieldLvl, m_solid[i][j], shieldLvl, 255 ); } // Affichage basique else stringRGBA( screen, m_pos.x + 8 * j, m_pos.y + 8 * i, s, 255, m_solid[i][j], m_solid[i][j], 255 ); } } } // Affichage des pointeurs Sint16 u, v, c; for ( unsigned int i(0); i < m_lasers.size(); i ++ ) { u = m_lasers[i].idX * 8 + m_pos.x - 9; v = m_lasers[i].idY * 8 + m_pos.y; while ( u > -8 ) { stringRGBA( screen, u, v, "-", m_lasers[i].r, m_lasers[i].g, m_lasers[i].b, m_lasers[i].a ); u -= 36; } } } void SpaceShip::fire( int weapId ) { if ( ( SDL_GetTicks() - m_loading[weapId] ) > m_hiter->getDecay( weapId ) ) { for ( unsigned int k(0); k < m_act[weapId].size(); k++ ) { if ( m_solid[ m_act[weapId][k].idY ][ m_act[weapId][k].idX ] > 0 ) { m_hiter->triggerWeapon( weapId, m_pos.x + 8*m_act[weapId][k].idX + 4, m_pos.y + 8*m_act[weapId][k].idY + 4, m_ally ); } } m_loading[weapId] = SDL_GetTicks(); } } void SpaceShip::update() { // Si le vaisseau n'est plus existant, alors rien n'existe if ( !getIsAlive() ) return ; // S'il reste du bouclier, il peut absorber les dégats ! if ( m_shieldLeft > 0 ) { Sint32 deg( m_hiter->absorb( m_ally, m_shH, m_shW, m_pos ) ); if ( deg > 0 ) { // La recharge du bouclier est retardée m_shieldLast = SDL_GetTicks(); // Le bouclier en prend un coup if ( deg > m_shieldLeft ) m_shieldLeft = 0; else m_shieldLeft -= deg; } } // S'il reste un carénage, il peut subir des dégâts ! else if ( m_hiter->colide( m_ally, m_solid, m_shH, m_shW, m_pos ) ) { // La recharge du bouclier est retardée m_shieldLast = SDL_GetTicks(); // Peut être que certains blocs ne sont plus attachés au vaisseau ! integrity(); // Certains boucliers sont peut être hors service ! if ( m_shieldMax > 0 ) resetShields(); } // Recharge éventuelle du bouclier if ( m_shieldLeft < m_shieldMax && ( SDL_GetTicks() - m_shieldLast > m_shieldDelay ) ) { m_shieldLeft += SHIELD_REGEN ; if ( m_shieldLeft > m_shieldMax ) m_shieldLeft = m_shieldMax ; } } void SpaceShip::destroyTabs() { // Destruction du modèle graphic if ( m_shape != 0x0 ) { for ( int i(0); i < m_shH; i++ ) { delete[] m_shape[i]; m_shape[i] = 0x0; } delete[] m_shape; m_shape = 0x0; } // Destruction de la carte du blindage if ( m_solid != 0x0 ) { for ( int i(0); i < m_shH; i++ ) { delete[] m_solid[i]; m_solid[i] = 0x0; } delete[] m_solid; m_solid = 0x0; } // Destruction des armes for ( unsigned int i(0); i < SHOT_NB; i++ ) { m_act[i].clear(); } // Destruction du bouclier m_shields.clear(); // Destruction des pointeurs m_lasers.clear(); } void SpaceShip::integrity() { // Création du tableau des liens Sint8 network[ m_shH ][ m_shW ]; for ( int i(0); i < m_shH; i++ ) { for ( int j(0); j < m_shW; j++ ) { network[i][j] = -1; } } // Création du réseau if ( getIsAlive() ) { network[ m_heartY ][ m_heartX ] = 1; std::queue q; // Couples à tester Uint16 y, x; if ( m_heartY > 0 ) q.push( { m_heartY - 1, m_heartX } ); if ( m_heartX > 0 ) q.push( { m_heartY, m_heartX - 1 } ); if ( m_heartY + 1 < m_shH ) q.push( { m_heartY + 1, m_heartX } ); if ( m_heartX + 1 < m_shW ) q.push( { m_heartY, m_heartX + 1} ); while ( !q.empty() ) { y = q.front().idY; x = q.front().idX; if ( m_solid[ y ][ x ] == 0 ) { // Bloc détruit network[ y ][ x ] = 0; } else if ( ( y > 0 && network[ y - 1 ][ x ] == 1 ) // Haut || ( y < m_shH - 1 && network[ y + 1 ][ x ] == 1 ) // Bas || ( x > 0 && network[ y ][ x - 1 ] == 1 ) // Gauche || ( x < m_shW - 1 && network[ y ][ x + 1 ] == 1 ) ) // Droite { // Bloc présent network[ y ][ x ] = 1; // Connexion des blocs adjacents if ( y > 0 && network[ y - 1 ][ x ] == -1 )// Haut q.push( { y - 1, x } ); if ( y < m_shH - 1 && network[ y + 1 ][ x ] == -1 )// Bas q.push( { y + 1, x } ); if ( x > 0 && network[ y ][ x - 1 ] == -1 )// Gauche q.push( { y, x - 1 } ); if ( x < m_shW - 1 && network[ y ][ x + 1 ] == -1 )// Doite q.push( { y, x + 1 } ); } else { // Bloc non connecté network[ y ][ x ] = 0; } q.pop(); } } // Destruction des pièces non connectées for ( int i(0); i < m_shH; i++ ) { for ( int j(0); j < m_shW; j++ ) { if ( m_solid[i][j] > 0 && network[i][j] == -1 ) { Sint16 vx( j - m_heartX ); Sint16 vy( i - m_heartY ); m_hiter->addShot( new Part( m_pos.x + j*8, m_pos.y + i*8, vx, vy, m_solid[i][j], m_shape[i][j], m_ally ) ); m_solid[i][j] = 0; } } } } void SpaceShip::resetShields() { m_shieldDelay = SHIELD_MAX_DELAY; m_shieldMax = 0; for ( unsigned int k(0); k < m_shields.size(); k++ ) { if ( m_solid[ m_shields[k].idY ][ m_shields[k].idX ] > 0 ) { m_shieldDelay -= SHIELD_1_EARN_DELAY; m_shieldMax += SHIELD_1_EARN_HP; } } if ( m_shieldLeft > m_shieldMax ) m_shieldLeft = m_shieldMax; if ( m_shieldDelay < SHIELD_MIN_DELAY ) m_shieldDelay = SHIELD_MIN_DELAY; }