Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
game.cpp
00001 #include "mbed.h" 00002 #include "N5110.h" 00003 #include "Gamepad.h" 00004 #include "collision_lib.h" 00005 00006 #include "models.h" 00007 #include "main.h" 00008 #include "game.h" 00009 #include "gameobject.h" 00010 00011 #include "boss.h" 00012 #include "enemies.h" 00013 #include "constants.h" 00014 #include "stars.h" 00015 #include "player.h" 00016 #include "hud.h" 00017 #include "gameovermanager.h" 00018 00019 00020 const int increase_difficulty = 70; 00021 int GameGlobals::game_score = 0; 00022 int GameGlobals::score_count_for_difficulty = 0; 00023 int GameGlobals::player_lifes = 3; 00024 int GameGlobals::high_score = 0; 00025 bool GameGlobals::is_shield_on = false; 00026 int GameGlobals::score_count_for_boss_mode = 0; 00027 00028 Boss boss; 00029 Enemies enemies; 00030 Enemy enemy; 00031 Stars stars; 00032 Player player; 00033 GameOverManager gameOverManager; 00034 00035 CircleBounds circleBounds; 00036 Hud hud; 00037 00038 00039 void Game::updateAndDrawGameplay() { 00040 checkButtonToShoot(); 00041 player.updateAndDraw(); 00042 player.updateAndDrawBlasts(); 00043 stars.updateAndDrawSmallStars(); 00044 //stars.updateAndDrawMediumStars(); 00045 stars.starsSpawnDelay(); 00046 increaseGameDifficultyAndEnemySpawnDelay(); 00047 hud.displayLifes(); 00048 hud.drawScore(); 00049 collideEnemiesAndBlasts(); 00050 collideEnemiesBlastsAndPlayer(); 00051 collideEnemiesAndPlayer(); 00052 enemies.updateAndDrawEnemies(); 00053 enemies.updateAndDrawEnemyBlasts(); 00054 boss.updateAndDrawBossBlasts(); 00055 00056 if (checkForGameOver()) { game_state = GameState_gameover;} 00057 if (is_boss_active) { game_state = GameState_boss_cutscene;} 00058 } 00059 00060 void Game::updateAndDrawGameover() { 00061 gameOverManager.updateAndDraw(); 00062 if (gamepad.check_event(gamepad.Y_PRESSED) && !gameOverManager.isPlayingAnimation()) { 00063 gameOverManager.reset(); 00064 game_state = GameState_newgame; 00065 } 00066 } 00067 00068 void Game::updateAndDrawBossCutscene() { 00069 boss.updateCutscene(); 00070 enemies.updateAndDrawEnemyBlasts(); 00071 boss.draw(); 00072 player.draw(); 00073 stars.updateAndDrawSmallStars(); 00074 stars.updateAndDrawMediumStars(); 00075 if (boss.isFinishedCutscene()) { 00076 game_state = GameState_boss_gameplay; 00077 boss.resetCutscene(); 00078 } 00079 } 00080 00081 void Game::updateAndDrawBossGameplay() { 00082 checkButtonToShoot(); 00083 enemies.updateAndDrawEnemyBlasts(); 00084 player.updateAndDraw(); 00085 player.updateAndDrawBlasts(); 00086 stars.updateAndDrawSmallStars(); 00087 stars.starsSpawnDelay(); 00088 hud.displayLifes(); 00089 hud.drawScore(); 00090 boss.updateAndDrawBossBlasts(); 00091 collideBossAndPlayerBlasts(); 00092 collideBossBlastsAndPlayer(); 00093 is_boss_active = boss.updateAndDrawBoss(); 00094 if (checkForGameOver()) { game_state = GameState_gameover;} 00095 if (!is_boss_active) { game_state = GameState_gameplay;} 00096 } 00097 00098 /** 00099 * This is the main function of game.cpp, where the actual gameplay happens. 00100 * Here all other functions are activeated, and when the player dies, it 00101 * returns back to main menu "main.cpp". 00102 */ 00103 bool Game::updateAndDraw() { 00104 if (game_state == GameState_newgame) { 00105 #ifdef DEBUGel17dg 00106 printf("start game \n"); 00107 #endif 00108 startNewGame(); 00109 } 00110 if (game_state == GameState_gameplay) { updateAndDrawGameplay(); } 00111 else if (game_state == GameState_boss_cutscene) { updateAndDrawBossCutscene(); } 00112 else if (game_state == GameState_boss_gameplay) { updateAndDrawBossGameplay(); } 00113 else if (game_state == GameState_gameover) { updateAndDrawGameover(); } 00114 00115 return checkIfNeedsToReturnToMenu(); 00116 } 00117 00118 void Game::checkButtonToShoot(){ 00119 if (gamepad.check_event(gamepad.X_PRESSED) && !GameGlobals::is_shield_on){ 00120 // Checking the button second time to prevent double blast. 00121 gamepad.check_event(gamepad.X_PRESSED); 00122 player.fireNewBlast(); 00123 gamepad.tone(200,0.1); 00124 } 00125 } 00126 00127 /** 00128 * This function checks whether the requirments for the collision of the two objects, 00129 * are met. When those requirments are met the collision of two objects function will 00130 * be checking wheter the boundaries of the objects colide. If they do, the blast 00131 * becomes inactive, in game score increases and enemy dies. 00132 */ 00133 void Game::collideEnemiesAndBlasts() { 00134 for (int i = 0; i < enemies.max_enemies; ++i) { 00135 for (int j = 0; j < player.max_player_blasts; ++j) { 00136 Enemy& enemy = enemies.enemies[i]; 00137 GameObject& blast = player.blasts[j]; 00138 if (enemy.active && !enemy.dead && blast.active) { 00139 bool collision = circleBounds.circleCollideTwoObjects( 00140 enemy.pos, enemies.enemy_bounds, 00141 blast.pos, player.blast_bounds 00142 ); 00143 if (collision) { 00144 enemy.die(); 00145 #ifdef DEBUGel17dg 00146 printf("enemy got hit and dies"); 00147 #endif 00148 GameGlobals::game_score += 30; 00149 GameGlobals::score_count_for_difficulty +=30; 00150 GameGlobals::score_count_for_boss_mode += 30; 00151 blast.active = false; 00152 } 00153 } 00154 } 00155 } 00156 } 00157 00158 /** 00159 * This code does the same work as the one before but with two other objects. 00160 * It checks whether the requirments for the collision of the two objects, 00161 * are met. When those requirments are met the collision of two objects function will 00162 * be checking wheter the boundaries of the objects colide. If they do, the blast 00163 * becomes inactive, in game score increases and enemy dies. 00164 */ 00165 void Game::collideEnemiesBlastsAndPlayer() { 00166 for (int i = 0; i < enemies.max_enemies; ++i) { 00167 GameObject& blast = enemies.enemy_blasts[i]; 00168 if (blast.active) { 00169 bool collision = circleBounds.circleCollideTwoObjects( 00170 player.pos, player.player_bounds, 00171 blast.pos, enemies.enemy_blast_bounds 00172 ); 00173 if (collision) { 00174 if (!GameGlobals::is_shield_on){ 00175 gamepad.tone(423,0.4); 00176 GameGlobals::player_lifes -= 1; 00177 #ifdef DEBUGel17dg 00178 printf("lost a life from blast. left: %i \n", GameGlobals::player_lifes); 00179 #endif 00180 blast.active = false; 00181 }else{ 00182 blast.active = false; 00183 gamepad.tone(700,0.6); 00184 } 00185 } 00186 } 00187 } 00188 } 00189 00190 /** 00191 * This code does the same work as the one before but with two other object. 00192 * of enemy ship and the player's ship 00193 */ 00194 void Game::collideEnemiesAndPlayer() { 00195 for (int i = 0; i < enemies.max_enemies; ++i) { 00196 Enemy& enemy = enemies.enemies[i]; 00197 if (enemy.active && !enemy.dead) { 00198 bool collision = circleBounds.circleCollideTwoObjects( 00199 player.pos, player.player_bounds, 00200 enemy.pos, enemies.enemy_bounds 00201 ); 00202 if (collision) { 00203 GameGlobals::player_lifes -= 1; 00204 00205 enemy.die(); 00206 #ifdef DEBUGel17dg 00207 printf("enemy got hit from collsion and dies"); 00208 printf("lost a life from enemy col. left: %i \n", GameGlobals::player_lifes); 00209 #endif 00210 } 00211 } 00212 } 00213 } 00214 00215 void Game::collideBossAndPlayerBlasts() { 00216 for (int i = 0; i < player.max_player_blasts; ++i) { 00217 GameObject& blast = player.blasts[i]; 00218 if (blast.active) { 00219 bool collision = circleBounds.circleCollideTwoObjects( 00220 boss.pos, boss.boss_bounds, 00221 blast.pos, player.blast_bounds 00222 ); 00223 if (collision) { 00224 boss.boss_lives -= 1; 00225 gamepad.tone(123,0.4); 00226 blast.active = false; 00227 #ifdef DEBUGel17dg 00228 printf("boss has. left: %i \n", boss.boss_lives); 00229 #endif 00230 } 00231 } 00232 } 00233 } 00234 00235 void Game::collideBossBlastsAndPlayer() { 00236 for (int i = 0; i < boss.max_boss_blasts; ++i) { 00237 GameObject& blast = boss.boss_blasts[i]; 00238 if (blast.active) { 00239 bool collision = circleBounds.circleCollideTwoObjects( 00240 player.pos, player.player_bounds, 00241 blast.pos, boss.boss_blast_bounds 00242 ); 00243 #ifdef DEBUGel17dg 00244 printf("player pos:%i,%i; offset:%i,%i; radius:%f.3; \n", player.pos.x, player.pos.y, player.player_bounds.center.x, player.player_bounds.center.y, player.player_bounds.radius); 00245 printf("blas pos:%i,%i; offset:%i,%i; radius:%f.3; \n", blast.pos.x, blast.pos.y, boss.boss_blast_bounds.center.x, boss.boss_blast_bounds.center.y, boss.boss_blast_bounds.radius); 00246 #endif 00247 if (collision) { 00248 if (!GameGlobals::is_shield_on){ 00249 00250 gamepad.tone(423,0.4); 00251 GameGlobals::player_lifes -= 1; 00252 blast.active = false; 00253 #ifdef DEBUGel17dg 00254 printf("collision happened;\n"); 00255 printf("lost a life from blast. left: %i \n", GameGlobals::player_lifes); 00256 #endif 00257 }else{ 00258 blast.active = false; 00259 gamepad.tone(700,0.6); 00260 } 00261 } 00262 } 00263 } 00264 } 00265 00266 /** 00267 * This function resets all the values to their intial states when the game is 00268 * first began when the player dies and wants to restart the game. 00269 * It does not reset the values when the game is paused. 00270 */ 00271 void Game::startNewGame() { 00272 is_boss_active = false; 00273 game_state = GameState_gameplay; 00274 player.pos.x = 0; //player was defined in player.h 00275 player.pos.y = 24; 00276 stars.stars_delay = 0; 00277 enemy_ship_delay_max = 40; 00278 enemy_ship_delay_counter = enemy_ship_delay_max; 00279 GameGlobals::is_shield_on = false; 00280 GameGlobals::game_score = 0; 00281 GameGlobals::score_count_for_difficulty = 0; 00282 GameGlobals::player_lifes = 3; 00283 GameGlobals::score_count_for_boss_mode = 0; 00284 hud.resetRedLed(); 00285 enemies.enemy_blast_speed = 3; 00286 enemy.enemy_speed = 1; 00287 #ifdef DEBUGel17dg 00288 printf("startNewGame\n"); 00289 00290 #endif 00291 for (int i = 0; i < enemies.max_enemies; ++i) { 00292 enemies.enemies[i].active = false; 00293 } 00294 for (int i = 0; i < player.max_player_blasts; ++i) { 00295 player.blasts[i].active = false; 00296 } 00297 for (int i = 0; i < enemies.max_enemy_blasts; ++i) { 00298 enemies.enemy_blasts[i].active = false; 00299 } 00300 for (int i = 0; i < boss.max_boss_blasts; ++i) { 00301 boss.boss_blasts[i].active = false; 00302 } 00303 gamepad.check_event(gamepad.START_PRESSED); 00304 } 00305 00306 /** 00307 * A function tbat delays enemy spawn on low game score. 00308 * It decreases the enemy spawn delay as in game score increases. 00309 * The enemy spawn delay is located in game.cpp because the game difficulty 00310 * depends on the on how fast enemy appears. 00311 */ 00312 void Game::increaseGameDifficultyAndEnemySpawnDelay(){ 00313 if (enemy_ship_delay_counter <= 0){ 00314 enemies.spawnNewEnemy(); 00315 enemy_ship_delay_counter = enemy_ship_delay_max; 00316 } 00317 else { enemy_ship_delay_counter -= 1;} 00318 00319 if (enemy_ship_delay_max >= 4 && GameGlobals::score_count_for_difficulty >= increase_difficulty){ 00320 //decrease enemy delay spawn. 00321 enemy_ship_delay_max -= 3; 00322 if (enemy_ship_delay_max <= 20 && enemy_ship_delay_max >= 15){ 00323 enemies.enemy_blast_speed += 1; 00324 enemy.enemy_speed += 1; 00325 } 00326 GameGlobals::score_count_for_difficulty = 0; 00327 } 00328 if (GameGlobals::score_count_for_boss_mode >= 400){ 00329 is_boss_active = true; 00330 lcd.inverseMode(); 00331 } 00332 } 00333 00334 bool Game::forceShildActivate(){ 00335 if (gamepad.check_event(gamepad.R_PRESSED)){ 00336 GameGlobals::is_shield_on = !GameGlobals::is_shield_on; 00337 } 00338 return GameGlobals::is_shield_on; 00339 } 00340 00341 /** 00342 * This is a single line function to set the player lifes to 0 when the. 00343 * game is over. 00344 */ 00345 bool Game::checkForGameOver() { 00346 return GameGlobals::player_lifes <= 0; 00347 } 00348 00349 /** This small statment checks whether the pause button was pressed or not. 00350 * If it was pressed, then the game will go back to main menu and will save 00351 * the current status of the object until the game is continued. 00352 */ 00353 bool Game::checkIfNeedsToReturnToMenu(){ 00354 bool want_to_pause = false; 00355 00356 if (gamepad.check_event(gamepad.START_PRESSED)){ 00357 #ifdef DEBUGel17dg 00358 printf("game paused\n"); 00359 #endif 00360 gamepad.check_event(gamepad.START_PRESSED); 00361 want_to_pause = true; 00362 } 00363 return want_to_pause; 00364 }
Generated on Wed Dec 20 2023 20:30:17 by
