PageRenderTime 75ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/creathemup_sdl/src/CLevelRenderer.cpp

http://creathemup.googlecode.com/
C++ | 1166 lines | 693 code | 241 blank | 232 comment | 115 complexity | 5eb0465fda530d9c82e58d52469c707c MD5 | raw file
  1. #include "../include/CLevelRenderer.h"
  2. #include "../include/CSDLManager.h"
  3. #include "../include/CRenderBackground.h"
  4. #include "../include/CRenderPlayer.h"
  5. #include "../include/CRenderEnemy.h"
  6. #include "../include/CPlayerBehaviour.h"
  7. #include "../include/CDefaultEnemyBehaviour.h"
  8. #include "../include/CDiagonalEnemyBehaviour.h"
  9. #include "../include/CHorizontalEnemyBehaviour.h"
  10. #include "../include/CBoatEnemyBehaviour.h"
  11. #include "../include/CDefaultPowerUpBehaviour.h"
  12. #include "../include/CShotPowerUpBehaviour.h"
  13. #include <SDL/SDL.h>
  14. #include <SDL/SDL_image.h>
  15. #include <SDL/SDL_ttf.h>
  16. #include <assert.h>
  17. #include <math.h>
  18. //**************************
  19. //Description : Constructor
  20. //Parameters : None
  21. //Note : Private because a single instance is needed
  22. //**************************
  23. CLevelRenderer::CLevelRenderer()
  24. : m_sNbPlayers(0),
  25. m_sCurrentPlayer(0),
  26. m_sNbEnemies(0)
  27. {
  28. }
  29. //**************************
  30. //Description : Constructor
  31. //Parameters : None
  32. //Note : Private because a single instance is needed
  33. //**************************
  34. CLevelRenderer::~CLevelRenderer()
  35. {
  36. }
  37. //**************************
  38. //Description : Init the instance
  39. //Parameters : None
  40. //Return Value : None
  41. //Note : None
  42. //**************************
  43. void CLevelRenderer::Init()
  44. {
  45. m_SDLManager = CSDLManager::GetInstancePtr();
  46. m_sCurrentLevel = NULL;
  47. m_Background = NULL;
  48. m_vPlayers = NULL;
  49. m_vEnemies = NULL;
  50. m_Highscores = m_SDLManager->GetHighscoreGameSurfaces();
  51. m_Lives = m_SDLManager->GetLivesSurfaces();
  52. m_Numbers = m_SDLManager->GetNumbersSurfaces();
  53. LoadHighScore();
  54. }
  55. //**************************
  56. //Description : DeInit the instance
  57. //Parameters : None
  58. //Return Value : None
  59. //Note : None
  60. //**************************
  61. void CLevelRenderer::DeInit()
  62. {
  63. if ( m_sCurrentLevel != NULL )
  64. delete[] m_sCurrentLevel;
  65. if ( m_Background != NULL )
  66. delete m_Background;
  67. if ( m_vPlayers != NULL )
  68. delete[] m_vPlayers;
  69. if ( m_vEnemies != NULL )
  70. delete[] m_vEnemies;
  71. }
  72. //**************************
  73. //Description : Load the level _szLevel
  74. //Parameters : Pointer toward the current level configuration file
  75. //Return Value : true if success, otherwise false
  76. //Note : Have to be called after the SDL initialisation because we need a screen
  77. //**************************
  78. bool CLevelRenderer::LoadLevel(const char * _szLevelDir)
  79. {
  80. char szBuffer[255]; //buffer of a line
  81. char szBackgroundName[255]; //name of the background bind to ther level
  82. int iTypeEnemy, // type of the enemy
  83. iX, // value of the abscissa
  84. iY, // value of the ordinary
  85. iSpeedX, // value of the m_sCurrentLevelspeed on the abscissa
  86. iSpeedY, // value of the speed on the ordinary
  87. iPowerUp, // 0 if no powerup, 1 if a powerup
  88. iTypePowerUp, // type of the power up
  89. iTypeShotPowerUp, // if it's a shot power up, we have to know the type of shot that is changed
  90. iBackgroundSpeed; //speed of the scrolling
  91. long lEnemyAppearance; //time before the appearance of an enemy
  92. SDL_Surface * Screen = m_SDLManager->GetScreen();
  93. FILE *fFile; //pointer on the file
  94. fFile = fopen(_szLevelDir, "r");
  95. //test on the opening
  96. assert ( fFile != NULL );
  97. //get the first line
  98. fgets(szBuffer, 255, fFile);
  99. //scan the background
  100. sscanf(szBuffer, "BACKGROUND: %s %d", szBackgroundName, &iBackgroundSpeed);
  101. //We create the animation
  102. CSpriteAnimation BackAnim(szBackgroundName);
  103. //we create the CRenderBackground
  104. m_Background = new CRenderBackground(Screen, &BackAnim, iBackgroundSpeed);
  105. //get the second line
  106. fgets(szBuffer, 255, fFile);
  107. //scan the number of enemies
  108. sscanf(szBuffer, "ENNEMIES: %hd", &m_sNbEnemies);
  109. m_vEnemies = new CRenderEnemy[m_sNbEnemies]();
  110. short sCount = 0;
  111. while ( !feof(fFile) && sCount < m_sNbEnemies )
  112. {
  113. //get a line
  114. fgets(szBuffer, 255, fFile);
  115. //check wether it's useful or not (comment line, blank, or nothing)
  116. if (szBuffer[0] != '#' && szBuffer[0] != '\r' && szBuffer[0] != '\0'
  117. && szBuffer[0] != '\n' && strlen(szBuffer) != 0)
  118. {
  119. //get info of the ennemy
  120. sscanf(szBuffer, "%d %d %d %d %d %d %d %d %ld", &iTypeEnemy,
  121. &iX, &iY,
  122. &iSpeedX, &iSpeedY,
  123. &iPowerUp, &iTypePowerUp, &iTypeShotPowerUp,
  124. &lEnemyAppearance);
  125. CDefaultEnemyBehaviour * Enemy;
  126. //create the enemy
  127. switch (iTypeEnemy)
  128. {
  129. case DEFAULTENEMY:
  130. {
  131. CDefaultEnemyBehaviour * DefaultEnemy = new CDefaultEnemyBehaviour(iX, iY, iSpeedX, iBackgroundSpeed+iSpeedY);
  132. Enemy = DefaultEnemy;
  133. break;
  134. }
  135. case DIAGONALENEMY:
  136. {
  137. CDiagonalEnemyBehaviour * DiagonalEnemy = new CDiagonalEnemyBehaviour(iX, iY, iSpeedX, iBackgroundSpeed+iSpeedY);
  138. Enemy = DiagonalEnemy;
  139. break;
  140. }
  141. case HORIZONTALENEMY:
  142. {
  143. CHorizontalEnemyBehaviour * HorizontalEnemy = new CHorizontalEnemyBehaviour(iX, iY, iSpeedX, iBackgroundSpeed+iSpeedY);
  144. Enemy = HorizontalEnemy;
  145. break;
  146. }
  147. case BOATENEMY:
  148. {
  149. CBoatEnemyBehaviour * BoatEnemy = new CBoatEnemyBehaviour(iX, iY, iSpeedX, iBackgroundSpeed+iSpeedY);
  150. Enemy = BoatEnemy;
  151. break;
  152. }
  153. }
  154. m_vEnemies[sCount].SetRender(Screen,
  155. Enemy,
  156. lEnemyAppearance,
  157. m_SDLManager->GetEnemyAnimations(iTypeEnemy),
  158. m_SDLManager->GetEnemyShotsAnimation(iTypeEnemy));
  159. //if there is a powerup
  160. if ( iPowerUp == 1 )
  161. {
  162. //create the powerup
  163. switch (iTypePowerUp)
  164. {
  165. case DEFAULTPOWERUP:
  166. {
  167. CDefaultPowerUpBehaviour * DefaultPowerUp = new CDefaultPowerUpBehaviour();
  168. m_vEnemies[sCount].SetPowerUpBehaviour(DefaultPowerUp, m_SDLManager->GetPowerUpAnimations(iTypePowerUp) );
  169. break;
  170. }
  171. case SHOTPOWERUP:
  172. {
  173. CShotPowerUpBehaviour * ShotPowerUp = new CShotPowerUpBehaviour();
  174. ShotPowerUp->SetTypeShotBonus(iTypeShotPowerUp);
  175. m_vEnemies[sCount].SetPowerUpBehaviour(ShotPowerUp, m_SDLManager->GetPowerUpAnimations(iTypePowerUp) );
  176. break;
  177. }
  178. }
  179. }
  180. sCount++;
  181. }
  182. }
  183. fclose(fFile);
  184. return true;
  185. }
  186. //**************************
  187. //Description : Load the last game saved
  188. //Parameters : The path to the game
  189. //Return Value : true if success, otherwise false
  190. //Note : Have to be called after the SDL initialisation because we need a screen
  191. //**************************
  192. bool CLevelRenderer::LoadGame(const char * _szLoad)
  193. {
  194. FILE *fLoadGame;
  195. short sCurrentLevel; //current level of a player
  196. int iLives, //number of lives of a player
  197. iEnemiesKilled; //number of ennemies that a player killed
  198. long lCurrentTime, //time spent from the begining of the current level
  199. lPoints; //points of the player
  200. int iNbShots[2]; //number of shot for each type of shot of the player
  201. SDL_Surface * Screen = m_SDLManager->GetScreen();
  202. fLoadGame = fopen(_szLoad, "rb");
  203. assert( fLoadGame != NULL );
  204. //we load the number of players
  205. fread(&m_sNbPlayers, sizeof(short), 1, fLoadGame);
  206. //we load the time from the begining of the level
  207. fread(&lCurrentTime, sizeof(long), 1, fLoadGame);
  208. //we load the number of the player who is currently playing
  209. fread(&m_sCurrentPlayer, sizeof(short), 1, fLoadGame);
  210. //we create necessary variables
  211. m_vPlayers = new CRenderPlayer[m_sNbPlayers]();
  212. m_sCurrentLevel = new short[m_sNbPlayers]();
  213. //we load the two players
  214. for (int i = 0; i < m_sNbPlayers; i++)
  215. {
  216. CPlayerBehaviour * Player = new CPlayerBehaviour();
  217. //we store its lives, its points and the number of enemies that he killed
  218. fread(&sCurrentLevel, sizeof(short), 1, fLoadGame);
  219. fread(&iLives, sizeof(int), 1, fLoadGame);
  220. fread(&lPoints, sizeof(long), 1, fLoadGame);
  221. fread(&iEnemiesKilled, sizeof(int), 1, fLoadGame);
  222. //we go until we have the TWO shots (primary and secondary)
  223. for (int j = 0; j < 2; j++)
  224. {
  225. fread(&iNbShots[j], sizeof(int), 1, fLoadGame);
  226. }
  227. //we set the current level
  228. m_sCurrentLevel[i] = sCurrentLevel;
  229. //we set the lives
  230. Player->AddLife(iLives - Player->HasLives());
  231. //we set its points
  232. Player->AddPoints(lPoints);
  233. //we set its number of enemies killed
  234. Player->AddEnemiesKilled(iEnemiesKilled);
  235. //we set the number of shots
  236. Player->SetNbShots(iNbShots);
  237. m_vPlayers[i].SetRender(Screen,
  238. Player,
  239. m_SDLManager->GetPlayerAnimations(i),
  240. m_SDLManager->GetPlayerShotsAnimation(i));
  241. Player = NULL;
  242. }
  243. //we load the current level
  244. char szCurrentLevel[2];
  245. sprintf(szCurrentLevel, "%hd", m_sCurrentLevel[m_sCurrentPlayer]);
  246. std::string szStringCurrentLevel;
  247. szStringCurrentLevel += szLevelsDir;
  248. szStringCurrentLevel += "Level";
  249. szStringCurrentLevel += szCurrentLevel;
  250. LoadLevel( szStringCurrentLevel.c_str() );
  251. //we record the beginning of the level
  252. m_lBeginLevel = SDL_GetTicks() - lCurrentTime;
  253. m_lPauseTime = 0;
  254. fclose(fLoadGame);
  255. //we make the enemies that have an appearance lowest than the time of the game disappear (we make their y be after the height of the window)
  256. int i = 0;
  257. while ( i < m_sNbEnemies && m_vEnemies[i].GetAppearance() < lCurrentTime )
  258. {
  259. m_vEnemies[i].GetEnemyBehaviour()->SetY(GAME_WINDOW_HEIGHT*2);
  260. i++;
  261. }
  262. return true;
  263. }
  264. //**************************
  265. //Description : Save the current game
  266. //Parameters : The path to the save
  267. //Return Value : true if success, otherwise false
  268. //Note : Have to be called after the SDL initialisation because we need a screen
  269. //**************************
  270. bool CLevelRenderer::SaveGame(const char * _szSave)
  271. {
  272. FILE *fSaveGame;
  273. short sCurrentLevel; //current level of a player
  274. int iLives, //number of lives of a player
  275. iEnemiesKilled; //number of ennemies that a player killed
  276. long lCurrentTime, //time spent from the begining of the current level
  277. lPoints; //points of the player
  278. int * iNbShots; //number of shot for each type of shot of the player
  279. fSaveGame = fopen(_szSave, "wb");
  280. assert( fSaveGame != NULL );
  281. //we get the time from the beginning of the level
  282. lCurrentTime = SDL_GetTicks() - m_lBeginLevel - m_lPauseTime;
  283. //we save the number of players
  284. fwrite(&m_sNbPlayers, sizeof(short), 1, fSaveGame);
  285. //we save this value
  286. fwrite(&lCurrentTime, sizeof(long), 1, fSaveGame);
  287. //we save the player who is currently playing
  288. fwrite(&m_sCurrentPlayer, sizeof(short), 1, fSaveGame);
  289. //we save the two players
  290. for (int i = 0; i < m_sNbPlayers; i++)
  291. {
  292. CPlayerBehaviour * Player = m_vPlayers[i].GetPlayerBehaviour();
  293. //we save info from the player
  294. sCurrentLevel = m_sCurrentLevel[i];
  295. iLives = Player->HasLives();
  296. lPoints = Player->GetPoints();
  297. iEnemiesKilled = Player->GetEnemiesKilled();
  298. iNbShots = Player->GetNbShots();
  299. //we store its current level, itslives, its points and the number of enemies that he killed
  300. fwrite(&sCurrentLevel, sizeof(short), 1, fSaveGame);
  301. fwrite(&iLives, sizeof(int), 1, fSaveGame);
  302. fwrite(&lPoints, sizeof(long), 1, fSaveGame);
  303. fwrite(&iEnemiesKilled, sizeof(int), 1, fSaveGame);
  304. //we go until we have the TWO shots (primary and secondary)
  305. for (int j = 0; j < 2; j++)
  306. {
  307. fwrite(&iNbShots[j], sizeof(int), 1, fSaveGame);
  308. }
  309. }
  310. fclose(fSaveGame);
  311. return true;
  312. }
  313. //**************************
  314. //Description : Restart the current level
  315. //Parameters : None
  316. //Return Value : None
  317. //Note : RestartLevel is called when a player die, because we can't restart a level when we want
  318. //**************************
  319. void CLevelRenderer::RestartLevel()
  320. {
  321. //we delete the background
  322. if ( m_Background != NULL )
  323. delete m_Background;
  324. //We delete the ennemies
  325. if ( m_vEnemies != NULL )
  326. delete[] m_vEnemies;
  327. //we reinitialise the current player and set the second (if any)
  328. m_vPlayers[m_sCurrentPlayer].InitRender();
  329. m_sCurrentPlayer++;
  330. if (m_sCurrentPlayer >= m_sNbPlayers)
  331. m_sCurrentPlayer = 0;
  332. //we init the current player in order to make it blink
  333. m_vPlayers[m_sCurrentPlayer].InitRender();
  334. //we load the level for the player
  335. char szCurrentLevel[2];
  336. sprintf(szCurrentLevel, "%hd", m_sCurrentLevel[m_sCurrentPlayer]);
  337. std::string szStringCurrentLevel;
  338. szStringCurrentLevel += szLevelsDir;
  339. szStringCurrentLevel += "Level";
  340. szStringCurrentLevel += szCurrentLevel;
  341. LoadLevel( szStringCurrentLevel.c_str() );
  342. //we save the begining of the level
  343. m_lBeginLevel = SDL_GetTicks();
  344. m_lPauseTime = 0;
  345. }
  346. //**************************
  347. //Description : Load the highscore of the game
  348. //Parameters : None
  349. //Return Value : true if success, otherwise false
  350. //Note : None
  351. //**************************
  352. bool CLevelRenderer::LoadHighScore()
  353. {
  354. FILE * fFile;
  355. fFile = fopen( szHighScoreDir.c_str() , "rb" );
  356. //test on the opening
  357. assert ( fFile != NULL );
  358. do
  359. {
  360. fread(&m_lHighScore, sizeof(long), 1, fFile);
  361. }
  362. while ( !feof(fFile) );
  363. fclose(fFile);
  364. return true;
  365. }
  366. //**************************
  367. //Description : Save the highscore of the game
  368. //Parameters : None
  369. //Return Value : true if success, otherwise false
  370. //Note : None
  371. //**************************
  372. bool CLevelRenderer::SaveHighScore()
  373. {
  374. FILE * fFile;
  375. fFile = fopen( szHighScoreDir.c_str(), "wb" );
  376. //test on the opening
  377. assert ( fFile != NULL );
  378. fwrite(&m_lHighScore, sizeof(long), 1, fFile);
  379. fclose(fFile);
  380. return true;
  381. }
  382. //**************************
  383. //Description : Return the highscore of the game
  384. //Parameters : None
  385. //Return Value : The high score of the game
  386. //Note : have to be called after LoadHighScore
  387. //**************************
  388. long CLevelRenderer::GetHighScore()
  389. {
  390. return m_lHighScore;
  391. }
  392. //**************************
  393. //Description : Start the game from the beginning with _sNbPLayers
  394. //Parameters : The number of players
  395. //Return Value : None
  396. //Note : None
  397. //**************************
  398. void CLevelRenderer::StartGame(short _sNbPlayers)
  399. {
  400. //we test if can start the game
  401. if ( _sNbPlayers > 0 && _sNbPlayers <= MAX_PLAYERS )
  402. {
  403. //we initialise
  404. m_sCurrentLevel = new short[_sNbPlayers]();
  405. m_sNbPlayers = _sNbPlayers;
  406. m_sCurrentPlayer = 0;
  407. //we initialise each player
  408. m_vPlayers = new CRenderPlayer[m_sNbPlayers]();
  409. CPlayerBehaviour * Players = NULL;
  410. SDL_Surface * Screen = m_SDLManager->GetScreen();
  411. for (int i = 0; i < m_sNbPlayers; i++)
  412. {
  413. Players = new CPlayerBehaviour();
  414. m_vPlayers[i].SetRender(Screen,
  415. Players,
  416. m_SDLManager->GetPlayerAnimations(i),
  417. m_SDLManager->GetPlayerShotsAnimation(i));
  418. m_sCurrentLevel[i] = 0;
  419. Players = NULL;
  420. }
  421. //we load the current level
  422. char szCurrentLevel[2];
  423. sprintf(szCurrentLevel, "%hd", m_sCurrentLevel[m_sCurrentPlayer]);
  424. std::string szStringCurrentLevel;
  425. szStringCurrentLevel += szLevelsDir;
  426. szStringCurrentLevel += "Level";
  427. szStringCurrentLevel += szCurrentLevel;
  428. LoadLevel( szStringCurrentLevel.c_str() );
  429. //we record the beginning of the level
  430. m_lBeginLevel = SDL_GetTicks();
  431. m_lPauseTime = 0;
  432. //we launch the game
  433. Game();
  434. }
  435. }
  436. //**************************
  437. //Description : Start the game from a save file
  438. //Parameters : The save configuration file
  439. //Return Value : None
  440. //Note : None
  441. //**************************
  442. void CLevelRenderer::StartGame(const char * _szLoadLevel)
  443. {
  444. if ( LoadGame(_szLoadLevel) )
  445. {
  446. //we test if can start the game by loading the save
  447. if ( m_sNbPlayers > 0 && m_sNbPlayers <= MAX_PLAYERS )
  448. {
  449. //we launch the game
  450. Game();
  451. }
  452. }
  453. }
  454. //**************************
  455. //Description : Test if the game is over or not
  456. //Parameters : None
  457. //Return Value : True if the game is over, false if not
  458. //Note : The game is over whan all players don't have life anymore or if one player has finished the game
  459. //**************************
  460. bool CLevelRenderer::GameOver()
  461. {
  462. bool bGameOver = true;
  463. int i = 0;
  464. if ( m_vPlayers != NULL )
  465. {
  466. //we search partially, because if only one players is alive, the game isn't over
  467. while (i < m_sNbPlayers && bGameOver)
  468. {
  469. bGameOver = (m_vPlayers[i].GetPlayerBehaviour()->IsDead() || (m_sCurrentLevel[i] >= NUMBER_LEVELS) );
  470. i++;
  471. }
  472. //we can declare the end of the game after the animation of death of the current player has ended
  473. if ( bGameOver )
  474. bGameOver = m_vPlayers[m_sCurrentPlayer].IsPlayerDead();
  475. }
  476. return bGameOver;
  477. }
  478. //**************************
  479. //Description : Test if the current level is over or not
  480. //Parameters : None
  481. //Return Value : True if the lvel is over, false if not
  482. //Note : The level is over when all ennemies went out of the screen (y > GAME_WINDOW_HEIGHT) or are dead
  483. //**************************
  484. bool CLevelRenderer::LevelOver()
  485. {
  486. //if the current player is dead, we have to restart the level
  487. if ( m_vPlayers != NULL && (m_vPlayers[m_sCurrentPlayer].IsExploding() || m_vPlayers[m_sCurrentPlayer].IsPlayerExplosed()) )
  488. return false;
  489. bool bLevelOver = true;
  490. //we test if there are enemies
  491. if ( m_vEnemies != NULL )
  492. {
  493. //we test the appearance of the last enemy and we add some time in order to let him move
  494. long lCurrentTime = SDL_GetTicks();
  495. int iNumEnemy = 0;
  496. while (iNumEnemy < m_sNbEnemies && bLevelOver)
  497. {
  498. //if the enemy has appeared
  499. if ( (m_vEnemies[iNumEnemy].GetAppearance() + 2000) < (lCurrentTime - m_lBeginLevel - m_lPauseTime) )
  500. {
  501. //we test if the enemy is dead OR if he is out of the screen (he has passed the height of the screen
  502. bLevelOver = ( m_vEnemies[iNumEnemy].IsEnemyDead()
  503. || (m_vEnemies[iNumEnemy].GetEnemyBehaviour()->GetY() - m_vEnemies[iNumEnemy].GetEnemyBehaviour()->GetHeight()/2) > GAME_WINDOW_HEIGHT );
  504. }
  505. else
  506. bLevelOver = false;
  507. iNumEnemy++;
  508. }
  509. }
  510. return bLevelOver;
  511. }
  512. //**************************
  513. //Description : Manage collision between all rendering entities
  514. //Parameters : None
  515. //Return Value : True if the players collide with an enemy or a shot, otherwise false
  516. //Note : None
  517. //**************************
  518. bool CLevelRenderer::Collision()
  519. {
  520. bool bCollision = false;
  521. //we get the current time
  522. long lCurrentTime = SDL_GetTicks();
  523. for (int i = 0; i < m_sNbEnemies; i++)
  524. {
  525. //we test the time of appearance
  526. if ( m_vEnemies[i].GetAppearance() < (lCurrentTime - m_lBeginLevel - m_lPauseTime) )
  527. {
  528. if ( m_vPlayers[m_sCurrentPlayer].CollideWithEnemy(&m_vEnemies[i]) )
  529. bCollision = true;
  530. m_vEnemies[i].CollideWithPlayer(&m_vPlayers[m_sCurrentPlayer]);
  531. }
  532. //else ennemies after this one don't appear because their appearance time is higher
  533. else
  534. i = m_sNbEnemies;
  535. }
  536. return bCollision;
  537. }
  538. //**************************
  539. //Description : Draw the statistics of the given player at the end of a level, of the game or when it's game over
  540. //Parameters : The number of the player we want to draw the statistics
  541. //Return Value : None
  542. //Note : None
  543. //**************************
  544. void CLevelRenderer::DrawPlayerStatistics(int _iNumPlayer)
  545. {
  546. std::string szText;
  547. char szPlayer[100];
  548. long lHigh = 0; //highscore of the player
  549. int iNum; //number to draw
  550. int iPow = 1; //result of pow
  551. SDL_Color White = { 255, 255, 255 };
  552. SDL_Color Green = { 0, 255, 0 };
  553. SDL_Color Red = { 255, 0, 0 };
  554. SDL_Rect Dest;
  555. SDL_Surface * Screen = m_SDLManager->GetScreen(), *Text;
  556. //we get the font
  557. TTF_Font * BigGameFont = m_SDLManager->GetBigGameFont();
  558. TTF_Font * LittleGameFont = m_SDLManager->GetLittleGameFont();
  559. szText.clear();
  560. sprintf(szPlayer, "%d", _iNumPlayer);
  561. szText = "Player ";
  562. szText += szPlayer;
  563. Text = TTF_RenderText_Blended(LittleGameFont, szText.c_str(), Green);
  564. Dest.x = 50;
  565. Dest.y = 150 + (_iNumPlayer-1) * 200;
  566. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  567. //if the player is dead, we show it
  568. if ( m_vPlayers[_iNumPlayer-1].GetPlayerBehaviour()->IsDead() )
  569. {
  570. Dest.x = 60 + Text->w;
  571. Dest.y = 150 + (_iNumPlayer-1) * 200;
  572. szText.clear();
  573. szText = "DEAD";
  574. Text = TTF_RenderText_Blended(LittleGameFont, szText.c_str(), Red);
  575. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  576. }
  577. szText.clear();
  578. szText = "Highscore :";
  579. Text = TTF_RenderText_Blended(LittleGameFont, szText.c_str(), White);
  580. Dest.x = 70;
  581. Dest.y = 190 + (_iNumPlayer-1) * 200;
  582. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  583. lHigh = m_vPlayers[_iNumPlayer-1].GetPlayerBehaviour()->GetPoints();
  584. //we draw that we have a new highscore
  585. if ( lHigh > m_lHighScore )
  586. {
  587. szText.clear();
  588. szText = "NEW HIGHSCORE !";
  589. Text = TTF_RenderText_Blended(LittleGameFont, szText.c_str(), Red);
  590. Dest.y = 190 + (_iNumPlayer-1) * 200;
  591. Dest.x = 9 * 40;
  592. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  593. }
  594. //we draw the value of the highscore
  595. for (int j = 0; j < 9; j++)
  596. {
  597. for (int a = 0; a < (8-j); a++)
  598. iPow *= 10;
  599. iNum = lHigh / iPow;
  600. lHigh -= iNum * iPow;
  601. sprintf(szPlayer, "%d", iNum);
  602. Text = TTF_RenderText_Blended(LittleGameFont, szPlayer, White);
  603. Dest.y = 230 + (_iNumPlayer-1) * 200;
  604. Dest.x = 100 + j * 40;
  605. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  606. iPow = 1;
  607. }
  608. szText.clear();
  609. szText = "Enemies killed :";
  610. Text = TTF_RenderText_Blended(LittleGameFont, szText.c_str(), White);
  611. Dest.x = 70;
  612. Dest.y = 270 + (_iNumPlayer-1) * 200;
  613. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  614. sprintf(szPlayer, "%d", m_vPlayers[_iNumPlayer-1].GetPlayerBehaviour()->GetEnemiesKilled());
  615. Text = TTF_RenderText_Blended(LittleGameFont, szPlayer, White);
  616. Dest.x = 100;
  617. Dest.y = 310 + (_iNumPlayer-1) * 200;
  618. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  619. }
  620. //**************************
  621. //Description : Draw the statistics on the screen at the end of the level or at the end of the game
  622. //Parameters : None
  623. //Return Value : None
  624. //Note : None
  625. //**************************
  626. void CLevelRenderer::DrawEndStatistics()
  627. {
  628. SDL_Rect Dest;
  629. SDL_Surface * Screen = m_SDLManager->GetScreen();
  630. // We first fill the entire screen with black
  631. SDL_FillRect(Screen, NULL, SDL_MapRGB(Screen->format, 0, 0, 0));
  632. //we get the background of the menu and apply it here
  633. SDL_Surface * Background = m_SDLManager->GetBackgroundMenu();
  634. Dest.x = 0;
  635. Dest.y = 0;
  636. SDL_BlitSurface(Background, NULL, Screen, &Dest);
  637. //we get the font
  638. TTF_Font * BigGameFont = m_SDLManager->GetBigGameFont();
  639. TTF_Font * LittleGameFont = m_SDLManager->GetLittleGameFont();
  640. SDL_Color White = { 255, 255, 255 };
  641. SDL_Color Green = { 0, 255, 0 };
  642. SDL_Color Red = { 255, 0, 0 };
  643. SDL_Surface * Text;
  644. //we are either at the end of a level, or at the end of the game when this function is called
  645. if ( LevelOver() )
  646. {
  647. if ( m_sCurrentLevel[m_sCurrentPlayer] >= (NUMBER_LEVELS-1) )
  648. Text = TTF_RenderText_Blended(BigGameFont, "Game Finished !", Green);
  649. else
  650. Text = TTF_RenderText_Blended(BigGameFont, "Level Clear !", Green);
  651. Dest.y = 20;
  652. Dest.x = (WINDOW_WIDTH / 2) - (Text->w / 2);
  653. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  654. //we draw the statistics only for the current player
  655. DrawPlayerStatistics(m_sCurrentPlayer+1);
  656. }
  657. else
  658. {
  659. Text = TTF_RenderText_Blended(BigGameFont, "Game Statistics :", Green);
  660. Dest.y = 20;
  661. Dest.x = (WINDOW_WIDTH / 2) - (Text->w / 2);
  662. SDL_BlitSurface(Text, NULL, Screen, &Dest);
  663. //we draw the statistics of the two players
  664. for (int i = 1; i <= m_sNbPlayers; i++)
  665. DrawPlayerStatistics(i);
  666. }
  667. //We flip the screen
  668. m_SDLManager->Flip();
  669. SDL_Delay(4000);
  670. }
  671. //**************************
  672. //Description : Draw the statistics on the screen
  673. //Parameters : None
  674. //Return Value : None
  675. //Note : None
  676. //**************************
  677. void CLevelRenderer::DrawStatistics()
  678. {
  679. SDL_Surface * Screen = m_SDLManager->GetScreen();
  680. SDL_Rect Dest;
  681. long lHigh = 0; //highscore of the player
  682. int iNum; //number to draw
  683. int iPow = 1; //result of pow
  684. //we draw the highscores to the left off the screen
  685. for (int i = 0; i < m_sNbPlayers; i++)
  686. {
  687. Dest.y = i * (2 * m_Highscores[i+1]->h);
  688. Dest.x = 0;
  689. SDL_BlitSurface(m_Highscores[i+1], NULL, Screen, &Dest);
  690. lHigh = m_vPlayers[i].GetPlayerBehaviour()->GetPoints();
  691. //we draw the value of the highscore
  692. for (int j = 0; j < 9; j++)
  693. {
  694. Dest.y = i * (2 * m_Highscores[i+1]->h) + m_Highscores[i+1]->h;
  695. Dest.x = j * m_Numbers[j]->w;
  696. for (int a = 0; a < (8-j); a++)
  697. iPow *= 10;
  698. iNum = lHigh / iPow;
  699. lHigh -= iNum * iPow;
  700. SDL_BlitSurface(m_Numbers[iNum], NULL, Screen, &Dest);
  701. iPow = 1;
  702. }
  703. }
  704. //the highscore of the game is drawn to the bottom left
  705. Dest.y = WINDOW_HEIGHT - (2 * m_Highscores[0]->h);
  706. Dest.x = 0;
  707. SDL_BlitSurface(m_Highscores[0], NULL, Screen, &Dest);
  708. lHigh = m_lHighScore;
  709. //we draw the value of the highscore
  710. for (int j = 0; j < 9; j++)
  711. {
  712. Dest.y = WINDOW_HEIGHT - m_Highscores[0]->h;
  713. Dest.x = j * m_Numbers[j]->w;
  714. for (int a = 0; a < (8-j); a++)
  715. iPow *= 10;
  716. iNum = lHigh / iPow;
  717. lHigh -= iNum * iPow;
  718. SDL_BlitSurface(m_Numbers[iNum], NULL, Screen, &Dest);
  719. iPow = 1;
  720. }
  721. int iLives; //number of lives of a player
  722. //the lives are drawn to the right of the screen
  723. for (int i = 0; i < m_sNbPlayers; i++)
  724. {
  725. Dest.y = i * (2 * m_Lives[i]->h);
  726. Dest.x = GAME_WINDOW_X + GAME_WINDOW_WIDTH;
  727. SDL_BlitSurface(m_Lives[i], NULL, Screen, &Dest);
  728. //we draw the number of lives
  729. Dest.y = i * (2 * m_Lives[i]->h) + m_Lives[i]->h;
  730. Dest.x = GAME_WINDOW_X + GAME_WINDOW_WIDTH;
  731. iLives = m_vPlayers[i].GetPlayerBehaviour()->HasLives();
  732. SDL_BlitSurface(m_Numbers[iLives], NULL, Screen, &Dest);
  733. }
  734. }
  735. //**************************
  736. //Description : Draw the screen
  737. //Parameters : None
  738. //Return Value : None
  739. //Note : None
  740. //**************************
  741. void CLevelRenderer::DrawScene()
  742. {
  743. SDL_Surface * Screen = m_SDLManager->GetScreen();
  744. // We first fill the entire screen with black
  745. SDL_FillRect(Screen, NULL, SDL_MapRGB(Screen->format, 0, 0, 0));
  746. //we draw the statistics
  747. DrawStatistics();
  748. //we render the background
  749. m_Background->Render();
  750. //we get the current time
  751. long lCurrentTime = SDL_GetTicks();
  752. //we render the enemies if they have to appear
  753. for (int i = 0; i < m_sNbEnemies; i++)
  754. {
  755. //we test the time of appearance
  756. if ( m_vEnemies[i].GetAppearance() < (lCurrentTime - m_lBeginLevel - m_lPauseTime) )
  757. m_vEnemies[i].Render();
  758. //else ennemies after this one don't appear because their appearance time is higher
  759. else
  760. i = m_sNbEnemies;
  761. }
  762. //we render the player
  763. m_vPlayers[m_sCurrentPlayer].Render();
  764. //We flip the screen
  765. m_SDLManager->Flip();
  766. }
  767. //**************************
  768. //Description : Manage events in the game
  769. //Parameters : a boolean, to know if the player quit the game, a boolean to know if we are in pause or not
  770. //Return Value : None
  771. //Note : None
  772. //**************************
  773. void CLevelRenderer::ManageEvents(bool & _bEndGame, bool & _bPauseGame)
  774. {
  775. SDL_Event event;
  776. while ( SDL_PollEvent(&event) )
  777. {
  778. if ( event.type == SDL_QUIT )
  779. _bEndGame = true;
  780. if ( event.type == SDL_KEYDOWN )
  781. {
  782. if ( event.key.keysym.sym == SDLK_ESCAPE )
  783. _bEndGame = true;
  784. if ( event.key.keysym.sym == SDLK_p )
  785. {
  786. _bPauseGame = !_bPauseGame;
  787. if (_bPauseGame)
  788. m_lBeginPause = SDL_GetTicks();
  789. else
  790. m_lPauseTime += SDL_GetTicks() - m_lBeginPause;
  791. }
  792. //save the game
  793. if ( event.key.keysym.sym == SDLK_F5 )
  794. {
  795. SaveGame( szSaveGameDir.c_str() );
  796. }
  797. }
  798. }
  799. }
  800. //**************************
  801. //Description : Manage the game
  802. //Parameters : None
  803. //Return Value : None
  804. //Note : None
  805. //**************************
  806. void CLevelRenderer::Game()
  807. {
  808. bool bPlayerExploded = false; //allows us to show the animation of the death of the player before switching player
  809. bool bEndGame = false; //if escape or sdl_quit is called we return to the menu
  810. bool bPauseGame = false; //if P is pressed, Pause is set/unset
  811. long lCurrentTime, lFormerTime = SDL_GetTicks();
  812. while ( !bEndGame && !GameOver() )
  813. {
  814. lCurrentTime = SDL_GetTicks();
  815. if ( (lCurrentTime - lFormerTime) > DELAY )
  816. {
  817. ManageEvents(bEndGame, bPauseGame);
  818. if ( !bPauseGame )
  819. {
  820. if ( !LevelOver() )
  821. {
  822. if ( !bPlayerExploded )
  823. //we test the collision
  824. bPlayerExploded = Collision();
  825. else
  826. {
  827. //if the animation of the death of the current player has finished, we switch player and restart the level
  828. if ( m_vPlayers[m_sCurrentPlayer].IsPlayerExplosed() )
  829. {
  830. //we search the first player who don't have finished the game
  831. do
  832. {
  833. m_sCurrentPlayer++;
  834. if ( m_sCurrentPlayer >= m_sNbPlayers )
  835. m_sCurrentPlayer = 0;
  836. }
  837. while ( m_sCurrentLevel[m_sCurrentPlayer] >= NUMBER_LEVELS );
  838. m_sCurrentPlayer--;
  839. if ( m_sCurrentPlayer < 0 )
  840. m_sCurrentPlayer = m_sNbPlayers - 1;
  841. RestartLevel();
  842. bPlayerExploded = false;
  843. }
  844. }
  845. //we render the screen
  846. DrawScene();
  847. }
  848. else
  849. {
  850. //show the current statistics
  851. DrawEndStatistics();
  852. //Delete current enemies and background
  853. delete m_Background;
  854. m_Background = NULL;
  855. delete[] m_vEnemies;
  856. m_vEnemies = NULL;
  857. //we reinitialise the player for the next level
  858. m_vPlayers[m_sCurrentPlayer].InitRender();
  859. //next level
  860. m_sCurrentLevel[m_sCurrentPlayer]++;
  861. //if we are ate the end of the game
  862. if ( m_sCurrentLevel[m_sCurrentPlayer] < NUMBER_LEVELS )
  863. {
  864. //load the next level
  865. char szCurrentLevel[2];
  866. sprintf(szCurrentLevel, "%hd", m_sCurrentLevel[m_sCurrentPlayer]);
  867. std::string szStringCurrentLevel;
  868. szStringCurrentLevel += szLevelsDir;
  869. szStringCurrentLevel += "Level";
  870. szStringCurrentLevel += szCurrentLevel;
  871. LoadLevel( szStringCurrentLevel.c_str() );
  872. m_lBeginLevel = SDL_GetTicks();
  873. m_lPauseTime = 0;
  874. }
  875. else
  876. {
  877. bEndGame = true;
  878. //the game is finished for this player but maybe not for the others
  879. int i = 0;
  880. while ( i < m_sNbPlayers && bEndGame )
  881. {
  882. if ( m_sCurrentLevel[i] < NUMBER_LEVELS )
  883. bEndGame = false;
  884. i++;
  885. }
  886. //if the game is not ended, we get to the player before the first who do not have finished the game and restart the level
  887. if ( !bEndGame )
  888. {
  889. while ( m_sCurrentLevel[m_sCurrentPlayer] >= NUMBER_LEVELS )
  890. {
  891. m_sCurrentPlayer++;
  892. if ( m_sCurrentPlayer >= m_sNbPlayers )
  893. m_sCurrentPlayer = 0;
  894. }
  895. m_sCurrentPlayer--;
  896. if ( m_sCurrentPlayer < 0 )
  897. m_sCurrentPlayer = m_sNbPlayers - 1;
  898. RestartLevel();
  899. }
  900. }
  901. }
  902. }
  903. lFormerTime = SDL_GetTicks();
  904. }
  905. else
  906. SDL_Delay(DELAY - (lCurrentTime - lFormerTime));
  907. }
  908. DrawEndStatistics();
  909. long lPlayer;
  910. for ( int i = 0; i < m_sNbPlayers; i++)
  911. {
  912. lPlayer = m_vPlayers[i].GetPlayerBehaviour()->GetPoints();
  913. if ( lPlayer > m_lHighScore )
  914. {
  915. m_lHighScore = lPlayer;
  916. SaveHighScore();
  917. }
  918. }
  919. //we delete the players for further instances
  920. if ( m_vPlayers != NULL )
  921. {
  922. delete[] m_vPlayers;
  923. m_vPlayers = NULL;
  924. }
  925. }