Game.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. #include "Game.h"
  2. using namespace std;
  3. Game::Game()
  4. :m_screen( 0x0 ), m_lvlSelect(0), m_shipSelect(0), m_pSelect(0)
  5. {
  6. //ctor
  7. }
  8. Game::~Game()
  9. {
  10. if ( m_screen ) SDL_FreeSurface( m_screen );
  11. m_screen = 0x0;
  12. }
  13. /// Public
  14. bool Game::init()
  15. {
  16. /// [1] Démarrage
  17. // [1.1] Démarrages SDL
  18. if ( SDL_Init( SDL_INIT_VIDEO ) < 0)
  19. {
  20. cout << "Impossible d'initialiser la SDL: " << SDL_GetError() << endl;
  21. return false;
  22. }
  23. // [1.2] Préparation de fermeture
  24. atexit(SDL_Quit);
  25. // [1.3] Para-fenêtre
  26. SDL_WM_SetCaption("ASCII Space Destroyer", 0);
  27. // [1.4] Seed pour nombres aléatoires
  28. srand( time(0) );
  29. /// [2] Préparation des composants
  30. // [2.1] Préparation de la fenêtre
  31. m_screen = SDL_SetVideoMode(1280, 720, 32, SDL_HWSURFACE|SDL_DOUBLEBUF );
  32. if ( !m_screen )
  33. {
  34. cout << "Bug à l'initialisation: " << SDL_GetError() << endl;
  35. return false;
  36. }
  37. // [2.2] Préparation du WaveManager
  38. m_waver.giveHitManager( &m_hiter );
  39. // [2.3] Préparation du joueur
  40. m_player.giveHitManager( &m_hiter );
  41. // [2.4] Préparation du HitManager
  42. //...
  43. /// [3] Finalisation de la procédure
  44. return true;
  45. }
  46. void Game::run()
  47. {
  48. string msg;
  49. while ( true )
  50. {
  51. msg = menu();
  52. if ( msg == "Quit" )
  53. return;
  54. msg.erase(0, 2);
  55. if ( rush( msg ) && ( msg != "Tutoriel" ) )
  56. {
  57. m_score.addVictory();
  58. m_score.giveLoot( msg );
  59. }
  60. m_score.save();
  61. }
  62. }
  63. /// Protected
  64. string Game::menu()
  65. {
  66. /// [1] Préparation
  67. // [1.2] Chargement des index
  68. ifstream levelStream("Resources/Levels/index.txt");
  69. ifstream shipStream("Resources/Ships/index.txt");
  70. ifstream playerStream("Resources/Saves/index.txt");
  71. // [1.3] Variables
  72. string line;
  73. vector< vector<string> > levelDetail;
  74. vector<string> shipNames;
  75. vector<Uint32> shipCpu;
  76. vector<string> playerNames;
  77. bool loop( true );
  78. bool canDrive( false );
  79. // [1.3] Lecture des planètes
  80. while ( getline( levelStream, line ) )
  81. {
  82. if ( line[0] == '>' )
  83. {
  84. // Nouvelle planète
  85. levelDetail.push_back( {} );
  86. }
  87. levelDetail.back().push_back( line );
  88. }
  89. levelStream.close();
  90. // [1.4] Lecture des vaisseaux
  91. while ( getline( shipStream, line ) )
  92. {
  93. shipNames.push_back( line );
  94. shipCpu.push_back( 0 );
  95. }
  96. shipStream.close();
  97. // [1.4] Lecture des joueurs
  98. while ( getline( playerStream, line ) )
  99. {
  100. playerNames.push_back( line );
  101. }
  102. playerStream.close();
  103. // [1._] Erreurs
  104. if ( levelDetail.empty() || shipNames.empty() )
  105. {
  106. cout << "Problème de lecture d'un index." << endl;
  107. return "Quit";
  108. }
  109. // [1.1] Préparation du joueur
  110. m_player.loadShape("Resources/Ships/" + shipNames[m_shipSelect] + ".txt");
  111. m_player.setPos( 50, 100 );
  112. shipCpu[m_shipSelect] = m_player.countCPU();
  113. string weapNames[ SHOT_NB ] = ACTOR_NAME;
  114. m_score.load( playerNames[m_pSelect] );
  115. // [1. ] Pointeur souris
  116. m_input.placerPtr( m_screen );
  117. m_input.afficherPointeur( true );
  118. m_input.capturerPointeur( false );
  119. /// [2] Lancement boucle principale
  120. while ( loop )
  121. {
  122. /// [3] Évènements
  123. // [2.1] Mise à jour des évènements
  124. m_input.updateEvenements();
  125. // [2.2] Gestion de la boucle
  126. loop = !m_input.terminer() && !m_input.getToucheHeld( SDLK_ESCAPE );
  127. if ( loop && m_input.getToucheHeld( SDLK_RETURN ) && canDrive )
  128. loop = false;
  129. // [2.2] Gestion évènements choix du vaisseau
  130. if ( m_input.getToucheInstant( SDLK_RIGHT )
  131. || ( m_input.getBoutonSourisInstant( 1 )
  132. && m_input.getX() < m_screen->w / 2
  133. && m_input.getY() < m_screen->h / 2 ) )
  134. {
  135. m_shipSelect += 1;
  136. if ( m_shipSelect >= shipNames.size() ) m_shipSelect = 0;
  137. m_player.loadShape("Resources/Ships/" + shipNames[m_shipSelect] + ".txt");
  138. m_player.setPos( 50, 100 );
  139. if ( shipCpu[m_shipSelect] == 0 ) shipCpu[m_shipSelect] = m_player.countCPU();
  140. }
  141. if ( m_input.getToucheInstant( SDLK_LEFT )
  142. || ( m_input.getBoutonSourisInstant( 3 )
  143. && m_input.getX() < m_screen->w / 2
  144. && m_input.getY() < m_screen->h / 2 ) )
  145. {
  146. m_shipSelect -= 1;
  147. if ( m_shipSelect >= shipNames.size() ) m_shipSelect = shipNames.size() - 1;
  148. m_player.loadShape("Resources/Ships/" + shipNames[m_shipSelect] + ".txt");
  149. m_player.setPos( 50, 100 );
  150. if ( shipCpu[m_shipSelect] == 0 ) shipCpu[m_shipSelect] = m_player.countCPU();
  151. }
  152. // [2.2] Gestion évènements choix du joueur
  153. if ( m_input.getToucheInstant( SDLK_d )
  154. || ( m_input.getBoutonSourisInstant( 1 )
  155. && m_input.getX() < m_screen->w / 2
  156. && m_input.getY() > m_screen->h / 2 ) )
  157. {
  158. m_pSelect += 1;
  159. if ( m_pSelect >= playerNames.size() ) m_pSelect = 0;
  160. m_score.load( playerNames[ m_pSelect ] );
  161. }
  162. if ( m_input.getToucheInstant( SDLK_a ) || m_input.getToucheInstant( SDLK_q )
  163. || ( m_input.getBoutonSourisInstant( 3 )
  164. && m_input.getX() < m_screen->w / 2
  165. && m_input.getY() > m_screen->h / 2 ) )
  166. {
  167. m_pSelect -= 1;
  168. if ( m_pSelect >= playerNames.size() ) m_pSelect = playerNames.size() - 1;
  169. m_score.load( playerNames[ m_pSelect ] );
  170. }
  171. // [3.3] Gestion évènements choix du niveau
  172. if ( m_input.getToucheInstant( SDLK_DOWN )
  173. || ( m_input.getBoutonSourisInstant( 1 )
  174. && m_input.getX() > m_screen->w / 2 ) )
  175. {
  176. m_lvlSelect += 1;
  177. if ( m_lvlSelect >= levelDetail.size() ) m_lvlSelect = 0;
  178. }
  179. if ( m_input.getToucheInstant( SDLK_UP )
  180. || ( m_input.getBoutonSourisInstant( 3 )
  181. && m_input.getX() > m_screen->w / 2 ) )
  182. {
  183. m_lvlSelect -= 1;
  184. if ( m_lvlSelect >= levelDetail.size() ) m_lvlSelect = levelDetail.size() - 1;
  185. }
  186. /// [4] Validité du vaisseau
  187. canDrive = true;
  188. canDrive = canDrive && shipCpu[ m_shipSelect ] <= m_score.getCpuLoad();
  189. canDrive = canDrive && ( m_score.hasShield() || !m_player.hasShield() );
  190. for ( unsigned int i(1); i < SHOT_NB; i++ )
  191. canDrive = canDrive && ( m_score.hasWeapon(i) || !m_player.hasWeapon(i) );
  192. /// [5] Dessin des composants
  193. // [4.1] Nettoyage fenêtre
  194. SDL_FillRect(m_screen, 0, 0x000000);
  195. // [4.2] Affichage de vaisseau
  196. m_player.draw( m_screen );
  197. stringRGBA( m_screen, 50, 50, shipNames[m_shipSelect].c_str(), 255, 255, 255, 255 );
  198. stringRGBA( m_screen, 50, 60, "CPU needed :", 255, 255, 255, 255 );
  199. for ( unsigned int i(0); i < 6; i++ )
  200. {
  201. char s[2];
  202. s[0] = (char)( shipCpu[m_shipSelect] % (Uint32)pow(10, 6 - i) / pow(10, 5 - i) );
  203. s[0] += 48;
  204. s[1] = 0;
  205. stringRGBA( m_screen, 146 + i*8, 60, s, 255, 255, 255, 255 );
  206. }
  207. stringRGBA( m_screen, 50, 70, "Can be driven :", 255, 255, 255, 255 );
  208. if ( canDrive ) stringRGBA( m_screen, 178, 70, "Yes", 0, 255, 42, 255 );
  209. else stringRGBA( m_screen, 178, 70, "No", 255, 0, 0, 255 );
  210. // [4.3] Affichage du niveau
  211. for ( unsigned int i(0); i < levelDetail[m_lvlSelect].size(); i++)
  212. {
  213. stringRGBA( m_screen, m_screen->w / 2, 50 + i * 12, levelDetail[m_lvlSelect][i].c_str(), 255, 255, 255, 255 );
  214. }
  215. // [4.4] Affichage des données du joueur
  216. stringRGBA( m_screen, 50, m_screen->h / 2, m_score.getName().c_str(), 255, 255, 255, 255 );
  217. stringRGBA( m_screen, 50, m_screen->h / 2 + 12, "Nombre de victoires :", 255, 255, 255, 255 );
  218. for ( unsigned int i(0); i < 6; i++ )
  219. {
  220. char vict[2];
  221. vict[0] = (char)( m_score.getWinNumber() % (Uint32)pow(10, 6 - i) / pow(10, 5 - i) );
  222. vict[0] += 48;
  223. vict[1] = 0;
  224. stringRGBA( m_screen, 224 + i*8, m_screen->h / 2 + 12, vict, 255, 255, 255, 255 );
  225. }
  226. stringRGBA( m_screen, 50, m_screen->h / 2 + 24, "CPU disponible :", 255, 255, 255, 255 );
  227. for ( unsigned int i(0); i < 6; i++ )
  228. {
  229. char s[2];
  230. s[0] = (char)( m_score.getCpuLoad() % (Uint32)pow(10, 6 - i) / pow(10, 5 - i) );
  231. s[0] += 48;
  232. s[1] = 0;
  233. stringRGBA( m_screen, 186 + i*8, m_screen->h / 2 + 24, s, 255, 255, 255, 255 );
  234. }
  235. stringRGBA( m_screen, 50, m_screen->h / 2 + 36, "Possede le bouclier :", 255, 255, 255, 255 );
  236. if ( m_score.hasShield() ) stringRGBA( m_screen, 224, m_screen->h / 2 + 36, "Oui", 0, 255, 42, 255 );
  237. else stringRGBA( m_screen, 224, m_screen->h / 2 + 36, "Non", 255, 0, 0, 255 );
  238. for ( unsigned int i(1); i < SHOT_NB; i ++ )
  239. {
  240. stringRGBA( m_screen, 50, m_screen->h / 2 + 36 + 12 * i, weapNames[i].c_str(), 255, 255, 255, 255 );
  241. if ( m_score.hasWeapon( i ) )
  242. stringRGBA( m_screen, 60 + 8 * weapNames[i].size(), m_screen->h / 2 + 36 + 12 * i, ": Disponible", 0, 255, 42, 255 );
  243. else
  244. stringRGBA( m_screen, 60 + 8 * weapNames[i].size(), m_screen->h / 2 + 36 + 12 * i, ": Inconnue", 255, 0, 0, 255 );
  245. }
  246. // [4.5] Double buff
  247. SDL_Flip( m_screen );
  248. /// [6] Temps
  249. SDL_Delay( 16 ); // Economie du CPU
  250. }
  251. /// [7] Fin
  252. if ( m_input.getToucheHeld( SDLK_RETURN ) )
  253. return levelDetail[m_lvlSelect][0];
  254. else
  255. return "Quit";
  256. }
  257. bool Game::rush( string planet )
  258. {
  259. /// [1] Préparation
  260. // [1.1] Préparation du joueur
  261. //m_player.loadShape("Resources/Ships/LightBeam.txt");
  262. m_player.setPos( m_screen->w, m_screen->h / 2 );
  263. // [1.2] Nettoyage
  264. m_hiter.clean();
  265. m_waver.reset();
  266. // [1.3] Paramètrage des vagues
  267. m_waver.setPlanet( planet );
  268. // [1.4] Variables du temps
  269. Uint32 lastFresh( SDL_GetTicks() );
  270. // [1.5] Capturer le pointeur
  271. m_input.placerPtr( m_screen );
  272. m_input.afficherPointeur( false );
  273. m_input.capturerPointeur( true );
  274. /// [2] Boucle principale
  275. while ( !m_input.terminer() && !m_input.getToucheHeld( SDLK_ESCAPE ) )
  276. {
  277. // [2.1] Mise à jour des évènements
  278. m_input.updateEvenements();
  279. // [2.2] Gestion évènements
  280. m_player.scroll( m_input.getYRel() );
  281. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getBoutonSourisHeld( 1 ) ) // Clic gauche
  282. m_player.fire( GUN_ID );
  283. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getBoutonSourisHeld( 3 ) ) // Clic droit
  284. m_player.fire( CUTTER_ID );
  285. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_a ) ) // Touche a
  286. m_player.fire( PHOTO_ID );
  287. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_z ) ) // Touche z
  288. m_player.fire( MISSILE_ID );
  289. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_e ) ) // Touche e
  290. m_player.fire( DISPER_ID );
  291. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_r ) ) // Touche r
  292. m_player.fire( BREXIT_ID );
  293. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_t ) ) // Touche t
  294. m_player.fire( HECTO_ID );
  295. if ( m_input.getToucheHeld( SDLK_SPACE ) || m_input.getToucheHeld( SDLK_y ) ) // Touche y
  296. m_player.fire( SNIPER_ID );
  297. // [2.3] Mise à jour des éléments
  298. m_player.enableThruster( m_waver.hasWon() );
  299. m_player.update();
  300. m_waver.update();
  301. m_hiter.setNearPt( m_waver.nearestFromPoint( m_player.getHeartPos() ) );
  302. m_hiter.setNearAxe( m_waver.nearestFromAxe( m_player.getHeartPos() ) );
  303. m_hiter.setNearAlly( m_player.getHeartPos() );
  304. m_hiter.update();
  305. // [2.4] Dessin des composants
  306. SDL_FillRect(m_screen, 0, 0x000000);
  307. m_waver.draw( m_screen );
  308. m_player.draw( m_screen );
  309. m_hiter.draw( m_screen );
  310. if ( !m_player.getIsAlive() || m_waver.hasLost() )
  311. printGameOver();
  312. SDL_Flip( m_screen );
  313. // [2.5] Temps
  314. while( SDL_GetTicks() - lastFresh < 16 )
  315. {
  316. if ( SDL_GetTicks() - lastFresh < 12 )
  317. SDL_Delay( 2 ); // Economie du CPU
  318. }
  319. lastFresh = SDL_GetTicks();
  320. }
  321. /// [3] Fin
  322. // [3. ] Si victoire
  323. bool victory( m_waver.hasWon() );
  324. // [3._] Nettoyage
  325. m_hiter.clean();
  326. m_waver.clean();
  327. // [3._] Attente de la touche echape
  328. while ( m_input.getToucheHeld( SDLK_ESCAPE ) ) m_input.updateEvenements();
  329. // [3._] Retour
  330. return m_player.getIsAlive() && victory;
  331. }
  332. /// Private
  333. void Game::printGameOver()
  334. {
  335. stringRGBA( m_screen, 12, 30, "GAME OVER", 255, 255, 255, 255 );
  336. }