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.
Dependencies: mbed
Fork of el17dg by
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 Hud hud; 00036 00037 00038 void Game::updateAndDrawGameplay() { 00039 checkButtonToShoot(); 00040 player.updateAndDraw(); 00041 player.updateAndDrawBlasts(); 00042 stars.updateAndDrawSmallStars(); 00043 stars.updateAndDrawMediumStars(); 00044 stars.starsSpawnDelay(); 00045 increaseGameDifficultyAndEnemySpawnDelay(); 00046 hud.displayLifes(); 00047 hud.drawScore(); 00048 collideEnemiesAndBlasts(); 00049 collideEnemiesBlastsAndPlayer(); 00050 collideEnemiesAndPlayer(); 00051 enemies.updateAndDrawEnemies(); 00052 enemies.updateAndDrawEnemyBlasts(); 00053 boss.updateAndDrawBossBlasts(); 00054 00055 if (checkForGameOver()) { game_state = GameState_gameover;} 00056 if (is_boss_active) { game_state = GameState_boss_cutscene;} 00057 } 00058 00059 void Game::updateAndDrawGameover() { 00060 gameOverManager.updateAndDraw(); 00061 lcd.normalMode(); 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 gamepad.tone(60,2); 00076 for (int i = 0; i < enemies.max_enemies; ++i) { 00077 enemies.enemies[i].active = false; 00078 } 00079 for (int i = 0; i < enemies.max_enemy_blasts; ++i) { 00080 enemies.enemy_blasts[i].active = false; 00081 } 00082 if (boss.isFinishedCutscene()) { 00083 game_state = GameState_boss_gameplay; 00084 boss.resetCutscene(); 00085 } 00086 } 00087 00088 void Game::updateAndDrawBossGameplay() { 00089 checkButtonToShoot(); 00090 enemies.updateAndDrawEnemyBlasts(); 00091 player.updateAndDraw(); 00092 player.updateAndDrawBlasts(); 00093 stars.updateAndDrawSmallStars(); 00094 stars.starsSpawnDelay(); 00095 hud.displayLifes(); 00096 hud.drawScore(); 00097 boss.updateAndDrawBossBlasts(); 00098 collideBossAndPlayerBlasts(); 00099 collideBossBlastsAndPlayer(); 00100 is_boss_active = boss.updateAndDrawBoss(); 00101 if (checkForGameOver()) { game_state = GameState_gameover;} 00102 if (!is_boss_active) { game_state = GameState_gameplay;} 00103 } 00104 00105 /** 00106 * This is the main function of game.cpp, where the actual gameplay happens. 00107 * Here all other functions are activeated, and when the player dies, it 00108 * returns back to main menu "main.cpp". 00109 */ 00110 bool Game::updateAndDraw() { 00111 if (game_state == GameState_newgame) { 00112 DG_PRINTF("start game \n"); 00113 startNewGame(); 00114 } 00115 if (game_state == GameState_gameplay) { updateAndDrawGameplay(); } 00116 else if (game_state == GameState_boss_cutscene) { updateAndDrawBossCutscene(); } 00117 else if (game_state == GameState_boss_gameplay) { updateAndDrawBossGameplay(); } 00118 else if (game_state == GameState_gameover) { updateAndDrawGameover(); } 00119 00120 return checkIfNeedsToReturnToMenu(); 00121 } 00122 00123 void Game::checkButtonToShoot(){ 00124 if (gamepad.check_event(gamepad.X_PRESSED) && !GameGlobals::is_shield_on){ 00125 // Checking the button second time to prevent double blast. 00126 gamepad.check_event(gamepad.X_PRESSED); 00127 player.fireNewBlast(); 00128 gamepad.tone(200,0.1); 00129 } 00130 } 00131 00132 /** 00133 * This function checks whether the requirments for the collision of the two objects, 00134 * are met. When those requirments are met the collision of two objects function will 00135 * be checking wheter the boundaries of the objects colide. If they do, the blast 00136 * becomes inactive, in game score increases and enemy dies. 00137 */ 00138 void Game::collideEnemiesAndBlasts() { 00139 for (int i = 0; i < enemies.max_enemies; ++i) { 00140 for (int j = 0; j < player.max_player_blasts; ++j) { 00141 Enemy& enemy = enemies.enemies[i]; 00142 GameObject& blast = player.blasts[j]; 00143 if (enemy.active && !enemy.dead && blast.active) { 00144 bool collision = circleCollideTwoObjects( 00145 enemy.pos, enemies.enemy_bounds, 00146 blast.pos, player.blast_bounds 00147 ); 00148 if (collision) { 00149 enemy.die(); 00150 DG_PRINTF("enemy got hit and dies \n"); 00151 GameGlobals::game_score += 30; 00152 GameGlobals::score_count_for_difficulty +=30; 00153 GameGlobals::score_count_for_boss_mode += 30; 00154 blast.active = false; 00155 } 00156 } 00157 } 00158 } 00159 } 00160 00161 /** 00162 * This code does the same work as the one before but with two other objects. 00163 * It checks whether the requirments for the collision of the two objects, 00164 * are met. When those requirments are met the collision of two objects function will 00165 * be checking wheter the boundaries of the objects colide. If they do, the blast 00166 * becomes inactive, in game score increases and enemy dies. 00167 */ 00168 void Game::collideEnemiesBlastsAndPlayer() { 00169 for (int i = 0; i < enemies.max_enemies; ++i) { 00170 GameObject& blast = enemies.enemy_blasts[i]; 00171 if (blast.active) { 00172 bool collision = circleCollideTwoObjects( 00173 player.pos, player.player_bounds, 00174 blast.pos, enemies.enemy_blast_bounds 00175 ); 00176 if (collision) { 00177 if (!GameGlobals::is_shield_on){ 00178 gamepad.tone(423,0.4); 00179 GameGlobals::player_lifes -= 1; 00180 DG_PRINTF("lost a life from blast. left: %i \n", GameGlobals::player_lifes); 00181 blast.active = false; 00182 }else{ 00183 blast.active = false; 00184 gamepad.tone(700,0.6); 00185 } 00186 } 00187 } 00188 } 00189 } 00190 00191 /** 00192 * This code does the same work as the one before but with two other object. 00193 * of enemy ship and the player's ship 00194 */ 00195 void Game::collideEnemiesAndPlayer() { 00196 for (int i = 0; i < enemies.max_enemies; ++i) { 00197 Enemy& enemy = enemies.enemies[i]; 00198 if (enemy.active && !enemy.dead) { 00199 bool collision = circleCollideTwoObjects( 00200 player.pos, player.player_bounds, 00201 enemy.pos, enemies.enemy_bounds 00202 ); 00203 if (collision) { 00204 GameGlobals::player_lifes -= 1; 00205 00206 enemy.die(); 00207 DG_PRINTF("enemy got hit from collsion and dies"); 00208 DG_PRINTF("lost a life from enemy col. left: %i \n", GameGlobals::player_lifes); 00209 } 00210 } 00211 } 00212 } 00213 00214 void Game::collideBossAndPlayerBlasts() { 00215 for (int i = 0; i < player.max_player_blasts; ++i) { 00216 GameObject& blast = player.blasts[i]; 00217 if (blast.active) { 00218 bool collision = circleCollideTwoObjects( 00219 boss.pos, boss.boss_bounds, 00220 blast.pos, player.blast_bounds 00221 ); 00222 if (collision) { 00223 boss.boss_lives -= 1; 00224 gamepad.tone(123,0.4); 00225 blast.active = false; 00226 DG_PRINTF("boss has. left: %i \n", boss.boss_lives); 00227 } 00228 } 00229 } 00230 } 00231 00232 void Game::collideBossBlastsAndPlayer() { 00233 for (int i = 0; i < boss.max_boss_blasts; ++i) { 00234 GameObject& blast = boss.boss_blasts[i]; 00235 if (blast.active) { 00236 bool collision = circleCollideTwoObjects( 00237 player.pos, player.player_bounds, 00238 blast.pos, boss.boss_blast_bounds 00239 ); 00240 DG_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); 00241 DG_PRINTF("blast 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); 00242 if (collision) { 00243 if (!GameGlobals::is_shield_on){ 00244 00245 gamepad.tone(423,0.4); 00246 GameGlobals::player_lifes -= 1; 00247 blast.active = false; 00248 DG_PRINTF("collision happened;\n"); 00249 DG_PRINTF("lost a life from blast. left: %i \n", GameGlobals::player_lifes); 00250 }else{ 00251 blast.active = false; 00252 gamepad.tone(700,0.6); 00253 } 00254 } 00255 } 00256 } 00257 } 00258 00259 /** 00260 * This function resets all the values to their intial states when the game is 00261 * first began when the player dies and wants to restart the game. 00262 * It does not reset the values when the game is paused. 00263 */ 00264 void Game::startNewGame() { 00265 is_boss_active = false; 00266 game_state = GameState_gameplay; 00267 player.pos.x = 0; //player was defined in player.h 00268 player.pos.y = 24; 00269 stars.stars_delay = 0; 00270 enemy_ship_delay_max = 40; 00271 enemy_ship_delay_counter = enemy_ship_delay_max; 00272 GameGlobals::is_shield_on = false; 00273 GameGlobals::game_score = 0; 00274 GameGlobals::score_count_for_difficulty = 0; 00275 GameGlobals::player_lifes = 3; 00276 GameGlobals::score_count_for_boss_mode = 0; 00277 hud.resetRedLed(); 00278 enemies.enemy_blast_speed = 3; 00279 enemy.enemy_speed = 1; 00280 gamepad.check_event(gamepad.START_PRESSED); 00281 for (int i = 0; i < enemies.max_enemies; ++i) { 00282 enemies.enemies[i].active = false; 00283 } 00284 for (int i = 0; i < player.max_player_blasts; ++i) { 00285 player.blasts[i].active = false; 00286 } 00287 for (int i = 0; i < enemies.max_enemy_blasts; ++i) { 00288 enemies.enemy_blasts[i].active = false; 00289 } 00290 for (int i = 0; i < boss.max_boss_blasts; ++i) { 00291 boss.boss_blasts[i].active = false; 00292 } 00293 gamepad.check_event(gamepad.START_PRESSED); 00294 } 00295 00296 /** 00297 * A function tbat delays enemy spawn on low game score. 00298 * It decreases the enemy spawn delay as in game score increases. 00299 * The enemy spawn delay is located in game.cpp because the game difficulty 00300 * depends on the on how fast enemy appears. 00301 */ 00302 void Game::increaseGameDifficultyAndEnemySpawnDelay(){ 00303 if (enemy_ship_delay_counter <= 0){ 00304 enemies.spawnNewEnemy(); 00305 enemy_ship_delay_counter = enemy_ship_delay_max; 00306 } 00307 else { enemy_ship_delay_counter -= 1;} 00308 00309 if (enemy_ship_delay_max >= 4 && GameGlobals::score_count_for_difficulty >= increase_difficulty){ 00310 //decrease enemy delay spawn. 00311 enemy_ship_delay_max -= 3; 00312 if (enemy_ship_delay_max <= 20 && enemy_ship_delay_max >= 15){ 00313 enemies.enemy_blast_speed += 1; 00314 enemy.enemy_speed += 1; 00315 } 00316 GameGlobals::score_count_for_difficulty = 0; 00317 } 00318 if (GameGlobals::score_count_for_boss_mode >= 400){ 00319 is_boss_active = true; 00320 lcd.inverseMode(); 00321 } 00322 } 00323 00324 bool Game::forceShildActivate(){ 00325 if (gamepad.check_event(gamepad.R_PRESSED)){ 00326 GameGlobals::is_shield_on = !GameGlobals::is_shield_on; 00327 } 00328 return GameGlobals::is_shield_on; 00329 } 00330 00331 /** 00332 * This is a single line function to set the player lifes to 0 when the. 00333 * game is over. 00334 */ 00335 bool Game::checkForGameOver() { 00336 return GameGlobals::player_lifes <= 0; 00337 } 00338 00339 /** This small statment checks whether the pause button was pressed or not. 00340 * If it was pressed, then the game will go back to main menu and will save 00341 * the current status of the object until the game is continued. 00342 */ 00343 bool Game::checkIfNeedsToReturnToMenu(){ 00344 bool want_to_pause = false; 00345 00346 if (gamepad.check_event(gamepad.START_PRESSED)){ 00347 DG_PRINTF("game paused\n"); 00348 gamepad.check_event(gamepad.START_PRESSED); 00349 gamepad.check_event(gamepad.A_PRESSED); 00350 want_to_pause = true; 00351 } 00352 return want_to_pause; 00353 }
Generated on Thu Jul 14 2022 14:15:02 by
1.7.2
