Initial publish
Dependencies: mbed
Fork of el17dg by
game/game.cpp@28:35af3843de8f, 2019-04-10 (annotated)
- Committer:
- Noximilien
- Date:
- Wed Apr 10 15:42:10 2019 +0000
- Revision:
- 28:35af3843de8f
- Parent:
- 27:f05f4e738ba9
- Child:
- 29:579e00b7f118
Moved starSpawnDelay to stars.h. Made enemies move y-direction as the game score increase. Added more comments. Cleaned the code a bit. Changed struct to gameObject in the main.cpp. Made some functions less than 20 lines.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Noximilien | 3:10918b0f7a7d | 1 | #include "mbed.h" |
Noximilien | 3:10918b0f7a7d | 2 | #include "N5110.h" |
Noximilien | 3:10918b0f7a7d | 3 | #include "Gamepad.h" |
Noximilien | 3:10918b0f7a7d | 4 | |
Noximilien | 3:10918b0f7a7d | 5 | #include "models.h" |
Noximilien | 4:02c63aaa2df9 | 6 | #include "main.h" |
Noximilien | 4:02c63aaa2df9 | 7 | #include "game.h" |
Noximilien | 21:0eb394495b8a | 8 | #include "geometry.h" |
Noximilien | 21:0eb394495b8a | 9 | #include "gameobject.h" |
Noximilien | 21:0eb394495b8a | 10 | |
Noximilien | 21:0eb394495b8a | 11 | #include "enemies.h" |
Noximilien | 22:4dc3c95f2146 | 12 | #include "constants.h" |
Noximilien | 23:240bc00ef25b | 13 | #include "stars.h" |
Noximilien | 23:240bc00ef25b | 14 | #include "player.h" |
Noximilien | 26:676874c42883 | 15 | #include "hud.h" |
Noximilien | 20:557e84189a57 | 16 | |
Noximilien | 21:0eb394495b8a | 17 | bool game_over = true; |
Noximilien | 21:0eb394495b8a | 18 | int game_score; |
Noximilien | 28:35af3843de8f | 19 | int high_score = 0; |
Noximilien | 26:676874c42883 | 20 | int score_count_for_difficulty; |
Noximilien | 27:f05f4e738ba9 | 21 | int player_lifes = 3; |
Noximilien | 21:0eb394495b8a | 22 | bool red_led_state; |
Noximilien | 21:0eb394495b8a | 23 | int red_led_flashing; |
Noximilien | 26:676874c42883 | 24 | int enemy_ship_delay_counter; |
Noximilien | 7:42376925945c | 25 | |
Noximilien | 26:676874c42883 | 26 | const int increase_difficulty = 50; |
Noximilien | 26:676874c42883 | 27 | int enemy_ship_delay_max = 40; |
Noximilien | 11:cf2ba52e8b7e | 28 | |
Noximilien | 21:0eb394495b8a | 29 | Enemies enemies; |
Noximilien | 23:240bc00ef25b | 30 | Stars stars; |
Noximilien | 23:240bc00ef25b | 31 | Player playerShip; |
Noximilien | 23:240bc00ef25b | 32 | GameObject gameOverLogo; |
Noximilien | 23:240bc00ef25b | 33 | GameObject youDied; |
Noximilien | 26:676874c42883 | 34 | Hud hud; |
Noximilien | 12:bfe3a3deaac3 | 35 | |
Noximilien | 22:4dc3c95f2146 | 36 | /**@brief |
Noximilien | 22:4dc3c95f2146 | 37 | * This function checks whether the requirments for the collision of the two objects, |
Noximilien | 22:4dc3c95f2146 | 38 | * are met. When those requirments are met the collision of two objects function will |
Noximilien | 22:4dc3c95f2146 | 39 | * be checking wheter the boundaries of the objects colide. If they do, the blast |
Noximilien | 22:4dc3c95f2146 | 40 | * becomes inactive, in game score increases and enemy dies. |
Noximilien | 22:4dc3c95f2146 | 41 | */ |
Noximilien | 21:0eb394495b8a | 42 | void Game::collideEnemiesAndBlasts() { |
Noximilien | 21:0eb394495b8a | 43 | for (int i = 0; i < max_enemies; ++i) { |
Noximilien | 23:240bc00ef25b | 44 | for (int j = 0; j < max_player_blasts; ++j) { |
Noximilien | 21:0eb394495b8a | 45 | Enemy& enemy = enemies.enemies[i]; |
Noximilien | 21:0eb394495b8a | 46 | GameObject& blast = blasts[j]; |
Noximilien | 21:0eb394495b8a | 47 | if (enemy.active && !enemy.dead && blast.active) { |
Noximilien | 12:bfe3a3deaac3 | 48 | bool collision = circleCollideTwoObjects( |
Noximilien | 21:0eb394495b8a | 49 | enemy.pos, enemies.enemy_bounds, |
Noximilien | 21:0eb394495b8a | 50 | blast.pos, blast_bounds |
Noximilien | 12:bfe3a3deaac3 | 51 | ); |
Noximilien | 12:bfe3a3deaac3 | 52 | if (collision) { |
Noximilien | 21:0eb394495b8a | 53 | enemy.die(); |
Noximilien | 21:0eb394495b8a | 54 | game_score += 30; |
Noximilien | 26:676874c42883 | 55 | score_count_for_difficulty +=30; |
Noximilien | 21:0eb394495b8a | 56 | blast.active = false; |
Noximilien | 12:bfe3a3deaac3 | 57 | } |
Noximilien | 12:bfe3a3deaac3 | 58 | } |
Noximilien | 12:bfe3a3deaac3 | 59 | } |
Noximilien | 12:bfe3a3deaac3 | 60 | } |
Noximilien | 12:bfe3a3deaac3 | 61 | } |
Noximilien | 5:2b9181bc5c89 | 62 | |
Noximilien | 22:4dc3c95f2146 | 63 | /**@brief |
Noximilien | 23:240bc00ef25b | 64 | * This code does the same work as the one before but with two other objects. |
Noximilien | 22:4dc3c95f2146 | 65 | * It checks whether the requirments for the collision of the two objects, |
Noximilien | 22:4dc3c95f2146 | 66 | * are met. When those requirments are met the collision of two objects function will |
Noximilien | 22:4dc3c95f2146 | 67 | * be checking wheter the boundaries of the objects colide. If they do, the blast |
Noximilien | 22:4dc3c95f2146 | 68 | * becomes inactive, in game score increases and enemy dies. |
Noximilien | 22:4dc3c95f2146 | 69 | */ |
Noximilien | 21:0eb394495b8a | 70 | void Game::collideEnemiesBlastsAndPlayer() { |
Noximilien | 23:240bc00ef25b | 71 | for (int i = 0; i < max_enemies; ++i) { |
Noximilien | 21:0eb394495b8a | 72 | GameObject& blast = enemies.enemy_blasts[i]; |
Noximilien | 21:0eb394495b8a | 73 | if (blast.active) { |
Noximilien | 21:0eb394495b8a | 74 | bool collision = circleCollideTwoObjects( |
Noximilien | 21:0eb394495b8a | 75 | player.pos, player_bounds, |
Noximilien | 21:0eb394495b8a | 76 | blast.pos, enemies.enemy_blast_bounds |
Noximilien | 21:0eb394495b8a | 77 | ); |
Noximilien | 21:0eb394495b8a | 78 | if (collision) { |
Noximilien | 23:240bc00ef25b | 79 | gamepad.tone(87,0.3); |
Noximilien | 23:240bc00ef25b | 80 | gamepad.tone(287,0.2); |
Noximilien | 23:240bc00ef25b | 81 | gamepad.tone(423,0.4); |
Noximilien | 27:f05f4e738ba9 | 82 | printf("lost a life. left: %i \n", player_lifes); |
Noximilien | 21:0eb394495b8a | 83 | player_lifes -= 1; |
Noximilien | 21:0eb394495b8a | 84 | blast.active = false; |
Noximilien | 18:6becc9f9de5e | 85 | } |
Noximilien | 18:6becc9f9de5e | 86 | } |
Noximilien | 18:6becc9f9de5e | 87 | } |
Noximilien | 18:6becc9f9de5e | 88 | } |
Noximilien | 26:676874c42883 | 89 | |
Noximilien | 22:4dc3c95f2146 | 90 | /**@brief |
Noximilien | 23:240bc00ef25b | 91 | * This code does the same work as the one before but with two other object. |
Noximilien | 23:240bc00ef25b | 92 | * of enemy ship and the player's ship |
Noximilien | 22:4dc3c95f2146 | 93 | */ |
Noximilien | 23:240bc00ef25b | 94 | void Game::collideEnemiesAndPlayer() { |
Noximilien | 27:f05f4e738ba9 | 95 | for (int i = 0; i < max_enemies; ++i) { |
Noximilien | 23:240bc00ef25b | 96 | Enemy& enemy = enemies.enemies[i]; |
Noximilien | 23:240bc00ef25b | 97 | if (enemy.active && !enemy.dead) { |
Noximilien | 23:240bc00ef25b | 98 | bool collision = circleCollideTwoObjects( |
Noximilien | 23:240bc00ef25b | 99 | player.pos, player_bounds, |
Noximilien | 23:240bc00ef25b | 100 | enemy.pos, enemies.enemy_bounds |
Noximilien | 23:240bc00ef25b | 101 | ); |
Noximilien | 23:240bc00ef25b | 102 | if (collision) { |
Noximilien | 27:f05f4e738ba9 | 103 | player_lifes -= 1; |
Noximilien | 23:240bc00ef25b | 104 | enemy.die(); |
Noximilien | 23:240bc00ef25b | 105 | } |
Noximilien | 23:240bc00ef25b | 106 | } |
Noximilien | 23:240bc00ef25b | 107 | } |
Noximilien | 13:5c3dc6e827c2 | 108 | } |
Noximilien | 13:5c3dc6e827c2 | 109 | |
Noximilien | 26:676874c42883 | 110 | /**@brief |
Noximilien | 26:676874c42883 | 111 | * This function resets all the values to their intial states when the game is |
Noximilien | 26:676874c42883 | 112 | * first began when the player dies and wants to restart the game. |
Noximilien | 23:240bc00ef25b | 113 | * It does not reset the values when the game is paused. |
Noximilien | 23:240bc00ef25b | 114 | */ |
Noximilien | 21:0eb394495b8a | 115 | void Game::startNewGame() { |
Noximilien | 23:240bc00ef25b | 116 | gameOverLogo.pos.x = game_area_x - 29; // 0 - the sprite length |
Noximilien | 23:240bc00ef25b | 117 | gameOverLogo.pos.y = game_area_y; |
Noximilien | 23:240bc00ef25b | 118 | youDied.pos.x = game_area_width; |
Noximilien | 23:240bc00ef25b | 119 | youDied.pos.y = game_area_y; |
Noximilien | 21:0eb394495b8a | 120 | game_over = false; |
Noximilien | 23:240bc00ef25b | 121 | player.pos.x = 0; //player was defined in player.h |
Noximilien | 21:0eb394495b8a | 122 | player.pos.y = 24; |
Noximilien | 26:676874c42883 | 123 | stars_delay = 0; |
Noximilien | 26:676874c42883 | 124 | enemy_ship_delay_max = 40; |
Noximilien | 26:676874c42883 | 125 | enemy_ship_delay_counter = enemy_ship_delay_max; |
Noximilien | 21:0eb394495b8a | 126 | game_score = 0; |
Noximilien | 26:676874c42883 | 127 | score_count_for_difficulty = 0; |
Noximilien | 21:0eb394495b8a | 128 | player_lifes = 3; |
Noximilien | 21:0eb394495b8a | 129 | red_led_state = false; |
Noximilien | 21:0eb394495b8a | 130 | red_led_flashing = 0; |
Noximilien | 26:676874c42883 | 131 | enemy_blast_speed = 3; |
Noximilien | 26:676874c42883 | 132 | enemy_speed = 1; |
Noximilien | 21:0eb394495b8a | 133 | for (int i = 0; i < max_enemies; ++i) { |
Noximilien | 21:0eb394495b8a | 134 | enemies.enemies[i].active = false; |
Noximilien | 13:5c3dc6e827c2 | 135 | } |
Noximilien | 23:240bc00ef25b | 136 | for (int i = 0; i < max_player_blasts; ++i) { |
Noximilien | 21:0eb394495b8a | 137 | blasts[i].active = false; |
Noximilien | 13:5c3dc6e827c2 | 138 | } |
Noximilien | 21:0eb394495b8a | 139 | for (int i = 0; i < max_enemy_blasts; ++i) { |
Noximilien | 21:0eb394495b8a | 140 | enemies.enemy_blasts[i].active = false; |
Noximilien | 13:5c3dc6e827c2 | 141 | } |
Noximilien | 27:f05f4e738ba9 | 142 | //Reset start button event |
Noximilien | 27:f05f4e738ba9 | 143 | gamepad.check_event(gamepad.START_PRESSED); |
Noximilien | 27:f05f4e738ba9 | 144 | |
Noximilien | 13:5c3dc6e827c2 | 145 | } |
Noximilien | 13:5c3dc6e827c2 | 146 | |
Noximilien | 26:676874c42883 | 147 | /**@brief |
Noximilien | 23:240bc00ef25b | 148 | * A game over function that shows the sprites of "game over" and "you died". |
Noximilien | 23:240bc00ef25b | 149 | * Allows to reset the game to play again. |
Noximilien | 23:240bc00ef25b | 150 | */ |
Noximilien | 23:240bc00ef25b | 151 | void Game::gameOver() { |
Noximilien | 28:35af3843de8f | 152 | drawGameOver(); |
Noximilien | 26:676874c42883 | 153 | char buffer[32]; |
Noximilien | 24:0570cb4b92d7 | 154 | sprintf(buffer,"Your Score %i",game_score); |
Noximilien | 24:0570cb4b92d7 | 155 | lcd.printString(buffer,0,3); |
Noximilien | 23:240bc00ef25b | 156 | wait(1); |
Noximilien | 23:240bc00ef25b | 157 | lcd.printString("Press Y",0,4); |
Noximilien | 23:240bc00ef25b | 158 | lcd.printString("to restart",0,5); |
Noximilien | 23:240bc00ef25b | 159 | lcd.refresh(); |
Noximilien | 23:240bc00ef25b | 160 | bool led_state = false; |
Noximilien | 23:240bc00ef25b | 161 | while (!gamepad.check_event(gamepad.Y_PRESSED)){////////////////////////////// |
Noximilien | 23:240bc00ef25b | 162 | gamepad.led(1,(float)led_state); |
Noximilien | 23:240bc00ef25b | 163 | gamepad.led(2,(float)!led_state); |
Noximilien | 23:240bc00ef25b | 164 | gamepad.led(3,(float)led_state); |
Noximilien | 23:240bc00ef25b | 165 | gamepad.led(4,(float)!led_state); |
Noximilien | 23:240bc00ef25b | 166 | gamepad.led(5,(float)led_state); |
Noximilien | 23:240bc00ef25b | 167 | gamepad.led(6,(float)!led_state); |
Noximilien | 23:240bc00ef25b | 168 | wait(0.5); |
Noximilien | 23:240bc00ef25b | 169 | led_state = !led_state; |
Noximilien | 23:240bc00ef25b | 170 | } |
Noximilien | 23:240bc00ef25b | 171 | } |
Noximilien | 23:240bc00ef25b | 172 | |
Noximilien | 26:676874c42883 | 173 | /**@brief |
Noximilien | 26:676874c42883 | 174 | * A function tbat delays enemy spawn on low game score. |
Noximilien | 26:676874c42883 | 175 | * It decreases the enemy spawn delay as in game score increases. |
Noximilien | 26:676874c42883 | 176 | */ |
Noximilien | 26:676874c42883 | 177 | void Game::increaseGameDifficultyAndEnemySpawnDelay(){ |
Noximilien | 26:676874c42883 | 178 | if (enemy_ship_delay_counter <= 0){ |
Noximilien | 26:676874c42883 | 179 | enemies.spawnNewEnemy(); |
Noximilien | 26:676874c42883 | 180 | enemy_ship_delay_counter = enemy_ship_delay_max; |
Noximilien | 26:676874c42883 | 181 | } |
Noximilien | 26:676874c42883 | 182 | else { enemy_ship_delay_counter -= 1;} |
Noximilien | 26:676874c42883 | 183 | |
Noximilien | 26:676874c42883 | 184 | if (enemy_ship_delay_max >= 4 && score_count_for_difficulty >= increase_difficulty){ |
Noximilien | 26:676874c42883 | 185 | enemy_ship_delay_max -= 3; |
Noximilien | 26:676874c42883 | 186 | |
Noximilien | 26:676874c42883 | 187 | if (enemy_ship_delay_max <= 20 && enemy_ship_delay_max >= 15){ |
Noximilien | 26:676874c42883 | 188 | enemy_blast_speed += 1; |
Noximilien | 26:676874c42883 | 189 | enemy_speed += 1; |
Noximilien | 26:676874c42883 | 190 | } |
Noximilien | 26:676874c42883 | 191 | score_count_for_difficulty = 0; |
Noximilien | 26:676874c42883 | 192 | } |
Noximilien | 26:676874c42883 | 193 | } |
Noximilien | 26:676874c42883 | 194 | |
Noximilien | 26:676874c42883 | 195 | /**@brief |
Noximilien | 23:240bc00ef25b | 196 | * This is the main function of game.cpp, where the actual gameplay happens. |
Noximilien | 23:240bc00ef25b | 197 | * Here all other functions are activeated, and when the player dies, it |
Noximilien | 23:240bc00ef25b | 198 | * returns back to main menu "main.cpp". |
Noximilien | 23:240bc00ef25b | 199 | */ |
Noximilien | 21:0eb394495b8a | 200 | bool Game::updateAndDraw() { |
Noximilien | 27:f05f4e738ba9 | 201 | //printf("update \n"); |
Noximilien | 21:0eb394495b8a | 202 | if (game_over) { |
Noximilien | 27:f05f4e738ba9 | 203 | printf("start game \n"); |
Noximilien | 21:0eb394495b8a | 204 | startNewGame(); |
Noximilien | 13:5c3dc6e827c2 | 205 | } |
Noximilien | 26:676874c42883 | 206 | |
Noximilien | 19:b78fa41d04a9 | 207 | if (gamepad.check_event(gamepad.X_PRESSED)){ |
Noximilien | 28:35af3843de8f | 208 | // Checking the button second time to prevent double blast. |
Noximilien | 28:35af3843de8f | 209 | gamepad.check_event(gamepad.X_PRESSED); |
Noximilien | 23:240bc00ef25b | 210 | playerShip.fireNewBlast(); |
Noximilien | 23:240bc00ef25b | 211 | gamepad.tone(200,0.1); |
Noximilien | 6:100b46be4bea | 212 | } |
Noximilien | 26:676874c42883 | 213 | |
Noximilien | 26:676874c42883 | 214 | playerShip.playerShipMovement(); |
Noximilien | 28:35af3843de8f | 215 | stars.starsSpawnDelay(); |
Noximilien | 26:676874c42883 | 216 | increaseGameDifficultyAndEnemySpawnDelay(); |
Noximilien | 26:676874c42883 | 217 | hud.displayLifes(); |
Noximilien | 23:240bc00ef25b | 218 | playerShip.updateAndDrawBlasts(); |
Noximilien | 23:240bc00ef25b | 219 | stars.updateAndDrawSmallStars(); |
Noximilien | 23:240bc00ef25b | 220 | stars.updateAndDrawMediumStars(); |
Noximilien | 21:0eb394495b8a | 221 | enemies.updateAndDrawEnemies(); |
Noximilien | 12:bfe3a3deaac3 | 222 | collideEnemiesAndBlasts(); |
Noximilien | 18:6becc9f9de5e | 223 | collideEnemiesBlastsAndPlayer(); |
Noximilien | 23:240bc00ef25b | 224 | collideEnemiesAndPlayer(); |
Noximilien | 21:0eb394495b8a | 225 | enemies.updateAndDrawEnemyBlasts(); |
Noximilien | 27:f05f4e738ba9 | 226 | hud.drawScore(); |
Noximilien | 24:0570cb4b92d7 | 227 | |
Noximilien | 24:0570cb4b92d7 | 228 | /**@brief |
Noximilien | 26:676874c42883 | 229 | * This small statment checks whether the pause button was pressed or not. |
Noximilien | 26:676874c42883 | 230 | * If it was pressed, then the game will go back to main menu and will save |
Noximilien | 26:676874c42883 | 231 | * the current status of the object until the game is continued. |
Noximilien | 26:676874c42883 | 232 | */ |
Noximilien | 4:02c63aaa2df9 | 233 | bool want_to_pause = false; |
Noximilien | 27:f05f4e738ba9 | 234 | game_over = checkForGameOver(); |
Noximilien | 21:0eb394495b8a | 235 | if (game_over){ |
Noximilien | 27:f05f4e738ba9 | 236 | printf("game over happened\n"); |
Noximilien | 23:240bc00ef25b | 237 | gameOver(); |
Noximilien | 21:0eb394495b8a | 238 | want_to_pause = true; |
Noximilien | 21:0eb394495b8a | 239 | } |
Noximilien | 4:02c63aaa2df9 | 240 | if (gamepad.check_event(gamepad.START_PRESSED)){ |
Noximilien | 27:f05f4e738ba9 | 241 | printf("pausing the game\n"); |
Noximilien | 28:35af3843de8f | 242 | gamepad.check_event(gamepad.START_PRESSED); |
Noximilien | 19:b78fa41d04a9 | 243 | want_to_pause = true; |
Noximilien | 4:02c63aaa2df9 | 244 | } |
Noximilien | 4:02c63aaa2df9 | 245 | return want_to_pause; |
Noximilien | 27:f05f4e738ba9 | 246 | } |
Noximilien | 27:f05f4e738ba9 | 247 | /**@brief |
Noximilien | 27:f05f4e738ba9 | 248 | * This is a single line function to set the player lifes to 0 when the. |
Noximilien | 27:f05f4e738ba9 | 249 | * game is over. |
Noximilien | 27:f05f4e738ba9 | 250 | */ |
Noximilien | 27:f05f4e738ba9 | 251 | bool Game::checkForGameOver() { |
Noximilien | 27:f05f4e738ba9 | 252 | return player_lifes == 0; |
Noximilien | 28:35af3843de8f | 253 | } |
Noximilien | 28:35af3843de8f | 254 | void Game::drawGameOver(){ |
Noximilien | 28:35af3843de8f | 255 | for (int i = 0; i < 42; i++){ |
Noximilien | 28:35af3843de8f | 256 | lcd.clear(); |
Noximilien | 28:35af3843de8f | 257 | lcd.drawSprite(gameOverLogo.pos.x + i, gameOverLogo.pos.y, 14, 29, (int*)gameOverSprite); |
Noximilien | 28:35af3843de8f | 258 | lcd.drawSprite(youDied.pos.x - i, youDied.pos.y, 14, 24, (int*)youDiedSprite); |
Noximilien | 28:35af3843de8f | 259 | lcd.refresh(); |
Noximilien | 28:35af3843de8f | 260 | wait(0.1); |
Noximilien | 28:35af3843de8f | 261 | } |
Noximilien | 26:676874c42883 | 262 | } |