Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407

Dependencies:   Joystick N5110 SDFileSystem mbed

Committer:
avi23
Date:
Thu May 05 13:58:33 2016 +0000
Revision:
11:eab3fb334bde
Parent:
9:cbb982b7e353
Fixed Mute option leaving a trailing 'f'

Who changed what in which revision?

UserRevisionLine numberNew contents of line
avi23 8:b2faec20ed8f 1 /**
avi23 8:b2faec20ed8f 2 @file main.cpp
avi23 8:b2faec20ed8f 3 @brief Implementation File
avi23 8:b2faec20ed8f 4 */
avi23 8:b2faec20ed8f 5
avi23 1:b300d052d549 6 /*
avi23 1:b300d052d549 7 Space Invaders - Avinash Patel 200860407
avi23 1:b300d052d549 8
avi23 1:b300d052d549 9 Week 19 - Set up joystick class
avi23 1:b300d052d549 10 Week 20 - Changed to space invaders as constrained too much by screen resolution
avi23 1:b300d052d549 11 - Core cannon is drawn and can move, enemies are visible and they switch between states every second
avi23 2:d34c95990605 12 Week 21 - Begun to set up barriers
avi23 5:34855f712350 13 Easter - Barriers work, invader and player can shoot. Begun setting up menus
avi23 7:babc367a3333 14 Week 22 - Most menus work
avi23 7:babc367a3333 15 Week 23 - Menus work
avi23 1:b300d052d549 16 */
avi23 0:427469992efe 17 #include "mbed.h"
avi23 7:babc367a3333 18 #include "main.h"
avi23 0:427469992efe 19
avi23 0:427469992efe 20 int main()
avi23 0:427469992efe 21 {
avi23 8:b2faec20ed8f 22 ///Wait for 2 seconds to allow power to settle
avi23 5:34855f712350 23 wait(1);
avi23 8:b2faec20ed8f 24 ///Initalises the board and perhiperals
avi23 0:427469992efe 25 init_K64F();
avi23 0:427469992efe 26 init_serial();
avi23 2:d34c95990605 27 init_shoot();
avi23 5:34855f712350 28 init_rng();
avi23 5:34855f712350 29 joystick.init();
avi23 0:427469992efe 30 lcd.init();
avi23 0:427469992efe 31 lcd.clear();
avi23 0:427469992efe 32
avi23 9:cbb982b7e353 33 LoadHighScores();
avi23 9:cbb982b7e353 34
avi23 8:b2faec20ed8f 35 ///Configures the function pointer for the invaders normal missile
avi23 5:34855f712350 36 move_invader_normal_missile_isr[0] = &move_invader_normal_missile_0_isr;
avi23 5:34855f712350 37 move_invader_normal_missile_isr[1] = &move_invader_normal_missile_1_isr;
avi23 0:427469992efe 38
avi23 8:b2faec20ed8f 39 ///Samples joystick every 0.05 second
avi23 5:34855f712350 40 move_joystick.attach(&move_joystick_isr, 0.05);
avi23 2:d34c95990605 41
avi23 9:cbb982b7e353 42 ///Splash Screen
avi23 9:cbb982b7e353 43 SplashScreen();
avi23 9:cbb982b7e353 44
avi23 2:d34c95990605 45 while (true) {
avi23 8:b2faec20ed8f 46 if (game_state == menu) { ///Menu screen
avi23 8:b2faec20ed8f 47 lcd.clear();
avi23 8:b2faec20ed8f 48 fsm_state = 0; ///Sets the fsm state to 0
avi23 8:b2faec20ed8f 49 MenuScreen();
avi23 8:b2faec20ed8f 50 } else if (game_state == paused) { ///Paused screen
avi23 8:b2faec20ed8f 51 ///Clears the screen
avi23 2:d34c95990605 52 lcd.clear();
avi23 8:b2faec20ed8f 53 fsm_state = 0; ///Ssets the fsm state to 0
avi23 8:b2faec20ed8f 54 PauseScreen();
avi23 8:b2faec20ed8f 55 } else if (game_state == game) { ///Game screen
avi23 8:b2faec20ed8f 56 AttachTickers();
avi23 8:b2faec20ed8f 57 Game();
avi23 8:b2faec20ed8f 58 } else if (game_state == save) {
avi23 9:cbb982b7e353 59 SaveGameData();
avi23 8:b2faec20ed8f 60 } else if (game_state == load) {
avi23 9:cbb982b7e353 61 LoadGameData();
avi23 9:cbb982b7e353 62 } else if (game_state == over) {
avi23 9:cbb982b7e353 63 lcd.clear();
avi23 9:cbb982b7e353 64 GameOverScreen();
avi23 9:cbb982b7e353 65 } else if (game_state == scores) {
avi23 9:cbb982b7e353 66 lcd.clear();
avi23 9:cbb982b7e353 67 ScoreScreen();
avi23 9:cbb982b7e353 68 } else if (game_state == settings) {
avi23 9:cbb982b7e353 69 lcd.clear();
avi23 9:cbb982b7e353 70 fsm_state = 0;
avi23 9:cbb982b7e353 71 SettingsScreen();
avi23 0:427469992efe 72 }
avi23 2:d34c95990605 73
avi23 0:427469992efe 74 sleep();
avi23 0:427469992efe 75 }
avi23 0:427469992efe 76 }
avi23 0:427469992efe 77
avi23 0:427469992efe 78 void init_K64F()
avi23 0:427469992efe 79 {
avi23 8:b2faec20ed8f 80 /// on-board LEDs are active-low, so set pin high to turn them off.
avi23 0:427469992efe 81 r_led = 1;
avi23 0:427469992efe 82 g_led = 1;
avi23 0:427469992efe 83 b_led = 1;
avi23 0:427469992efe 84
avi23 8:b2faec20ed8f 85 /// since the on-board switches have external pull-ups, we should disable the internal pull-down
avi23 8:b2faec20ed8f 86 /// resistors that are enabled by default using InterruptIn
avi23 0:427469992efe 87 sw2.mode(PullNone);
avi23 0:427469992efe 88 sw3.mode(PullNone);
avi23 0:427469992efe 89 }
avi23 0:427469992efe 90
avi23 0:427469992efe 91 void error()
avi23 0:427469992efe 92 {
avi23 8:b2faec20ed8f 93 while(1) { /// if error, hang while flashing error message
avi23 0:427469992efe 94 r_led = 0;
avi23 0:427469992efe 95 wait(0.2);
avi23 0:427469992efe 96 r_led = 1;
avi23 0:427469992efe 97 wait(0.2);
avi23 0:427469992efe 98 }
avi23 0:427469992efe 99 }
avi23 0:427469992efe 100
avi23 0:427469992efe 101 void init_serial()
avi23 0:427469992efe 102 {
avi23 8:b2faec20ed8f 103 /// set to highest baud - ensure terminal software matches
avi23 0:427469992efe 104 pc.baud(115200);
avi23 0:427469992efe 105 }
avi23 0:427469992efe 106
avi23 8:b2faec20ed8f 107 ///Seeds the random number generator with noise from an analog in pin
avi23 5:34855f712350 108 void init_rng()
avi23 5:34855f712350 109 {
avi23 8:b2faec20ed8f 110 AnalogIn rng_seed(PTC10); ///Creates a AnalogIn on a unused pin
avi23 8:b2faec20ed8f 111 srand(floor(10000*rng_seed.read())); ///Sets the seed as 10000x the input of the analog in
avi23 5:34855f712350 112 }
avi23 5:34855f712350 113
avi23 2:d34c95990605 114 void init_shoot()
avi23 0:427469992efe 115 {
avi23 2:d34c95990605 116 shoot_button.mode(PullUp);
avi23 2:d34c95990605 117 shoot_button.fall(&shoot_pressed_isr);
avi23 9:cbb982b7e353 118 shoot_button.rise(&shoot_pressed_rise_isr);
avi23 2:d34c95990605 119 }
avi23 2:d34c95990605 120
avi23 2:d34c95990605 121 void update_screen_isr()
avi23 2:d34c95990605 122 {
avi23 2:d34c95990605 123 g_update_screen_flag = true;
avi23 0:427469992efe 124 }
avi23 0:427469992efe 125
avi23 5:34855f712350 126 void move_enemies_isr()
avi23 5:34855f712350 127 {
avi23 5:34855f712350 128 g_move_enemies_flag = true;
avi23 5:34855f712350 129 }
avi23 5:34855f712350 130
avi23 2:d34c95990605 131 void shoot_pressed_isr()
avi23 2:d34c95990605 132 {
avi23 8:b2faec20ed8f 133 ///Only sets the shoot pressed flag 0.1s after the last press
avi23 6:89d4a7f7588b 134 if (!g_shoot_button_debounce_flag) {
avi23 6:89d4a7f7588b 135 g_shoot_pressed_flag = true;
avi23 6:89d4a7f7588b 136 g_shoot_button_debounce_flag = true;
avi23 6:89d4a7f7588b 137 }
avi23 5:34855f712350 138 }
avi23 5:34855f712350 139
avi23 5:34855f712350 140 void move_cannon_missile_isr()
avi23 5:34855f712350 141 {
avi23 5:34855f712350 142 g_move_cannon_missile_flag = true;
avi23 5:34855f712350 143 }
avi23 5:34855f712350 144
avi23 5:34855f712350 145 void move_joystick_isr()
avi23 5:34855f712350 146 {
avi23 8:b2faec20ed8f 147 ///Always set the move flag in a game
avi23 5:34855f712350 148 if (game_state == game) {
avi23 5:34855f712350 149 g_move_joystick_flag = true;
avi23 5:34855f712350 150 } else if (!g_joystick_cursor_regulator_flag) {
avi23 8:b2faec20ed8f 151 ///Only sets the flag if the regulator is not set
avi23 5:34855f712350 152 g_move_joystick_flag = true;
avi23 5:34855f712350 153 g_joystick_cursor_regulator_flag = true;
avi23 5:34855f712350 154
avi23 8:b2faec20ed8f 155 ///Attachs a timeout to clear the regulator in 0.1s to prevent the cursor from behaving erratically
avi23 6:89d4a7f7588b 156 joystick_cursor_regulator.attach(&joystick_cursor_regulator_isr, 0.1);
avi23 5:34855f712350 157 }
avi23 5:34855f712350 158 }
avi23 5:34855f712350 159
avi23 6:89d4a7f7588b 160 void joystick_cursor_regulator_isr()
avi23 6:89d4a7f7588b 161 {
avi23 5:34855f712350 162 g_joystick_cursor_regulator_flag = false;
avi23 5:34855f712350 163 }
avi23 5:34855f712350 164
avi23 6:89d4a7f7588b 165 void shoot_button_debounce_isr()
avi23 6:89d4a7f7588b 166 {
avi23 6:89d4a7f7588b 167 g_shoot_button_debounce_flag = false;
avi23 6:89d4a7f7588b 168 }
avi23 6:89d4a7f7588b 169
avi23 5:34855f712350 170 void move_invader_normal_missile_0_isr()
avi23 5:34855f712350 171 {
avi23 5:34855f712350 172 g_move_invader_normal_missile_flag[0] = true;
avi23 5:34855f712350 173 }
avi23 5:34855f712350 174
avi23 5:34855f712350 175 void move_invader_normal_missile_1_isr()
avi23 5:34855f712350 176 {
avi23 5:34855f712350 177 g_move_invader_normal_missile_flag[1] = true;
avi23 5:34855f712350 178 }
avi23 5:34855f712350 179
avi23 5:34855f712350 180 void cannon_hit_isr()
avi23 5:34855f712350 181 {
avi23 5:34855f712350 182 g_cannon_hit_flag = false;
avi23 2:d34c95990605 183 }
avi23 2:d34c95990605 184
avi23 8:b2faec20ed8f 185 void move_ufo_isr()
avi23 8:b2faec20ed8f 186 {
avi23 8:b2faec20ed8f 187 g_move_ufo_flag = true;
avi23 8:b2faec20ed8f 188 }
avi23 8:b2faec20ed8f 189
avi23 8:b2faec20ed8f 190 void fire_buzzer_isr()
avi23 8:b2faec20ed8f 191 {
avi23 8:b2faec20ed8f 192 g_fire_buzzer_flag = true;
avi23 8:b2faec20ed8f 193 }
avi23 8:b2faec20ed8f 194
avi23 9:cbb982b7e353 195 void lp_wait_isr()
avi23 9:cbb982b7e353 196 {
avi23 9:cbb982b7e353 197 g_lp_wait_flag = false;
avi23 9:cbb982b7e353 198 }
avi23 9:cbb982b7e353 199
avi23 9:cbb982b7e353 200 void shoot_pressed_rise_isr()
avi23 9:cbb982b7e353 201 {
avi23 9:cbb982b7e353 202 ///Attaches a timeout to clear the debounce flag in 0.125 seconds
avi23 9:cbb982b7e353 203 shoot_button_debounce.attach(&shoot_button_debounce_isr, 0.125);
avi23 9:cbb982b7e353 204 }
avi23 9:cbb982b7e353 205
avi23 5:34855f712350 206 void Game()
avi23 6:89d4a7f7588b 207 {
avi23 8:b2faec20ed8f 208 ///Stays within the loop while the selected state is game
avi23 5:34855f712350 209 while (game_state == game) {
avi23 8:b2faec20ed8f 210 pc.printf("Mute: %d\n", is_muted);
avi23 9:cbb982b7e353 211 ///If the game is over detach all the tickers and set game state to over
avi23 5:34855f712350 212 if (number_of_lives == 0) {
avi23 5:34855f712350 213 DetachTickers();
avi23 9:cbb982b7e353 214 game_state = over;
avi23 8:b2faec20ed8f 215 } else if (no_of_alive_invaders == 0) { ///If the player wins a round
avi23 8:b2faec20ed8f 216 ///Resets the no of alive invaders
avi23 5:34855f712350 217 no_of_alive_invaders = 15;
avi23 8:b2faec20ed8f 218 down_count = 0;
avi23 8:b2faec20ed8f 219 ///Detaches the enemy ticker while reinitalising invaders
avi23 5:34855f712350 220 move_enemies.detach();
avi23 8:b2faec20ed8f 221 ///Reinitalises objects
avi23 5:34855f712350 222 InitSmallInvaders();
avi23 5:34855f712350 223 InitMediumInvaders();
avi23 5:34855f712350 224 InitLargeInvaders();
avi23 8:b2faec20ed8f 225 ///Reattaches enemy ticker
avi23 5:34855f712350 226 move_enemies.attach(&move_enemies_isr, 1);
avi23 5:34855f712350 227 } else {
avi23 8:b2faec20ed8f 228 ///Updates pixels on the screen
avi23 5:34855f712350 229 if (g_update_screen_flag) {
avi23 5:34855f712350 230 g_update_screen_flag = false;
avi23 5:34855f712350 231
avi23 5:34855f712350 232 UpdateScreen();
avi23 5:34855f712350 233 }
avi23 5:34855f712350 234
avi23 8:b2faec20ed8f 235 ///Controls cannon movement
avi23 5:34855f712350 236 if (g_move_joystick_flag) {
avi23 5:34855f712350 237 g_move_joystick_flag = false;
avi23 5:34855f712350 238
avi23 5:34855f712350 239 MoveCannon();
avi23 5:34855f712350 240 DrawBarriers();
avi23 5:34855f712350 241 }
avi23 5:34855f712350 242
avi23 8:b2faec20ed8f 243 ///Controls enemy movement
avi23 5:34855f712350 244 if (g_move_enemies_flag) {
avi23 5:34855f712350 245 g_move_enemies_flag = false;
avi23 5:34855f712350 246
avi23 8:b2faec20ed8f 247 ///Increses the speed the invaders move
avi23 5:34855f712350 248 move_enemies.detach();
avi23 5:34855f712350 249 ticker_period = 0.1+(no_of_alive_invaders*0.06);
avi23 5:34855f712350 250 move_enemies.attach(&move_enemies_isr, ticker_period);
avi23 5:34855f712350 251
avi23 8:b2faec20ed8f 252 //Attach the buzzer timeout if mute is unselected
avi23 8:b2faec20ed8f 253 if (!is_muted) {
avi23 8:b2faec20ed8f 254 fire_buzzer.attach(&fire_buzzer_isr, ticker_period/2.0f);
avi23 8:b2faec20ed8f 255 }
avi23 8:b2faec20ed8f 256
avi23 8:b2faec20ed8f 257 ///Clears the old bitmaps
avi23 5:34855f712350 258 ClearSmallInvaders();
avi23 5:34855f712350 259 ClearMediumInvaders();
avi23 5:34855f712350 260 ClearLargeInvaders();
avi23 5:34855f712350 261
avi23 5:34855f712350 262 MoveInvaderXPositions();
avi23 8:b2faec20ed8f 263 ///Switches the bitmap state
avi23 5:34855f712350 264 invaders_in_state2 = !invaders_in_state2;
avi23 5:34855f712350 265
avi23 8:b2faec20ed8f 266 ///Draws the invaders
avi23 5:34855f712350 267 DrawSmallInvaders();
avi23 5:34855f712350 268 DrawMediumInvaders();
avi23 5:34855f712350 269 DrawLargeInvaders();
avi23 5:34855f712350 270
avi23 8:b2faec20ed8f 271 ///Attempts to fire the invaders missiles
avi23 5:34855f712350 272 AttemptToFireInvaderNormalMissiles();
avi23 8:b2faec20ed8f 273
avi23 8:b2faec20ed8f 274 ///Attempts to spawn UFO
avi23 8:b2faec20ed8f 275 AttemptToSpawnUFO();
avi23 5:34855f712350 276 }
avi23 5:34855f712350 277
avi23 8:b2faec20ed8f 278 if (g_fire_buzzer_flag && !is_muted) {
avi23 8:b2faec20ed8f 279 g_fire_buzzer_flag = false;
avi23 8:b2faec20ed8f 280
avi23 9:cbb982b7e353 281 PlayBuzzer();
avi23 8:b2faec20ed8f 282 }
avi23 8:b2faec20ed8f 283
avi23 8:b2faec20ed8f 284 ///Spawns a player bullet if the shoot button is pressed and there isn't a bullet on the screen
avi23 5:34855f712350 285 if (g_shoot_pressed_flag) {
avi23 5:34855f712350 286 g_shoot_pressed_flag = false;
avi23 5:34855f712350 287
avi23 5:34855f712350 288 if (!cannon_missile_on_screen) {
avi23 5:34855f712350 289 FireCannonMissile();
avi23 8:b2faec20ed8f 290
avi23 8:b2faec20ed8f 291 ///Counts fired missiles to see if the ufo bonus can be applied
avi23 8:b2faec20ed8f 292 if (ufo_bonus && shot_count > 14) {
avi23 8:b2faec20ed8f 293 shot_count = 0;
avi23 8:b2faec20ed8f 294 } else if (shot_count > 22) {
avi23 8:b2faec20ed8f 295 shot_count = 0;
avi23 8:b2faec20ed8f 296 } else {
avi23 8:b2faec20ed8f 297 ++shot_count;
avi23 8:b2faec20ed8f 298 }
avi23 5:34855f712350 299 }
avi23 5:34855f712350 300 }
avi23 5:34855f712350 301
avi23 8:b2faec20ed8f 302 ///Move the cannon shot
avi23 5:34855f712350 303 if (g_move_cannon_missile_flag) {
avi23 5:34855f712350 304 g_move_cannon_missile_flag = false;
avi23 5:34855f712350 305
avi23 5:34855f712350 306 MoveCannonMissile();
avi23 5:34855f712350 307 }
avi23 5:34855f712350 308
avi23 8:b2faec20ed8f 309 ///Moves the invaders 1st normal missile
avi23 5:34855f712350 310 if (g_move_invader_normal_missile_flag[0]) {
avi23 5:34855f712350 311 g_move_invader_normal_missile_flag[0] = false;
avi23 5:34855f712350 312
avi23 5:34855f712350 313 MoveInvaderNormalMissile(0);
avi23 5:34855f712350 314 }
avi23 5:34855f712350 315
avi23 8:b2faec20ed8f 316 ///Moves the invaders 2nd normal missile
avi23 5:34855f712350 317 if (g_move_invader_normal_missile_flag[1]) {
avi23 5:34855f712350 318 g_move_invader_normal_missile_flag[1] = false;
avi23 5:34855f712350 319
avi23 5:34855f712350 320 MoveInvaderNormalMissile(1);
avi23 5:34855f712350 321 }
avi23 5:34855f712350 322
avi23 8:b2faec20ed8f 323 ///Moves the UFO
avi23 8:b2faec20ed8f 324 if (g_move_ufo_flag) {
avi23 8:b2faec20ed8f 325 g_move_ufo_flag = false;
avi23 8:b2faec20ed8f 326
avi23 8:b2faec20ed8f 327 ///Clears the UFO
avi23 8:b2faec20ed8f 328 ClearUFO();
avi23 8:b2faec20ed8f 329
avi23 8:b2faec20ed8f 330 ///Moves the UFO in the correct direction
avi23 8:b2faec20ed8f 331 if (ufo_direction == RIGHT) {
avi23 8:b2faec20ed8f 332 ufo_x_pos += 2;
avi23 8:b2faec20ed8f 333 } else {
avi23 8:b2faec20ed8f 334 ufo_x_pos -= 2;
avi23 8:b2faec20ed8f 335 }
avi23 8:b2faec20ed8f 336
avi23 8:b2faec20ed8f 337 ///Draws the UFO
avi23 8:b2faec20ed8f 338 DrawUFO();
avi23 8:b2faec20ed8f 339 }
avi23 8:b2faec20ed8f 340
avi23 5:34855f712350 341 if (joystick.get_button_flag()) {
avi23 5:34855f712350 342 joystick.set_button_flag(0);
avi23 5:34855f712350 343
avi23 9:cbb982b7e353 344 ///Detach all game tickers and turn off PWM
avi23 5:34855f712350 345 DetachTickers();
avi23 9:cbb982b7e353 346 buzzer.write(0.0);
avi23 5:34855f712350 347 game_state = paused;
avi23 5:34855f712350 348 }
avi23 5:34855f712350 349 }
avi23 5:34855f712350 350
avi23 5:34855f712350 351 sleep();
avi23 5:34855f712350 352 }
avi23 2:d34c95990605 353 }
avi23 2:d34c95990605 354
avi23 7:babc367a3333 355 void InitaliseGame()
avi23 7:babc367a3333 356 {
avi23 8:b2faec20ed8f 357 ///Clears the screen buffer and runs init functions
avi23 7:babc367a3333 358 memset(screen_buffer, 0, sizeof(screen_buffer));
avi23 7:babc367a3333 359 no_of_alive_invaders = 15;
avi23 7:babc367a3333 360 score = 0;
avi23 7:babc367a3333 361 number_of_lives = 3;
avi23 8:b2faec20ed8f 362 down_count = 0;
avi23 9:cbb982b7e353 363 cannon_xpos = 13;
avi23 9:cbb982b7e353 364 ufo_on_screen = false;
avi23 8:b2faec20ed8f 365 ufo_bonus = false;
avi23 8:b2faec20ed8f 366 shot_count = 0;
avi23 7:babc367a3333 367 InitSmallInvaders();
avi23 7:babc367a3333 368 InitMediumInvaders();
avi23 7:babc367a3333 369 InitLargeInvaders();
avi23 7:babc367a3333 370 InitBarriers();
avi23 8:b2faec20ed8f 371 ///If the sound is set activate the buzzer flag
avi23 8:b2faec20ed8f 372 if (!is_muted) {
avi23 8:b2faec20ed8f 373 g_fire_buzzer_flag = true;
avi23 8:b2faec20ed8f 374 }
avi23 8:b2faec20ed8f 375 ///Sets the flags so enemies pop up straight away
avi23 7:babc367a3333 376 g_update_screen_flag = true;
avi23 7:babc367a3333 377 g_move_joystick_flag = true;
avi23 7:babc367a3333 378 g_move_enemies_flag = true;
avi23 8:b2faec20ed8f 379 g_fire_buzzer_flag = true;
avi23 8:b2faec20ed8f 380 ///Forces the missiles to have the fired flags to flase
avi23 7:babc367a3333 381 cannon_missile_on_screen = false;
avi23 7:babc367a3333 382 invader_normal_missile[0].fired = false;
avi23 7:babc367a3333 383 invader_normal_missile[1].fired = false;
avi23 7:babc367a3333 384 }
avi23 7:babc367a3333 385
avi23 5:34855f712350 386 void UpdateScreen()
avi23 2:d34c95990605 387 {
avi23 8:b2faec20ed8f 388 ///Loops through the screen buffer and sets pixels on the LCD
avi23 5:34855f712350 389 for (int col = 0; col < 84; ++col) {
avi23 5:34855f712350 390 for (int row = 0; row < 48; ++row) {
avi23 5:34855f712350 391 if (screen_buffer[col][row]) {
avi23 5:34855f712350 392 lcd.setPixel(col, row);
avi23 5:34855f712350 393 } else {
avi23 5:34855f712350 394 lcd.clearPixel(col, row);
avi23 5:34855f712350 395 }
avi23 5:34855f712350 396 }
avi23 5:34855f712350 397 }
avi23 5:34855f712350 398
avi23 5:34855f712350 399 lcd.refresh();
avi23 2:d34c95990605 400 }
avi23 2:d34c95990605 401
avi23 2:d34c95990605 402 void MoveCannon()
avi23 0:427469992efe 403 {
avi23 8:b2faec20ed8f 404 ///Clears the cannon
avi23 5:34855f712350 405 for (int col = 0; col < 9; ++col) {
avi23 5:34855f712350 406 for (int row = 0; row < 5; ++row) {
avi23 1:b300d052d549 407 if(cannon_bitmap[row][col]) {
avi23 5:34855f712350 408 screen_buffer[cannon_xpos+col][cannon_ypos+row] = empty_pixel;
avi23 0:427469992efe 409 }
avi23 0:427469992efe 410 }
avi23 0:427469992efe 411 }
avi23 0:427469992efe 412
avi23 8:b2faec20ed8f 413 ///Changes the position of the cannon when the joystick is moved, capping at 0 and 75 so it always fits on the screen
avi23 0:427469992efe 414 if (joystick.GetXValue() < 0.25f) {
avi23 1:b300d052d549 415 cannon_xpos--;
avi23 1:b300d052d549 416 if (cannon_xpos < 0) {
avi23 1:b300d052d549 417 cannon_xpos = 0;
avi23 0:427469992efe 418 }
avi23 0:427469992efe 419 } else if (joystick.GetXValue() > 0.75f) {
avi23 1:b300d052d549 420 cannon_xpos++;
avi23 1:b300d052d549 421 if (cannon_xpos > 75) {
avi23 1:b300d052d549 422 cannon_xpos = 75;
avi23 0:427469992efe 423 }
avi23 0:427469992efe 424 }
avi23 0:427469992efe 425
avi23 8:b2faec20ed8f 426 ///Redraws the cannon
avi23 5:34855f712350 427 for (int col = 0; col < 9; ++col) {
avi23 5:34855f712350 428 for (int row = 0; row < 5; ++row) {
avi23 1:b300d052d549 429 if(cannon_bitmap[row][col]) {
avi23 5:34855f712350 430 screen_buffer[cannon_xpos+col][cannon_ypos+row] = cannon_pixel;
avi23 0:427469992efe 431 }
avi23 0:427469992efe 432 }
avi23 0:427469992efe 433 }
avi23 0:427469992efe 434 }
avi23 0:427469992efe 435
avi23 8:b2faec20ed8f 436 ///Sets the position and status of the small invaders
avi23 0:427469992efe 437 void InitSmallInvaders()
avi23 0:427469992efe 438 {
avi23 5:34855f712350 439 for (int i = 0; i < 5; ++i) {
avi23 8:b2faec20ed8f 440 small_invader[i].x_pos = 2 + (i*13); /// Large invaders are 12 across so add 13 for a gap space
avi23 2:d34c95990605 441 small_invader[i].y_pos = 1;
avi23 5:34855f712350 442 small_invader[i].status = alive;
avi23 0:427469992efe 443 }
avi23 0:427469992efe 444 }
avi23 0:427469992efe 445
avi23 8:b2faec20ed8f 446 ///Cycles through all the small invaders. If they're not already dead clear them
avi23 2:d34c95990605 447 void ClearSmallInvaders()
avi23 2:d34c95990605 448 {
avi23 5:34855f712350 449 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 450 if (small_invader[i].status) {
avi23 5:34855f712350 451 ClearSingleSmallInvader(i);
avi23 5:34855f712350 452 }
avi23 5:34855f712350 453 }
avi23 5:34855f712350 454 }
avi23 5:34855f712350 455
avi23 8:b2faec20ed8f 456 ///Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0
avi23 5:34855f712350 457 void ClearSingleSmallInvader(int invader_no)
avi23 5:34855f712350 458 {
avi23 5:34855f712350 459 for (int col = 0; col < 8; ++col) {
avi23 5:34855f712350 460 for (int row = 0; row < 6; ++row) {
avi23 5:34855f712350 461 if (invaders_in_state2) {
avi23 5:34855f712350 462 if (small_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 463 screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel;
avi23 2:d34c95990605 464 }
avi23 5:34855f712350 465 } else {
avi23 5:34855f712350 466 if (small_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 467 screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel;
avi23 2:d34c95990605 468 }
avi23 2:d34c95990605 469 }
avi23 2:d34c95990605 470 }
avi23 2:d34c95990605 471 }
avi23 5:34855f712350 472
avi23 5:34855f712350 473 small_invader[invader_no].status = (small_invader[invader_no].status == dying) ? dead : alive;
avi23 2:d34c95990605 474 }
avi23 2:d34c95990605 475
avi23 8:b2faec20ed8f 476 ///Cycles through all the small invaders. If they're alive set them in the screen buffer
avi23 0:427469992efe 477 void DrawSmallInvaders()
avi23 0:427469992efe 478 {
avi23 5:34855f712350 479 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 480 if (small_invader[i].status == alive) {
avi23 5:34855f712350 481 DrawSingleSmallInvader(i);
avi23 5:34855f712350 482 }
avi23 5:34855f712350 483 }
avi23 5:34855f712350 484 }
avi23 5:34855f712350 485
avi23 8:b2faec20ed8f 486 ///Cycles through the the screen invader bitmap and sets the pixels in the buffer
avi23 5:34855f712350 487 void DrawSingleSmallInvader(int invader_no)
avi23 5:34855f712350 488 {
avi23 5:34855f712350 489 for (int col = 0; col < 8; ++col) {
avi23 5:34855f712350 490 for (int row = 0; row < 6; ++row) {
avi23 2:d34c95990605 491 if (invaders_in_state2) {
avi23 5:34855f712350 492 if (small_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 493 screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = first_small_invader_pixel + invader_no;
avi23 0:427469992efe 494 }
avi23 0:427469992efe 495 } else {
avi23 5:34855f712350 496 if (small_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 497 screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = first_small_invader_pixel + invader_no;
avi23 0:427469992efe 498 }
avi23 0:427469992efe 499 }
avi23 0:427469992efe 500 }
avi23 0:427469992efe 501 }
avi23 1:b300d052d549 502 }
avi23 1:b300d052d549 503
avi23 8:b2faec20ed8f 504 ///Sets the position and aliveness of the medium invaders
avi23 1:b300d052d549 505 void InitMediumInvaders()
avi23 1:b300d052d549 506 {
avi23 5:34855f712350 507 for (int i = 0; i < 5; ++i) {
avi23 8:b2faec20ed8f 508 medium_invader[i].x_pos = 1 + (i*13); /// Large invaders are 12 across so add 13 for a gap space
avi23 2:d34c95990605 509 medium_invader[i].y_pos = 8;
avi23 5:34855f712350 510 medium_invader[i].status = alive;
avi23 1:b300d052d549 511 }
avi23 1:b300d052d549 512 }
avi23 1:b300d052d549 513
avi23 8:b2faec20ed8f 514 ///Cycles through all the medium invaders. If they're not already dead clear them
avi23 2:d34c95990605 515 void ClearMediumInvaders()
avi23 2:d34c95990605 516 {
avi23 5:34855f712350 517 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 518 if (medium_invader[i].status) {
avi23 5:34855f712350 519 ClearSingleMediumInvader(i);
avi23 2:d34c95990605 520 }
avi23 2:d34c95990605 521 }
avi23 2:d34c95990605 522 }
avi23 2:d34c95990605 523
avi23 8:b2faec20ed8f 524 ///Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0
avi23 5:34855f712350 525 void ClearSingleMediumInvader(int invader_no)
avi23 5:34855f712350 526 {
avi23 5:34855f712350 527 for (int col = 0; col < 10; ++col) {
avi23 5:34855f712350 528 for (int row = 0; row < 6; ++row) {
avi23 5:34855f712350 529 if (invaders_in_state2) {
avi23 5:34855f712350 530 if (medium_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 531 screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel;
avi23 5:34855f712350 532 }
avi23 5:34855f712350 533 } else {
avi23 5:34855f712350 534 if (medium_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 535 screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel;
avi23 5:34855f712350 536 }
avi23 5:34855f712350 537 }
avi23 5:34855f712350 538 }
avi23 5:34855f712350 539 }
avi23 5:34855f712350 540
avi23 5:34855f712350 541 medium_invader[invader_no].status = (medium_invader[invader_no].status == dying) ? dead : alive;
avi23 5:34855f712350 542 }
avi23 5:34855f712350 543
avi23 8:b2faec20ed8f 544 ///Cycles through all the medium invaders. If they're alive set them in the screen buffer
avi23 1:b300d052d549 545 void DrawMediumInvaders()
avi23 1:b300d052d549 546 {
avi23 5:34855f712350 547 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 548 if (medium_invader[i].status == alive) {
avi23 5:34855f712350 549 DrawSingleMediumInvader(i);
avi23 5:34855f712350 550 }
avi23 5:34855f712350 551 }
avi23 5:34855f712350 552 }
avi23 5:34855f712350 553
avi23 8:b2faec20ed8f 554 ///Cycles through the the screen invader bitmap and sets the pixels in the buffer
avi23 5:34855f712350 555 void DrawSingleMediumInvader(int invader_no)
avi23 5:34855f712350 556 {
avi23 5:34855f712350 557 for (int col = 0; col < 10; ++col) {
avi23 5:34855f712350 558 for (int row = 0; row < 6; ++row) {
avi23 2:d34c95990605 559 if (invaders_in_state2) {
avi23 5:34855f712350 560 if (medium_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 561 screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = first_medium_invader_pixel + invader_no;
avi23 1:b300d052d549 562 }
avi23 1:b300d052d549 563 } else {
avi23 5:34855f712350 564 if (medium_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 565 screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = first_medium_invader_pixel + invader_no;
avi23 1:b300d052d549 566 }
avi23 1:b300d052d549 567 }
avi23 1:b300d052d549 568 }
avi23 1:b300d052d549 569 }
avi23 1:b300d052d549 570 }
avi23 1:b300d052d549 571
avi23 8:b2faec20ed8f 572 ///Sets the position and status of the large invaders
avi23 1:b300d052d549 573 void InitLargeInvaders()
avi23 1:b300d052d549 574 {
avi23 5:34855f712350 575 for (int i = 0; i < 5; ++i) {
avi23 1:b300d052d549 576 large_invader[i].x_pos = 0 + (i*13);
avi23 2:d34c95990605 577 large_invader[i].y_pos = 15;
avi23 5:34855f712350 578 large_invader[i].status = alive;
avi23 5:34855f712350 579 }
avi23 5:34855f712350 580 }
avi23 5:34855f712350 581
avi23 8:b2faec20ed8f 582 ///Cycles through all the large invaders. If they're not already dead clear them
avi23 5:34855f712350 583 void ClearLargeInvaders()
avi23 5:34855f712350 584 {
avi23 5:34855f712350 585 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 586 if (large_invader[i].status) {
avi23 5:34855f712350 587 ClearSingleLargeInvader(i);
avi23 5:34855f712350 588 }
avi23 1:b300d052d549 589 }
avi23 1:b300d052d549 590 }
avi23 1:b300d052d549 591
avi23 8:b2faec20ed8f 592 ///Loops through the large invader bitmap, if the pixel in the bitmap is set to 1, set the pixel in the buffer to 0
avi23 5:34855f712350 593 void ClearSingleLargeInvader(int invader_no)
avi23 2:d34c95990605 594 {
avi23 5:34855f712350 595 for (int col = 0; col < 12; ++col) {
avi23 5:34855f712350 596 for (int row = 0; row < 6; ++row) {
avi23 5:34855f712350 597 if (invaders_in_state2) {
avi23 5:34855f712350 598 if (large_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 599 screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel;
avi23 5:34855f712350 600 }
avi23 5:34855f712350 601 } else {
avi23 5:34855f712350 602 if (large_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 603 screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel;
avi23 2:d34c95990605 604 }
avi23 2:d34c95990605 605 }
avi23 5:34855f712350 606 }
avi23 5:34855f712350 607 }
avi23 5:34855f712350 608
avi23 5:34855f712350 609 large_invader[invader_no].status = (large_invader[invader_no].status == dying) ? dead : alive;
avi23 5:34855f712350 610 }
avi23 5:34855f712350 611
avi23 8:b2faec20ed8f 612 ///Cycles through all the large invaders. If they're alive set them in the screen buffer
avi23 5:34855f712350 613 void DrawLargeInvaders()
avi23 5:34855f712350 614 {
avi23 5:34855f712350 615 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 616 if (large_invader[i].status == alive) {
avi23 5:34855f712350 617 DrawSingleLargeInvader(i);
avi23 5:34855f712350 618 }
avi23 5:34855f712350 619 }
avi23 5:34855f712350 620 }
avi23 5:34855f712350 621
avi23 8:b2faec20ed8f 622 ///Cycles through the the screen invader bitmap and sets the pixels in the buffer
avi23 5:34855f712350 623 void DrawSingleLargeInvader(int invader_no)
avi23 5:34855f712350 624 {
avi23 5:34855f712350 625 for (int col = 0; col < 12; ++col) {
avi23 5:34855f712350 626 for (int row = 0; row < 6; ++row) {
avi23 5:34855f712350 627 if (invaders_in_state2) {
avi23 5:34855f712350 628 if (large_invader_bitmap_1[row][col]) {
avi23 5:34855f712350 629 screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = first_large_invader_pixel + invader_no;
avi23 5:34855f712350 630 }
avi23 5:34855f712350 631 } else {
avi23 5:34855f712350 632 if (large_invader_bitmap_2[row][col]) {
avi23 5:34855f712350 633 screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = first_large_invader_pixel + invader_no;
avi23 2:d34c95990605 634 }
avi23 2:d34c95990605 635 }
avi23 2:d34c95990605 636 }
avi23 2:d34c95990605 637 }
avi23 2:d34c95990605 638 }
avi23 2:d34c95990605 639
avi23 8:b2faec20ed8f 640 ///Sets the position and loads the bitmap into the barrier objects
avi23 2:d34c95990605 641 void InitBarriers()
avi23 2:d34c95990605 642 {
avi23 5:34855f712350 643 for (int i = 0; i < 3; ++i) {
avi23 2:d34c95990605 644 barrier[i].x_pos = 10 + (i*25);
avi23 2:d34c95990605 645 barrier[i].y_pos = 33;
avi23 8:b2faec20ed8f 646 ///Copies the bitmap into the structs
avi23 2:d34c95990605 647 memcpy(barrier[i].before_bitmap, barrier_bitmap, sizeof(barrier_bitmap));
avi23 2:d34c95990605 648 memcpy(barrier[i].after_bitmap, barrier_bitmap, sizeof(barrier_bitmap));
avi23 2:d34c95990605 649 }
avi23 2:d34c95990605 650 }
avi23 2:d34c95990605 651
avi23 2:d34c95990605 652 void DrawBarriers()
avi23 2:d34c95990605 653 {
avi23 8:b2faec20ed8f 654 ///Clears the barrier and redraws it with damage applied
avi23 5:34855f712350 655 for (int i = 0; i < 3; ++i) {
avi23 5:34855f712350 656 for (int col = 0; col < 14; ++col) {
avi23 5:34855f712350 657 for (int row = 0; row < 8; ++row) {
avi23 2:d34c95990605 658 if (barrier[i].before_bitmap[row][col]) {
avi23 5:34855f712350 659 screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = empty_pixel;
avi23 2:d34c95990605 660 }
avi23 2:d34c95990605 661 if (barrier[i].after_bitmap[row][col]) {
avi23 5:34855f712350 662 screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = first_barrier_pixel + i;
avi23 2:d34c95990605 663 }
avi23 2:d34c95990605 664 }
avi23 2:d34c95990605 665 }
avi23 8:b2faec20ed8f 666 ///Copies the after array to the before array
avi23 2:d34c95990605 667 memcpy(barrier[i].before_bitmap, barrier[i].after_bitmap, sizeof(barrier[i].after_bitmap));
avi23 2:d34c95990605 668 }
avi23 2:d34c95990605 669 }
avi23 2:d34c95990605 670
avi23 5:34855f712350 671 void MoveInvaderXPositions()
avi23 2:d34c95990605 672 {
avi23 8:b2faec20ed8f 673 ///Moves the invader in the current direction
avi23 2:d34c95990605 674 if (invader_direction == RIGHT) {
avi23 8:b2faec20ed8f 675 ///Checking the right limit
avi23 7:babc367a3333 676 int right_invader_limit = CalculateInvaderRightLimit();
avi23 5:34855f712350 677 MoveInvadersRight(right_invader_limit);
avi23 5:34855f712350 678 } else {
avi23 8:b2faec20ed8f 679 ///Checks the left limit
avi23 7:babc367a3333 680 int left_invader_limit = CalculateInvaderLeftLimit();
avi23 5:34855f712350 681 MoveInvadersLeft(left_invader_limit);
avi23 5:34855f712350 682 }
avi23 5:34855f712350 683 }
avi23 5:34855f712350 684
avi23 8:b2faec20ed8f 685 ///Checks the status off the invaders per column, starting from the left
avi23 8:b2faec20ed8f 686 ///If they're alive return the row number
avi23 5:34855f712350 687 int CalculateInvaderLeftLimit()
avi23 5:34855f712350 688 {
avi23 5:34855f712350 689 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 690 if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) {
avi23 5:34855f712350 691 return i;
avi23 5:34855f712350 692 }
avi23 5:34855f712350 693 }
avi23 5:34855f712350 694
avi23 8:b2faec20ed8f 695 ///Sort gameover out stuff after
avi23 5:34855f712350 696 return 4;
avi23 5:34855f712350 697 }
avi23 5:34855f712350 698
avi23 8:b2faec20ed8f 699 ///Checks the status off the invaders per column, starting from the right
avi23 8:b2faec20ed8f 700 ///If they're alive return the row number
avi23 5:34855f712350 701 int CalculateInvaderRightLimit()
avi23 5:34855f712350 702 {
avi23 5:34855f712350 703 for (int i = 4; i >= 0; --i) {
avi23 5:34855f712350 704 if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) {
avi23 5:34855f712350 705 return i;
avi23 5:34855f712350 706 }
avi23 5:34855f712350 707 }
avi23 5:34855f712350 708
avi23 8:b2faec20ed8f 709 ///Sort gameover stuff
avi23 5:34855f712350 710 return 0;
avi23 5:34855f712350 711 }
avi23 5:34855f712350 712
avi23 5:34855f712350 713 void MoveInvadersLeft(int limit)
avi23 5:34855f712350 714 {
avi23 8:b2faec20ed8f 715 ///Checks the first large invader to see if it can travel anymore
avi23 5:34855f712350 716 if (large_invader[limit].x_pos > 1) {
avi23 5:34855f712350 717 for (int i = 0; i < 5; ++i) {
avi23 8:b2faec20ed8f 718 ///Moves the invaders 2 to the left
avi23 5:34855f712350 719 small_invader[i].x_pos -= 2;
avi23 5:34855f712350 720 medium_invader[i].x_pos -= 2;
avi23 5:34855f712350 721 large_invader[i].x_pos -= 2;
avi23 2:d34c95990605 722 }
avi23 2:d34c95990605 723 } else {
avi23 8:b2faec20ed8f 724 ///Shifts the Invaders down and passes in the new direction
avi23 5:34855f712350 725 MoveInvaderYPositions(RIGHT);
avi23 2:d34c95990605 726 }
avi23 2:d34c95990605 727 }
avi23 2:d34c95990605 728
avi23 5:34855f712350 729 void MoveInvadersRight(int limit)
avi23 2:d34c95990605 730 {
avi23 8:b2faec20ed8f 731 ///Checks the first large invader to see if it can travel anymore
avi23 5:34855f712350 732 if (large_invader[limit].x_pos < 71) {
avi23 8:b2faec20ed8f 733 ///Moves the invaders 2 to the right
avi23 5:34855f712350 734 for (int i = 0; i < 5; ++i) {
avi23 5:34855f712350 735 small_invader[i].x_pos += 2;
avi23 5:34855f712350 736 medium_invader[i].x_pos += 2;
avi23 5:34855f712350 737 large_invader[i].x_pos += 2;
avi23 5:34855f712350 738 }
avi23 2:d34c95990605 739 } else {
avi23 8:b2faec20ed8f 740 ///Shifts the Invaders down and passes in the new direction
avi23 5:34855f712350 741 MoveInvaderYPositions(LEFT);
avi23 2:d34c95990605 742 }
avi23 5:34855f712350 743 }
avi23 5:34855f712350 744
avi23 5:34855f712350 745 void MoveInvaderYPositions(bool new_direction)
avi23 5:34855f712350 746 {
avi23 8:b2faec20ed8f 747 ///Finds the invaders lower limit
avi23 5:34855f712350 748 Invader lowest_invader = CalculateInvaderYLimit();
avi23 5:34855f712350 749
avi23 8:b2faec20ed8f 750 ///When moving down lowest_invader should not equal none
avi23 5:34855f712350 751 if (lowest_invader == none) {
avi23 5:34855f712350 752 error();
avi23 5:34855f712350 753 }
avi23 5:34855f712350 754
avi23 8:b2faec20ed8f 755 ///If an invader touches the bottom the game ends, otherwise the invaders descend
avi23 5:34855f712350 756 if (small_invader[0].y_pos < 33 - (7*lowest_invader)) {
avi23 5:34855f712350 757 for (int i = 0; i < 5; ++i) {
avi23 2:d34c95990605 758 small_invader[i].y_pos += 3;
avi23 2:d34c95990605 759 medium_invader[i].y_pos += 3;
avi23 2:d34c95990605 760 large_invader[i].y_pos += 3;
avi23 2:d34c95990605 761 }
avi23 8:b2faec20ed8f 762 ++down_count;
avi23 5:34855f712350 763 invader_direction = new_direction;
avi23 5:34855f712350 764 } else {
avi23 5:34855f712350 765 number_of_lives = 0;
avi23 5:34855f712350 766 }
avi23 5:34855f712350 767 }
avi23 5:34855f712350 768
avi23 5:34855f712350 769 Invader CalculateInvaderYLimit()
avi23 5:34855f712350 770 {
avi23 8:b2faec20ed8f 771 ///Checks to see which row of invaders are still alive to work out maximum y positions
avi23 5:34855f712350 772 if (large_invader[0].status == alive || large_invader[1].status == alive || large_invader[2].status == alive || large_invader[3].status == alive || large_invader[4].status == alive) {
avi23 5:34855f712350 773 return large;
avi23 5:34855f712350 774 } else if (medium_invader[0].status == alive || medium_invader[1].status == alive || medium_invader[2].status == alive || medium_invader[3].status == alive || medium_invader[4].status == alive) {
avi23 5:34855f712350 775 return medium;
avi23 2:d34c95990605 776 } else {
avi23 5:34855f712350 777 return small;
avi23 2:d34c95990605 778 }
avi23 5:34855f712350 779 }
avi23 2:d34c95990605 780
avi23 8:b2faec20ed8f 781 ///Queries the invaders on their status and returns the type of invader which is alive
avi23 5:34855f712350 782 Invader LowestInvaderInColumn(int column)
avi23 5:34855f712350 783 {
avi23 5:34855f712350 784 if (large_invader[column].status == alive) {
avi23 5:34855f712350 785 return large;
avi23 5:34855f712350 786 } else if (medium_invader[column].status == alive) {
avi23 5:34855f712350 787 return medium;
avi23 5:34855f712350 788 } else if (small_invader[column].status == alive) {
avi23 5:34855f712350 789 return small;
avi23 5:34855f712350 790 } else {
avi23 5:34855f712350 791 return none;
avi23 5:34855f712350 792 }
avi23 2:d34c95990605 793 }
avi23 2:d34c95990605 794
avi23 5:34855f712350 795 void FireCannonMissile()
avi23 5:34855f712350 796 {
avi23 8:b2faec20ed8f 797 ///Sets the cannon fired flag to true
avi23 5:34855f712350 798 cannon_missile_on_screen = true;
avi23 5:34855f712350 799
avi23 8:b2faec20ed8f 800 ///Offset cannon missile x position by 4 of the cannons x pos
avi23 5:34855f712350 801 cannon_missile_x_pos = cannon_xpos + 4;
avi23 8:b2faec20ed8f 802 ///Will always have a starting y of 40
avi23 5:34855f712350 803 cannon_missile_y_pos = 40;
avi23 8:b2faec20ed8f 804 ///Attach the move cannon missile
avi23 5:34855f712350 805 move_cannon_missile.attach(&move_cannon_missile_isr, 0.05);
avi23 5:34855f712350 806 }
avi23 5:34855f712350 807
avi23 5:34855f712350 808 void MoveCannonMissile()
avi23 5:34855f712350 809 {
avi23 8:b2faec20ed8f 810 ///Checks bullet will not go beyond the bounds of the screen buffer
avi23 5:34855f712350 811 if (cannon_missile_y_pos > -1) {
avi23 8:b2faec20ed8f 812 ///Loops throught the shot bitmap and clears the pixels in the screen buffer
avi23 5:34855f712350 813 for (int row = 0; row < 4; ++row) {
avi23 8:b2faec20ed8f 814 ///Clears the position where the bullet was
avi23 5:34855f712350 815 screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel;
avi23 5:34855f712350 816 }
avi23 5:34855f712350 817
avi23 8:b2faec20ed8f 818 ///Increments the shot going up the screen
avi23 5:34855f712350 819 --cannon_missile_y_pos;
avi23 5:34855f712350 820
avi23 8:b2faec20ed8f 821 ///Checks to see if the shot will hit anything
avi23 5:34855f712350 822 CollisionDetectionCannonMissile();
avi23 5:34855f712350 823 } else {
avi23 8:b2faec20ed8f 824 ///Loops throught the shot bitmap and clears the pixels in the screen buffer
avi23 5:34855f712350 825 for (int row = 1; row < 4; ++row) {
avi23 8:b2faec20ed8f 826 ///Clears the position where the bullet was
avi23 5:34855f712350 827 screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel;
avi23 5:34855f712350 828 }
avi23 5:34855f712350 829
avi23 5:34855f712350 830 cannon_missile_on_screen = false;
avi23 5:34855f712350 831 move_cannon_missile.detach();
avi23 5:34855f712350 832 }
avi23 5:34855f712350 833 }
avi23 5:34855f712350 834
avi23 8:b2faec20ed8f 835 ///Checks to see what the shot hits. If it hits nothing the shot gets pushed to the screen buffer
avi23 5:34855f712350 836 void CollisionDetectionCannonMissile()
avi23 5:34855f712350 837 {
avi23 5:34855f712350 838 for (int row = 0; row < 4; ++row) {
avi23 5:34855f712350 839 int object_no;
avi23 7:babc367a3333 840 int pixel_check = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row];
avi23 8:b2faec20ed8f 841 if (pixel_check >= first_small_invader_pixel && pixel_check < ufo_pixel) { ///Collides with a small invader
avi23 8:b2faec20ed8f 842 ///Find the object no of the small invader it hit, clears it and increments the score
avi23 5:34855f712350 843 object_no = CannonMissileHitInvader(first_small_invader_pixel, row, small_invader);
avi23 5:34855f712350 844 ClearSingleSmallInvader(object_no);
avi23 5:34855f712350 845 score += 40;
avi23 5:34855f712350 846 break;
avi23 8:b2faec20ed8f 847 } else if (pixel_check >= first_medium_invader_pixel && pixel_check < first_small_invader_pixel) { ///Collides with a medium invader
avi23 8:b2faec20ed8f 848 ///Find the object no of the medium invader it hit, clears it and increments the score
avi23 5:34855f712350 849 object_no = CannonMissileHitInvader(first_medium_invader_pixel, row, medium_invader);
avi23 5:34855f712350 850 ClearSingleMediumInvader(object_no);
avi23 5:34855f712350 851 score += 20;
avi23 5:34855f712350 852 break;
avi23 8:b2faec20ed8f 853 } else if (pixel_check >= first_large_invader_pixel && pixel_check < first_medium_invader_pixel) { ///Collides with a large invader
avi23 8:b2faec20ed8f 854 ///Find the object no of the large invader it hit, clears it and increments the score
avi23 5:34855f712350 855 object_no = CannonMissileHitInvader(first_large_invader_pixel, row, large_invader);
avi23 5:34855f712350 856 ClearSingleLargeInvader(object_no);
avi23 5:34855f712350 857 score += 10;
avi23 5:34855f712350 858 break;
avi23 8:b2faec20ed8f 859 } else if (pixel_check >= first_barrier_pixel && pixel_check < (first_barrier_pixel + 3)) { ///Collides with a barrier
avi23 8:b2faec20ed8f 860 ///Adds the destruction done to the barrier to the bitmap and redraws the barriers
avi23 7:babc367a3333 861 CannonMissileHitBarrier(row);
avi23 5:34855f712350 862 DrawBarriers();
avi23 5:34855f712350 863 break;
avi23 8:b2faec20ed8f 864 } else if (pixel_check == ufo_pixel) { ///Collides with a UFO
avi23 8:b2faec20ed8f 865 ///Clears the UFO, calculates score depending on the ufo bonus
avi23 8:b2faec20ed8f 866 ClearUFO();
avi23 8:b2faec20ed8f 867 ufo_on_screen = false;
avi23 8:b2faec20ed8f 868 move_ufo.detach();
avi23 8:b2faec20ed8f 869 if (ufo_bonus && shot_count == 15) { ///If the shot bonus is active and on the 15th shot, give 300 points
avi23 8:b2faec20ed8f 870 score += 300;
avi23 8:b2faec20ed8f 871 } else if (shot_count == 23) { ///If the shot bonus isn't active and on the 23rd shot, give 300 points and activate the bonus
avi23 9:cbb982b7e353 872 ufo_bonus = true;
avi23 9:cbb982b7e353 873 score += 300;
avi23 8:b2faec20ed8f 874 } else { ///Randomly assign score between 50, 100, 150 points
avi23 8:b2faec20ed8f 875 score += 50 * ((rand() % 3) + 1);
avi23 8:b2faec20ed8f 876 }
avi23 5:34855f712350 877 cannon_missile_on_screen = false;
avi23 5:34855f712350 878 move_cannon_missile.detach();
avi23 5:34855f712350 879 break;
avi23 5:34855f712350 880 } else {
avi23 5:34855f712350 881 screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = cannon_missile_pixel;
avi23 5:34855f712350 882 }
avi23 5:34855f712350 883 }
avi23 5:34855f712350 884 }
avi23 5:34855f712350 885
avi23 8:b2faec20ed8f 886 ///Finds the invader number the missile hits, sets the hit invader to dying, decrements the no_of_alive_invaders and stops the shot from travalling up the screen
avi23 5:34855f712350 887 int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5])
avi23 5:34855f712350 888 {
avi23 5:34855f712350 889 int invader_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel;
avi23 5:34855f712350 890 invader[invader_no].status = dying;
avi23 5:34855f712350 891 cannon_missile_on_screen = false;
avi23 5:34855f712350 892 --no_of_alive_invaders;
avi23 5:34855f712350 893 move_cannon_missile.detach();
avi23 5:34855f712350 894
avi23 5:34855f712350 895 return invader_no;
avi23 5:34855f712350 896 }
avi23 5:34855f712350 897
avi23 8:b2faec20ed8f 898 ///Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation
avi23 7:babc367a3333 899 void CannonMissileHitBarrier(int row)
avi23 5:34855f712350 900 {
avi23 7:babc367a3333 901 int barrier_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_barrier_pixel;
avi23 8:b2faec20ed8f 902 ///Essentially inverse of barrier init
avi23 5:34855f712350 903 int relative_x_pos = cannon_missile_x_pos - 10 - (barrier_no*25) - 1;
avi23 8:b2faec20ed8f 904 int relative_y_pos = (cannon_missile_y_pos + row) - 33 - 1; ///Don't know why it's -1 and not -2
avi23 8:b2faec20ed8f 905 ///Loops through the damage bitmap and modifies the barrier's after bitmap
avi23 5:34855f712350 906 for (int col = 0; col < 3; ++col) {
avi23 5:34855f712350 907 for (int row_bit = 0; row_bit < 3; ++row_bit) {
avi23 8:b2faec20ed8f 908 ///Makes sure bitmap index does not go out of bounds. If it does go to the next iteration
avi23 8:b2faec20ed8f 909 ///Element by element multiplication of the 2 bitmaps to clear the required pixals
avi23 5:34855f712350 910 if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) {
avi23 5:34855f712350 911 barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_cannon_missile_damage_bitmap[row_bit][col];
avi23 5:34855f712350 912 }
avi23 5:34855f712350 913 }
avi23 5:34855f712350 914 }
avi23 5:34855f712350 915 cannon_missile_on_screen = false;
avi23 5:34855f712350 916 move_cannon_missile.detach();
avi23 5:34855f712350 917 }
avi23 5:34855f712350 918
avi23 5:34855f712350 919 void AttemptToFireInvaderNormalMissiles()
avi23 5:34855f712350 920 {
avi23 8:b2faec20ed8f 921 ///Fires the normal missiles
avi23 8:b2faec20ed8f 922 ///Loops through the 2 allowed missiles and if they're not on the screen, randomly fire
avi23 5:34855f712350 923 for (int i = 0; i < 2; ++i) {
avi23 5:34855f712350 924 if (!invader_normal_missile[i].fired) {
avi23 8:b2faec20ed8f 925 ///If the random mumber is 1, fire a missile
avi23 8:b2faec20ed8f 926 ///Higher chance when there are less invaders on the screen, up to a 1/3 chance
avi23 5:34855f712350 927 if ((rand() % (no_of_alive_invaders + 2)) == 1) {
avi23 5:34855f712350 928 int fired_column;
avi23 8:b2faec20ed8f 929 int loop_limit = 0; ///Stops loop from never ending
avi23 5:34855f712350 930 Invader missile_source;
avi23 5:34855f712350 931 do {
avi23 5:34855f712350 932 fired_column = rand() % 5;
avi23 5:34855f712350 933 missile_source = LowestInvaderInColumn(fired_column);
avi23 5:34855f712350 934 ++loop_limit;
avi23 5:34855f712350 935 } while (missile_source == none && loop_limit < 10);
avi23 5:34855f712350 936
avi23 8:b2faec20ed8f 937 ///Finds the centre point of the chosen invader and fires the missile
avi23 8:b2faec20ed8f 938 ///If the loop limit is reached, the missile source will be none and the for loop will jump to the next iteration
avi23 5:34855f712350 939 if (missile_source == none) {
avi23 5:34855f712350 940 continue;
avi23 5:34855f712350 941 } else if (missile_source == large) {
avi23 5:34855f712350 942 FireNormalInvaderMissile(i, missile_source, large_invader[fired_column]);
avi23 5:34855f712350 943 } else if (missile_source == medium) {
avi23 5:34855f712350 944 FireNormalInvaderMissile(i, missile_source, medium_invader[fired_column]);
avi23 5:34855f712350 945 } else {
avi23 5:34855f712350 946 FireNormalInvaderMissile(i, missile_source, small_invader[fired_column]);
avi23 5:34855f712350 947 }
avi23 5:34855f712350 948 }
avi23 5:34855f712350 949 }
avi23 5:34855f712350 950 }
avi23 5:34855f712350 951 }
avi23 5:34855f712350 952
avi23 5:34855f712350 953 void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader))
avi23 5:34855f712350 954 {
avi23 8:b2faec20ed8f 955 ///Finds the centre point of the chosen invader and fires the missile
avi23 8:b2faec20ed8f 956 ///Enums are implicity converted to ints --> the middle x position of the invader found by offsetting the invader type by 3
avi23 5:34855f712350 957 invader_normal_missile[missile_no].x_pos = invader.x_pos + (3 + source);
avi23 5:34855f712350 958 invader_normal_missile[missile_no].y_pos = invader.y_pos + 6;
avi23 5:34855f712350 959 invader_normal_missile[missile_no].fired = true;
avi23 5:34855f712350 960
avi23 8:b2faec20ed8f 961 ///Uses a function pointer to attach the ticker
avi23 5:34855f712350 962 move_invader_normal_missile[missile_no].attach(move_invader_normal_missile_isr[missile_no], 0.05);
avi23 5:34855f712350 963 }
avi23 5:34855f712350 964
avi23 7:babc367a3333 965 void MoveInvaderNormalMissile(int missile_no)
avi23 7:babc367a3333 966 {
avi23 8:b2faec20ed8f 967 ///Loops through the bitmap and clears the missile from the screen buffer
avi23 7:babc367a3333 968 for (int col = 0; col < 3; ++col) {
avi23 7:babc367a3333 969 for (int row = 0; row < 4; ++row) {
avi23 7:babc367a3333 970 if (invader_normal_missile_bitmap[row][col]) {
avi23 7:babc367a3333 971 screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel;
avi23 7:babc367a3333 972 }
avi23 7:babc367a3333 973 }
avi23 7:babc367a3333 974 }
avi23 7:babc367a3333 975
avi23 8:b2faec20ed8f 976 ///Checks missile will not exceed screen buffer
avi23 7:babc367a3333 977 if (invader_normal_missile[missile_no].y_pos < 44) {
avi23 8:b2faec20ed8f 978 ///Increments the position of the missile
avi23 7:babc367a3333 979 ++invader_normal_missile[missile_no].y_pos;
avi23 7:babc367a3333 980
avi23 8:b2faec20ed8f 981 ///Collision detection
avi23 7:babc367a3333 982 CollisionDetectionInvaderNormalMissile(missile_no);
avi23 7:babc367a3333 983
avi23 7:babc367a3333 984 } else {
avi23 8:b2faec20ed8f 985 ///Sets the missiles fired flag as false and detaches the tickers
avi23 7:babc367a3333 986 invader_normal_missile[missile_no].fired = false;
avi23 7:babc367a3333 987 move_invader_normal_missile[missile_no].detach();
avi23 7:babc367a3333 988 }
avi23 7:babc367a3333 989 }
avi23 7:babc367a3333 990
avi23 8:b2faec20ed8f 991 ///Checks the bottom centre point for a collision. If it doesn't push the bitmap to the screen buffer
avi23 7:babc367a3333 992 void CollisionDetectionInvaderNormalMissile(int missile_no)
avi23 7:babc367a3333 993 {
avi23 8:b2faec20ed8f 994 ///Invader missile coordinates shifted to match centre bottom of bitmap
avi23 7:babc367a3333 995 int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1;
avi23 7:babc367a3333 996 int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3;
avi23 7:babc367a3333 997 if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) {
avi23 9:cbb982b7e353 998 ///Cannon has invunerability for 1s after getting hit
avi23 9:cbb982b7e353 999 if (!g_cannon_hit_flag) {
avi23 9:cbb982b7e353 1000 g_cannon_hit_flag = true;
avi23 9:cbb982b7e353 1001 InvaderNormalMissileHitCannon();
avi23 9:cbb982b7e353 1002 ///Attaches a timeout to allow cannon to be hit again
avi23 9:cbb982b7e353 1003 cannon_hit.attach(&cannon_hit_isr, 1);
avi23 9:cbb982b7e353 1004 }
avi23 7:babc367a3333 1005 invader_normal_missile[missile_no].fired = false;
avi23 7:babc367a3333 1006 move_invader_normal_missile[missile_no].detach();
avi23 7:babc367a3333 1007 } else if (screen_buffer[relative_x_pos][relative_y_pos] >= first_barrier_pixel && screen_buffer[relative_x_pos][relative_y_pos] < (first_barrier_pixel + 3)) {
avi23 8:b2faec20ed8f 1008 ///Finds barrier number
avi23 7:babc367a3333 1009 InvaderNormalMissileHitBarrier(invader_normal_missile[missile_no]);
avi23 7:babc367a3333 1010 invader_normal_missile[missile_no].fired = false;
avi23 7:babc367a3333 1011 move_invader_normal_missile[missile_no].detach();
avi23 7:babc367a3333 1012 } else {
avi23 7:babc367a3333 1013 for (int col = 0; col < 3; ++col) {
avi23 7:babc367a3333 1014 for (int row = 0; row < 4; ++row) {
avi23 7:babc367a3333 1015 if (invader_normal_missile_bitmap[row][col]) {
avi23 7:babc367a3333 1016 screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = invader_normal_missile_pixel;
avi23 7:babc367a3333 1017 }
avi23 7:babc367a3333 1018 }
avi23 7:babc367a3333 1019 }
avi23 7:babc367a3333 1020 }
avi23 7:babc367a3333 1021 }
avi23 7:babc367a3333 1022
avi23 7:babc367a3333 1023 void InvaderNormalMissileHitCannon()
avi23 7:babc367a3333 1024 {
avi23 8:b2faec20ed8f 1025 ///Decrements the number of lives, pauses the game for 2 seconds
avi23 8:b2faec20ed8f 1026 ///Detaches all tickers
avi23 7:babc367a3333 1027 DetachTickers();
avi23 9:cbb982b7e353 1028 LPWait(2);
avi23 7:babc367a3333 1029 --number_of_lives;
avi23 9:cbb982b7e353 1030 AttachTickers();
avi23 7:babc367a3333 1031 }
avi23 7:babc367a3333 1032
avi23 8:b2faec20ed8f 1033 ///Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation
avi23 7:babc367a3333 1034 void InvaderNormalMissileHitBarrier(const struct InvaderNormalMissiles (&missile))
avi23 7:babc367a3333 1035 {
avi23 7:babc367a3333 1036 int barrier_no = screen_buffer[missile.x_pos + 1][missile.y_pos + 3] - first_barrier_pixel;
avi23 8:b2faec20ed8f 1037 ///Essentially inverse of barrier init
avi23 7:babc367a3333 1038 int relative_x_pos = (missile.x_pos + 1) - 10 - (barrier_no*25) - 1;
avi23 7:babc367a3333 1039 int relative_y_pos = (missile.y_pos + 3) - 33;
avi23 8:b2faec20ed8f 1040 ///Loops through the damage bitmap and modifies the barrier's after bitmap
avi23 7:babc367a3333 1041 for (int col = 0; col < 3; ++col) {
avi23 7:babc367a3333 1042 for (int row_bit = 0; row_bit < 2; ++row_bit) {
avi23 8:b2faec20ed8f 1043 ///Makes sure bitmap index does not go out of bounds. If it does go to the next iteration
avi23 7:babc367a3333 1044 if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) {
avi23 7:babc367a3333 1045 barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_invader_normal_missile_damage_bitmap[row_bit][col];
avi23 7:babc367a3333 1046 }
avi23 7:babc367a3333 1047 }
avi23 7:babc367a3333 1048 }
avi23 7:babc367a3333 1049 }
avi23 7:babc367a3333 1050
avi23 8:b2faec20ed8f 1051 ///Detaches game related tickers
avi23 5:34855f712350 1052 void DetachTickers()
avi23 5:34855f712350 1053 {
avi23 5:34855f712350 1054 update_screen.detach();
avi23 5:34855f712350 1055 move_enemies.detach();
avi23 8:b2faec20ed8f 1056
avi23 9:cbb982b7e353 1057 ///Only detaches if are on the screen
avi23 5:34855f712350 1058 if (cannon_missile_on_screen) {
avi23 5:34855f712350 1059 move_cannon_missile.detach();
avi23 5:34855f712350 1060 }
avi23 9:cbb982b7e353 1061 if (ufo_on_screen) {
avi23 9:cbb982b7e353 1062 move_ufo.detach();
avi23 9:cbb982b7e353 1063 }
avi23 5:34855f712350 1064 for (int i = 0; i < 2; ++i) {
avi23 5:34855f712350 1065 if (invader_normal_missile[i].fired) {
avi23 5:34855f712350 1066 move_invader_normal_missile[i].detach();
avi23 5:34855f712350 1067 }
avi23 5:34855f712350 1068 }
avi23 5:34855f712350 1069 }
avi23 5:34855f712350 1070
avi23 8:b2faec20ed8f 1071 ///Attaches game related tickers
avi23 5:34855f712350 1072 void AttachTickers()
avi23 5:34855f712350 1073 {
avi23 5:34855f712350 1074 update_screen.attach(&update_screen_isr, 0.05);
avi23 5:34855f712350 1075 move_enemies.attach(&move_enemies_isr, ticker_period);
avi23 8:b2faec20ed8f 1076 ///Only attaches if missiles were on the screen
avi23 5:34855f712350 1077 if (cannon_missile_on_screen) {
avi23 5:34855f712350 1078 move_cannon_missile.attach(&move_cannon_missile_isr, 0.05);
avi23 5:34855f712350 1079 }
avi23 9:cbb982b7e353 1080 if (ufo_on_screen) {
avi23 9:cbb982b7e353 1081 move_ufo.attach(&move_ufo_isr, 0.1);
avi23 9:cbb982b7e353 1082 }
avi23 5:34855f712350 1083 for (int i = 0; i < 2; ++i) {
avi23 5:34855f712350 1084 if (invader_normal_missile[i].fired) {
avi23 5:34855f712350 1085 move_invader_normal_missile[i].attach(move_invader_normal_missile_isr[i], 0.05);
avi23 5:34855f712350 1086 }
avi23 5:34855f712350 1087 }
avi23 6:89d4a7f7588b 1088 }
avi23 6:89d4a7f7588b 1089
avi23 6:89d4a7f7588b 1090 void PauseScreen()
avi23 6:89d4a7f7588b 1091 {
avi23 8:b2faec20ed8f 1092 ///Prints the pause screen, score etc
avi23 7:babc367a3333 1093 PrintPauseScreen();
avi23 7:babc367a3333 1094
avi23 6:89d4a7f7588b 1095 while (game_state == paused) {
avi23 8:b2faec20ed8f 1096 ///Draws the cursor
avi23 8:b2faec20ed8f 1097 cursor_y_pos = ((fsm_state+3)*8)+3; ///Adds 3 to the fsm state to get the bank, multiplies it by 8 to get the pixel no and offsets it by 3
avi23 8:b2faec20ed8f 1098 lcd.drawRect(74, cursor_y_pos, 2, 2, 1); ///Draws the cursor
avi23 6:89d4a7f7588b 1099
avi23 6:89d4a7f7588b 1100 if (g_move_joystick_flag) {
avi23 6:89d4a7f7588b 1101 g_move_joystick_flag = false;
avi23 6:89d4a7f7588b 1102
avi23 8:b2faec20ed8f 1103 ///Moves the cursor to match the selected option, only if the joystick isn't centred
avi23 6:89d4a7f7588b 1104 MoveCursor(fsm_paused);
avi23 6:89d4a7f7588b 1105 }
avi23 6:89d4a7f7588b 1106
avi23 8:b2faec20ed8f 1107 ///If the button is pressed the selected option will appear on the screen
avi23 6:89d4a7f7588b 1108 if (g_shoot_pressed_flag) {
avi23 6:89d4a7f7588b 1109 g_shoot_pressed_flag = false;
avi23 9:cbb982b7e353 1110
avi23 6:89d4a7f7588b 1111 game_state = fsm_paused[fsm_state].output;
avi23 6:89d4a7f7588b 1112 }
avi23 6:89d4a7f7588b 1113
avi23 9:cbb982b7e353 1114 ///Returns to the game state when the joystick is pressed
avi23 6:89d4a7f7588b 1115 if (joystick.get_button_flag()) {
avi23 6:89d4a7f7588b 1116 joystick.set_button_flag(0);
avi23 9:cbb982b7e353 1117
avi23 9:cbb982b7e353 1118 game_state = game;
avi23 6:89d4a7f7588b 1119 }
avi23 6:89d4a7f7588b 1120
avi23 6:89d4a7f7588b 1121 lcd.refresh();
avi23 6:89d4a7f7588b 1122 sleep();
avi23 6:89d4a7f7588b 1123 }
avi23 6:89d4a7f7588b 1124 }
avi23 6:89d4a7f7588b 1125
avi23 6:89d4a7f7588b 1126 void PrintPauseScreen()
avi23 6:89d4a7f7588b 1127 {
avi23 8:b2faec20ed8f 1128 ///Prints paused and a line underneath
avi23 6:89d4a7f7588b 1129 lcd.printString("Paused", 24, 0);
avi23 8:b2faec20ed8f 1130 ///Displays the current score
avi23 6:89d4a7f7588b 1131 char buffer[14];
avi23 6:89d4a7f7588b 1132 sprintf(buffer, "Score: %d", score);
avi23 6:89d4a7f7588b 1133 lcd.printString(buffer, 0, 1);
avi23 8:b2faec20ed8f 1134 ///Displays the no of lives
avi23 6:89d4a7f7588b 1135 sprintf(buffer, "Lives: %d", number_of_lives);
avi23 6:89d4a7f7588b 1136 lcd.printString(buffer, 0, 2);
avi23 6:89d4a7f7588b 1137 lcd.drawLine(0, 23, 83, 23, 2);
avi23 8:b2faec20ed8f 1138 ///Prints options on pause menu
avi23 6:89d4a7f7588b 1139 lcd.printString("Resume", 5, 3);
avi23 6:89d4a7f7588b 1140 lcd.printString("Save", 5, 4);
avi23 6:89d4a7f7588b 1141 lcd.printString("Quit", 5, 5);
avi23 6:89d4a7f7588b 1142 }
avi23 6:89d4a7f7588b 1143
avi23 6:89d4a7f7588b 1144 void MoveCursor(const struct FSMMenus *fsm)
avi23 6:89d4a7f7588b 1145 {
avi23 8:b2faec20ed8f 1146 ///If the joystick is is pushed down half way clear the cursor and set the next state
avi23 6:89d4a7f7588b 1147 if (joystick.GetYValue() < 0.25f) {
avi23 8:b2faec20ed8f 1148 ///Clears the cursor
avi23 6:89d4a7f7588b 1149 lcd.drawRect(74, cursor_y_pos, 2, 2, 2);
avi23 8:b2faec20ed8f 1150 ///Sets the new state
avi23 6:89d4a7f7588b 1151 fsm_state = fsm[fsm_state].next_state[0];
avi23 6:89d4a7f7588b 1152 } else if (joystick.GetYValue() > 0.75f) {
avi23 8:b2faec20ed8f 1153 ///Clears the cursor
avi23 6:89d4a7f7588b 1154 lcd.drawRect(74, cursor_y_pos, 2, 2, 2);
avi23 8:b2faec20ed8f 1155 ///Sets the new state
avi23 6:89d4a7f7588b 1156 fsm_state = fsm[fsm_state].next_state[1];
avi23 6:89d4a7f7588b 1157 }
avi23 8:b2faec20ed8f 1158 }
avi23 8:b2faec20ed8f 1159
avi23 8:b2faec20ed8f 1160 void MenuScreen()
avi23 8:b2faec20ed8f 1161 {
avi23 8:b2faec20ed8f 1162 ///Print the menu text
avi23 8:b2faec20ed8f 1163 PrintMenuScreen();
avi23 8:b2faec20ed8f 1164
avi23 8:b2faec20ed8f 1165 while (game_state == menu) {
avi23 8:b2faec20ed8f 1166 ///Draws the cursor
avi23 8:b2faec20ed8f 1167 cursor_y_pos = ((fsm_state+2)*8)+3; ///Adds 2 to the fsm state to get the bank, multiplies it by 8 to get the pixel no and offsets it by 3
avi23 8:b2faec20ed8f 1168 lcd.drawRect(74, cursor_y_pos, 2, 2, 1);
avi23 8:b2faec20ed8f 1169
avi23 8:b2faec20ed8f 1170 if (g_move_joystick_flag) {
avi23 8:b2faec20ed8f 1171 g_move_joystick_flag = false;
avi23 8:b2faec20ed8f 1172
avi23 8:b2faec20ed8f 1173 ///Moves the cursor to match the selected option, only if the joystick isn't centred
avi23 8:b2faec20ed8f 1174 MoveCursor(fsm_main_menu);
avi23 8:b2faec20ed8f 1175 }
avi23 8:b2faec20ed8f 1176
avi23 8:b2faec20ed8f 1177 ///If shoot is pressed go to the selected screen
avi23 8:b2faec20ed8f 1178 if (g_shoot_pressed_flag) {
avi23 8:b2faec20ed8f 1179 g_shoot_pressed_flag = false;
avi23 8:b2faec20ed8f 1180
avi23 8:b2faec20ed8f 1181 game_state = fsm_main_menu[fsm_state].output;
avi23 8:b2faec20ed8f 1182
avi23 8:b2faec20ed8f 1183 ///If the game state is equal to the game initalise it
avi23 8:b2faec20ed8f 1184 if (game_state == game) {
avi23 8:b2faec20ed8f 1185 InitaliseGame();
avi23 8:b2faec20ed8f 1186 }
avi23 8:b2faec20ed8f 1187 }
avi23 8:b2faec20ed8f 1188
avi23 8:b2faec20ed8f 1189 ///Do nothing when the joystick is pressed
avi23 8:b2faec20ed8f 1190 if(joystick.get_button_flag()) {
avi23 8:b2faec20ed8f 1191 joystick.set_button_flag(0);
avi23 8:b2faec20ed8f 1192 }
avi23 8:b2faec20ed8f 1193
avi23 8:b2faec20ed8f 1194 lcd.refresh();
avi23 8:b2faec20ed8f 1195 sleep();
avi23 8:b2faec20ed8f 1196 }
avi23 8:b2faec20ed8f 1197 }
avi23 8:b2faec20ed8f 1198
avi23 8:b2faec20ed8f 1199 void PrintMenuScreen()
avi23 8:b2faec20ed8f 1200 {
avi23 8:b2faec20ed8f 1201 ///Prints Space invaders, then menu below, then a line underneath
avi23 8:b2faec20ed8f 1202 lcd.printString("Space Invaders", 0, 0);
avi23 8:b2faec20ed8f 1203 lcd.printString("Menu", 28, 1);
avi23 8:b2faec20ed8f 1204 lcd.drawLine(0, 15, 83, 15, 2);
avi23 8:b2faec20ed8f 1205
avi23 8:b2faec20ed8f 1206 ///Prints menu options
avi23 8:b2faec20ed8f 1207 lcd.printString("New Game", 5, 2);
avi23 8:b2faec20ed8f 1208 lcd.printString("Load Game", 5, 3);
avi23 8:b2faec20ed8f 1209 lcd.printString("High Scores", 5, 4);
avi23 8:b2faec20ed8f 1210 lcd.printString("Settings", 5, 5);
avi23 8:b2faec20ed8f 1211 }
avi23 8:b2faec20ed8f 1212
avi23 8:b2faec20ed8f 1213 void AttemptToSpawnUFO()
avi23 8:b2faec20ed8f 1214 {
avi23 8:b2faec20ed8f 1215 ///1/8 chance of UFO spawning if it hasn't already
avi23 8:b2faec20ed8f 1216 if (!ufo_on_screen && (rand() % 8 == 1) && down_count > 1 && no_of_alive_invaders > 3) {
avi23 8:b2faec20ed8f 1217 ///Marks the UFO as on the screen and sets its position and direction
avi23 8:b2faec20ed8f 1218 ufo_on_screen = true;
avi23 8:b2faec20ed8f 1219 ufo_direction = (rand() % 2);
avi23 8:b2faec20ed8f 1220 if (ufo_direction == RIGHT) {
avi23 8:b2faec20ed8f 1221 ufo_x_pos = -14;
avi23 8:b2faec20ed8f 1222 } else {
avi23 8:b2faec20ed8f 1223 ufo_x_pos = 83;
avi23 8:b2faec20ed8f 1224 }
avi23 8:b2faec20ed8f 1225
avi23 8:b2faec20ed8f 1226 ///Attachs the move UFO ticker
avi23 8:b2faec20ed8f 1227 move_ufo.attach(&move_ufo_isr, 0.1);
avi23 8:b2faec20ed8f 1228 }
avi23 8:b2faec20ed8f 1229 }
avi23 8:b2faec20ed8f 1230
avi23 8:b2faec20ed8f 1231 void ClearUFO()
avi23 8:b2faec20ed8f 1232 {
avi23 8:b2faec20ed8f 1233 ///Clears the UFO
avi23 8:b2faec20ed8f 1234 for (int col = 0; col < 14; ++col) {
avi23 8:b2faec20ed8f 1235 for (int row = 0; row < 5; ++row) {
avi23 8:b2faec20ed8f 1236 ///Only clear the pixel in the buffer if it is within bounds
avi23 8:b2faec20ed8f 1237 if (ufo_x_pos + col >= 0 && ufo_x_pos + col < 84) {
avi23 8:b2faec20ed8f 1238 if (ufo_bitmap[row][col]) {
avi23 8:b2faec20ed8f 1239 screen_buffer[ufo_x_pos + col][ufo_y_pos + row] = empty_pixel;
avi23 8:b2faec20ed8f 1240 }
avi23 8:b2faec20ed8f 1241 }
avi23 8:b2faec20ed8f 1242 }
avi23 8:b2faec20ed8f 1243 }
avi23 8:b2faec20ed8f 1244 }
avi23 8:b2faec20ed8f 1245
avi23 8:b2faec20ed8f 1246 void DrawUFO()
avi23 8:b2faec20ed8f 1247 {
avi23 8:b2faec20ed8f 1248 ///Checks if the ufo can be within the screen bounds
avi23 8:b2faec20ed8f 1249 ///If it is, push the ufo to the screen buffer
avi23 8:b2faec20ed8f 1250 if (ufo_x_pos > -14 && ufo_x_pos < 84) {
avi23 8:b2faec20ed8f 1251 for (int col = 0; col < 14; ++col) {
avi23 8:b2faec20ed8f 1252 for (int row = 0; row < 5; ++row) {
avi23 8:b2faec20ed8f 1253 ///Only clear the pixel in the buffer if it is within bounds
avi23 8:b2faec20ed8f 1254 if (ufo_x_pos + col >= 0 && ufo_x_pos + col < 84) {
avi23 8:b2faec20ed8f 1255 if (ufo_bitmap[row][col]) {
avi23 8:b2faec20ed8f 1256 screen_buffer[ufo_x_pos + col][ufo_y_pos + row] = ufo_pixel;
avi23 8:b2faec20ed8f 1257 }
avi23 8:b2faec20ed8f 1258 }
avi23 8:b2faec20ed8f 1259 }
avi23 8:b2faec20ed8f 1260 }
avi23 8:b2faec20ed8f 1261 } else {
avi23 8:b2faec20ed8f 1262 ///Otherwise mark it as not on the screen and detach the ticker
avi23 8:b2faec20ed8f 1263 ufo_on_screen = false;
avi23 8:b2faec20ed8f 1264 move_ufo.detach();
avi23 8:b2faec20ed8f 1265 }
avi23 9:cbb982b7e353 1266 }
avi23 9:cbb982b7e353 1267
avi23 9:cbb982b7e353 1268 bool high_scores_sorter(const struct HighScores (&lhs), const struct HighScores (&rhs))
avi23 9:cbb982b7e353 1269 {
avi23 9:cbb982b7e353 1270 return lhs.score > rhs.score;
avi23 9:cbb982b7e353 1271 }
avi23 9:cbb982b7e353 1272
avi23 9:cbb982b7e353 1273 void ScoreScreen()
avi23 9:cbb982b7e353 1274 {
avi23 9:cbb982b7e353 1275 lcd.printString("High Scores", 8, 0);
avi23 9:cbb982b7e353 1276 lcd.drawLine(0, 7, 83, 7, 2);
avi23 9:cbb982b7e353 1277
avi23 9:cbb982b7e353 1278 PrintHighScores();
avi23 9:cbb982b7e353 1279
avi23 9:cbb982b7e353 1280 lcd.printString("Back", 5, 5);
avi23 9:cbb982b7e353 1281 const int cursor_y_pos = 43;
avi23 9:cbb982b7e353 1282 lcd.drawRect(74, cursor_y_pos, 2, 2, 1);
avi23 9:cbb982b7e353 1283
avi23 9:cbb982b7e353 1284 lcd.refresh();
avi23 9:cbb982b7e353 1285
avi23 9:cbb982b7e353 1286 while (game_state == scores) {
avi23 9:cbb982b7e353 1287 if (joystick.get_button_flag()) {
avi23 9:cbb982b7e353 1288 joystick.set_button_flag(0);
avi23 9:cbb982b7e353 1289 }
avi23 9:cbb982b7e353 1290 if (g_shoot_pressed_flag) {
avi23 9:cbb982b7e353 1291 g_shoot_pressed_flag = false;
avi23 9:cbb982b7e353 1292
avi23 9:cbb982b7e353 1293 game_state = menu; // If the button is pressed go to the menu state
avi23 9:cbb982b7e353 1294 }
avi23 9:cbb982b7e353 1295
avi23 9:cbb982b7e353 1296 sleep();
avi23 9:cbb982b7e353 1297 }
avi23 9:cbb982b7e353 1298 }
avi23 9:cbb982b7e353 1299
avi23 9:cbb982b7e353 1300 void PrintHighScores()
avi23 9:cbb982b7e353 1301 {
avi23 9:cbb982b7e353 1302 ///Loops throught the high scores and prints them to the screen
avi23 9:cbb982b7e353 1303 for (int i = 0; i < 3; ++i) {
avi23 9:cbb982b7e353 1304 ///Counts how many digits are in score
avi23 9:cbb982b7e353 1305 int temp_score = high_scores[i].score;
avi23 9:cbb982b7e353 1306 int no_of_digits = 0;
avi23 9:cbb982b7e353 1307 do {
avi23 9:cbb982b7e353 1308 temp_score /= 10;
avi23 9:cbb982b7e353 1309 ++no_of_digits;
avi23 9:cbb982b7e353 1310 } while (temp_score != 0);
avi23 9:cbb982b7e353 1311
avi23 9:cbb982b7e353 1312 ///Prints name to c-string
avi23 9:cbb982b7e353 1313 char buffer[14];
avi23 9:cbb982b7e353 1314 sprintf(buffer, "%s", high_scores[i].name);
avi23 9:cbb982b7e353 1315
avi23 9:cbb982b7e353 1316 ///Prints correct number of spaces to c-string
avi23 9:cbb982b7e353 1317 int no_of_spaces = 14 - no_of_digits;
avi23 9:cbb982b7e353 1318 for (int space = 3; space < no_of_spaces; ++space) {
avi23 9:cbb982b7e353 1319 sprintf(buffer, "%s%s", buffer, " ");
avi23 9:cbb982b7e353 1320 }
avi23 9:cbb982b7e353 1321
avi23 9:cbb982b7e353 1322 ///Prints score to c-string
avi23 9:cbb982b7e353 1323 sprintf(buffer, "%s%d", buffer, high_scores[i].score);
avi23 9:cbb982b7e353 1324 lcd.printString(buffer, 0, 2 + i);
avi23 9:cbb982b7e353 1325 }
avi23 9:cbb982b7e353 1326 }
avi23 9:cbb982b7e353 1327
avi23 9:cbb982b7e353 1328 void GameOverScreen()
avi23 9:cbb982b7e353 1329 {
avi23 9:cbb982b7e353 1330 lcd.printString("Game Over", 18, 0);
avi23 9:cbb982b7e353 1331 char buffer[14];
avi23 9:cbb982b7e353 1332 sprintf(buffer, "Score: %d", score);
avi23 9:cbb982b7e353 1333 lcd.printString(buffer, 0, 1);
avi23 9:cbb982b7e353 1334
avi23 9:cbb982b7e353 1335 ///Save score input
avi23 9:cbb982b7e353 1336 if (score > high_scores[2].score) {
avi23 9:cbb982b7e353 1337 lcd.printString("High Score!", 0, 2);
avi23 9:cbb982b7e353 1338 lcd.printChar('A', 27, 3);
avi23 9:cbb982b7e353 1339 lcd.printChar('A', 42, 3);
avi23 9:cbb982b7e353 1340 lcd.printChar('A', 57, 3);
avi23 9:cbb982b7e353 1341
avi23 9:cbb982b7e353 1342 int name[3] = {0, 0, 0};
avi23 9:cbb982b7e353 1343 GetNameForScore(name);
avi23 9:cbb982b7e353 1344
avi23 9:cbb982b7e353 1345 SaveHighScore(name);
avi23 9:cbb982b7e353 1346 }
avi23 9:cbb982b7e353 1347
avi23 9:cbb982b7e353 1348 ///After high score is inputted or no high score has been reached
avi23 9:cbb982b7e353 1349 lcd.printString("Quit", 5, 5);
avi23 9:cbb982b7e353 1350 const int cursor_y_pos = 43;
avi23 9:cbb982b7e353 1351 lcd.drawRect(74, cursor_y_pos, 2, 2, 1);
avi23 9:cbb982b7e353 1352
avi23 9:cbb982b7e353 1353 while (game_state == over) {
avi23 9:cbb982b7e353 1354 if (joystick.get_button_flag()) {
avi23 9:cbb982b7e353 1355 joystick.set_button_flag(0);
avi23 9:cbb982b7e353 1356 }
avi23 9:cbb982b7e353 1357
avi23 9:cbb982b7e353 1358 if (g_shoot_pressed_flag) {
avi23 9:cbb982b7e353 1359 g_shoot_pressed_flag = false;
avi23 9:cbb982b7e353 1360
avi23 9:cbb982b7e353 1361 game_state = menu;
avi23 9:cbb982b7e353 1362 }
avi23 9:cbb982b7e353 1363
avi23 9:cbb982b7e353 1364 lcd.refresh();
avi23 9:cbb982b7e353 1365 sleep();
avi23 9:cbb982b7e353 1366 }
avi23 9:cbb982b7e353 1367 }
avi23 9:cbb982b7e353 1368
avi23 9:cbb982b7e353 1369 void GetNameForScore(int (&name)[3])
avi23 9:cbb982b7e353 1370 {
avi23 9:cbb982b7e353 1371 int name_cursor_pos = 0; ///Cursor is at first letter
avi23 9:cbb982b7e353 1372
avi23 9:cbb982b7e353 1373 while (name_cursor_pos < 3) {
avi23 9:cbb982b7e353 1374 ///Prints the name cursor
avi23 9:cbb982b7e353 1375 lcd.drawRect(27+(15*name_cursor_pos), 32, 4, 2, 1);
avi23 9:cbb982b7e353 1376
avi23 9:cbb982b7e353 1377 if (g_shoot_pressed_flag) {
avi23 9:cbb982b7e353 1378 g_shoot_pressed_flag = false;
avi23 9:cbb982b7e353 1379
avi23 9:cbb982b7e353 1380 ///Clears the name cursor and moves it
avi23 9:cbb982b7e353 1381 lcd.drawRect(27+(15*name_cursor_pos), 32, 4, 2, 2);
avi23 9:cbb982b7e353 1382 ++name_cursor_pos;
avi23 9:cbb982b7e353 1383 }
avi23 9:cbb982b7e353 1384
avi23 9:cbb982b7e353 1385 if (g_move_joystick_flag) {
avi23 9:cbb982b7e353 1386 g_move_joystick_flag = false;
avi23 9:cbb982b7e353 1387
avi23 9:cbb982b7e353 1388 if (joystick.GetYValue() < 0.25f) {
avi23 9:cbb982b7e353 1389 ///Increments the name position, if it is over 25 set it to 0
avi23 9:cbb982b7e353 1390 if (++name[name_cursor_pos] > 25) {
avi23 9:cbb982b7e353 1391 name[name_cursor_pos] = 0;
avi23 9:cbb982b7e353 1392 }
avi23 9:cbb982b7e353 1393 } else if (joystick.GetYValue() > 0.75f) {
avi23 9:cbb982b7e353 1394 ///Decrements the name position, if it is under 0 set it to 25
avi23 9:cbb982b7e353 1395 if (--name[name_cursor_pos] < 0) {
avi23 9:cbb982b7e353 1396 name[name_cursor_pos] = 25;
avi23 9:cbb982b7e353 1397 }
avi23 9:cbb982b7e353 1398 }
avi23 9:cbb982b7e353 1399
avi23 9:cbb982b7e353 1400 lcd.printChar(name[name_cursor_pos] + 65, 27+(15*name_cursor_pos), 3); ///ASCII is offset by 65
avi23 9:cbb982b7e353 1401 }
avi23 9:cbb982b7e353 1402
avi23 9:cbb982b7e353 1403 lcd.refresh();
avi23 9:cbb982b7e353 1404 sleep();
avi23 9:cbb982b7e353 1405 }
avi23 9:cbb982b7e353 1406 }
avi23 9:cbb982b7e353 1407
avi23 9:cbb982b7e353 1408 void SaveHighScore(const int (&name)[3])
avi23 9:cbb982b7e353 1409 {
avi23 9:cbb982b7e353 1410 ///Saves name and score to struct array, overwritting lowest score
avi23 9:cbb982b7e353 1411 for (int letter = 0; letter < 3; ++letter) {
avi23 9:cbb982b7e353 1412 high_scores[2].name[letter] = name[letter] + 65;
avi23 9:cbb982b7e353 1413 }
avi23 9:cbb982b7e353 1414 high_scores[2].score = score;
avi23 9:cbb982b7e353 1415
avi23 9:cbb982b7e353 1416 ///Sorts struct array
avi23 9:cbb982b7e353 1417 std::sort(high_scores, high_scores + 3, &high_scores_sorter);
avi23 9:cbb982b7e353 1418
avi23 9:cbb982b7e353 1419 ///Saves the score
avi23 9:cbb982b7e353 1420 std::ofstream high_score_data("/sd/high_scores.dat", std::ios::binary);
avi23 9:cbb982b7e353 1421 if (high_score_data.good()) { ///Checks to see if file opening was good
avi23 9:cbb982b7e353 1422 high_score_data.write((char *)(&high_scores), sizeof(high_scores));
avi23 9:cbb982b7e353 1423 ///Flushes the buffer and saves the file
avi23 9:cbb982b7e353 1424 high_score_data.close();
avi23 9:cbb982b7e353 1425 lcd.printString("Saved", 27, 4);
avi23 9:cbb982b7e353 1426 } else {
avi23 9:cbb982b7e353 1427 lcd.clear();
avi23 9:cbb982b7e353 1428 lcd.printString("Error", 1, 1);
avi23 9:cbb982b7e353 1429 lcd.printString("Opening", 1, 2);
avi23 9:cbb982b7e353 1430 lcd.printString("File.", 1, 3);
avi23 9:cbb982b7e353 1431 LPWait(2);
avi23 9:cbb982b7e353 1432 }
avi23 9:cbb982b7e353 1433 }
avi23 9:cbb982b7e353 1434
avi23 9:cbb982b7e353 1435 void SaveGameData()
avi23 9:cbb982b7e353 1436 {
avi23 9:cbb982b7e353 1437 ///Creates the output file as a binary file
avi23 9:cbb982b7e353 1438 std::ofstream save_data("/sd/game_save.dat", std::ios::binary);
avi23 9:cbb982b7e353 1439 if (save_data.good()) { ///Checks to see if file opening was good
avi23 9:cbb982b7e353 1440 ///Prints booleans to file
avi23 9:cbb982b7e353 1441 save_data.write((char *)(&invaders_in_state2), sizeof(invaders_in_state2));
avi23 9:cbb982b7e353 1442 save_data.write((char *)(&invader_direction), sizeof(invader_direction));
avi23 9:cbb982b7e353 1443 save_data.write((char *)(&cannon_missile_on_screen), sizeof(cannon_missile_on_screen));
avi23 9:cbb982b7e353 1444 save_data.write((char *)(&ufo_on_screen), sizeof(ufo_on_screen));
avi23 9:cbb982b7e353 1445 save_data.write((char *)(&ufo_direction), sizeof(ufo_direction));
avi23 9:cbb982b7e353 1446 save_data.write((char *)(&ufo_bonus), sizeof(ufo_bonus));
avi23 9:cbb982b7e353 1447
avi23 9:cbb982b7e353 1448 ///Prints integers to file
avi23 9:cbb982b7e353 1449 save_data.write((char *)(&score), sizeof(score));
avi23 9:cbb982b7e353 1450 save_data.write((char *)(&shot_count), sizeof(shot_count));
avi23 9:cbb982b7e353 1451 save_data.write((char *)(&number_of_lives), sizeof(number_of_lives));
avi23 9:cbb982b7e353 1452 save_data.write((char *)(&cannon_xpos), sizeof(cannon_xpos));
avi23 9:cbb982b7e353 1453 save_data.write((char *)(&cannon_missile_x_pos), sizeof(cannon_missile_x_pos));
avi23 9:cbb982b7e353 1454 save_data.write((char *)(&cannon_missile_y_pos), sizeof(cannon_missile_y_pos));
avi23 9:cbb982b7e353 1455 save_data.write((char *)(&no_of_alive_invaders), sizeof(no_of_alive_invaders));
avi23 9:cbb982b7e353 1456 save_data.write((char *)(&down_count), sizeof(down_count));
avi23 9:cbb982b7e353 1457 save_data.write((char *)(&ufo_x_pos), sizeof(ufo_x_pos));
avi23 9:cbb982b7e353 1458
avi23 9:cbb982b7e353 1459 ///Prints invaders to file
avi23 9:cbb982b7e353 1460 save_data.write((char *)(&small_invader), sizeof(small_invader));
avi23 9:cbb982b7e353 1461 save_data.write((char *)(&medium_invader), sizeof(medium_invader));
avi23 9:cbb982b7e353 1462 save_data.write((char *)(&large_invader), sizeof(large_invader));
avi23 9:cbb982b7e353 1463
avi23 9:cbb982b7e353 1464 ///Prints invader missiles and barriers to file
avi23 9:cbb982b7e353 1465 save_data.write((char *)(&invader_normal_missile), sizeof(invader_normal_missile));
avi23 9:cbb982b7e353 1466 save_data.write((char *)(&barrier), sizeof(barrier));
avi23 9:cbb982b7e353 1467
avi23 9:cbb982b7e353 1468 ///Flushes the buffer and saves the file
avi23 9:cbb982b7e353 1469 save_data.close();
avi23 9:cbb982b7e353 1470 } else {
avi23 9:cbb982b7e353 1471 lcd.clear();
avi23 9:cbb982b7e353 1472 lcd.printString("Error", 1, 1);
avi23 9:cbb982b7e353 1473 lcd.printString("Opening", 1, 2);
avi23 9:cbb982b7e353 1474 lcd.printString("File.", 1, 3);
avi23 9:cbb982b7e353 1475 LPWait(2);
avi23 9:cbb982b7e353 1476 }
avi23 9:cbb982b7e353 1477
avi23 9:cbb982b7e353 1478 game_state = paused;
avi23 9:cbb982b7e353 1479 }
avi23 9:cbb982b7e353 1480
avi23 9:cbb982b7e353 1481 void LoadGameData()
avi23 9:cbb982b7e353 1482 {
avi23 9:cbb982b7e353 1483 ///Creates the input binary file object
avi23 9:cbb982b7e353 1484 std::ifstream save_data("/sd/game_save.dat", std::ios::binary);
avi23 9:cbb982b7e353 1485 if (save_data.good()) { ///Checks to see if file opening was good
avi23 9:cbb982b7e353 1486 ///Gets booleans from file
avi23 9:cbb982b7e353 1487 save_data.read((char *)(&invaders_in_state2), sizeof(invaders_in_state2));
avi23 9:cbb982b7e353 1488 save_data.read((char *)(&invader_direction), sizeof(invader_direction));
avi23 9:cbb982b7e353 1489 save_data.read((char *)(&cannon_missile_on_screen), sizeof(cannon_missile_on_screen));
avi23 9:cbb982b7e353 1490 save_data.read((char *)(&ufo_on_screen), sizeof(ufo_on_screen));
avi23 9:cbb982b7e353 1491 save_data.read((char *)(&ufo_direction), sizeof(ufo_direction));
avi23 9:cbb982b7e353 1492 save_data.read((char *)(&ufo_bonus), sizeof(ufo_bonus));
avi23 9:cbb982b7e353 1493
avi23 9:cbb982b7e353 1494 ///Gets integers from file
avi23 9:cbb982b7e353 1495 save_data.read((char *)(&score), sizeof(score));
avi23 9:cbb982b7e353 1496 save_data.read((char *)(&shot_count), sizeof(shot_count));
avi23 9:cbb982b7e353 1497 save_data.read((char *)(&number_of_lives), sizeof(number_of_lives));
avi23 9:cbb982b7e353 1498 save_data.read((char *)(&cannon_xpos), sizeof(cannon_xpos));
avi23 9:cbb982b7e353 1499 save_data.read((char *)(&cannon_missile_x_pos), sizeof(cannon_missile_x_pos));
avi23 9:cbb982b7e353 1500 save_data.read((char *)(&cannon_missile_y_pos), sizeof(cannon_missile_y_pos));
avi23 9:cbb982b7e353 1501 save_data.read((char *)(&no_of_alive_invaders), sizeof(no_of_alive_invaders));
avi23 9:cbb982b7e353 1502 save_data.read((char *)(&down_count), sizeof(down_count));
avi23 9:cbb982b7e353 1503 save_data.read((char *)(&ufo_x_pos), sizeof(ufo_x_pos));
avi23 9:cbb982b7e353 1504
avi23 9:cbb982b7e353 1505 ///Gets invaders from file
avi23 9:cbb982b7e353 1506 save_data.read((char *)(&small_invader), sizeof(small_invader));
avi23 9:cbb982b7e353 1507 save_data.read((char *)(&medium_invader), sizeof(medium_invader));
avi23 9:cbb982b7e353 1508 save_data.read((char *)(&large_invader), sizeof(large_invader));
avi23 9:cbb982b7e353 1509
avi23 9:cbb982b7e353 1510 ///Gets invader missiles and barriers from file
avi23 9:cbb982b7e353 1511 save_data.read((char *)(&invader_normal_missile), sizeof(invader_normal_missile));
avi23 9:cbb982b7e353 1512 save_data.read((char *)(&barrier), sizeof(barrier));
avi23 9:cbb982b7e353 1513
avi23 9:cbb982b7e353 1514 ///Closes the file
avi23 9:cbb982b7e353 1515 save_data.close();
avi23 9:cbb982b7e353 1516
avi23 9:cbb982b7e353 1517 ///Clears the screen buffer
avi23 9:cbb982b7e353 1518 memset(screen_buffer, 0, sizeof(screen_buffer));
avi23 9:cbb982b7e353 1519 ///Sets the game state flags
avi23 9:cbb982b7e353 1520 game_state = game;
avi23 9:cbb982b7e353 1521 g_update_screen_flag = true;
avi23 9:cbb982b7e353 1522 g_move_joystick_flag = true;
avi23 9:cbb982b7e353 1523 g_move_enemies_flag = true;
avi23 9:cbb982b7e353 1524 g_fire_buzzer_flag = true;
avi23 9:cbb982b7e353 1525 } else {
avi23 9:cbb982b7e353 1526 lcd.clear();
avi23 9:cbb982b7e353 1527 lcd.printString("Error", 1, 1);
avi23 9:cbb982b7e353 1528 lcd.printString("Opening", 1, 2);
avi23 9:cbb982b7e353 1529 lcd.printString("File.", 1, 3);
avi23 9:cbb982b7e353 1530 LPWait(2);
avi23 9:cbb982b7e353 1531 game_state = menu;
avi23 9:cbb982b7e353 1532 }
avi23 9:cbb982b7e353 1533 }
avi23 9:cbb982b7e353 1534
avi23 9:cbb982b7e353 1535 void LoadHighScores()
avi23 9:cbb982b7e353 1536 {
avi23 9:cbb982b7e353 1537 ///Clears high score data before loading file
avi23 9:cbb982b7e353 1538 memset(high_scores, 0, sizeof(high_scores));
avi23 9:cbb982b7e353 1539 ///Extracts high scores from file
avi23 9:cbb982b7e353 1540 std::ifstream high_score_data("/sd/high_scores.dat", std::ios::binary);
avi23 9:cbb982b7e353 1541 if (high_score_data.good()) {
avi23 9:cbb982b7e353 1542 high_score_data.read((char *)(&high_scores), sizeof(high_scores));
avi23 9:cbb982b7e353 1543 }
avi23 9:cbb982b7e353 1544 high_score_data.close();
avi23 9:cbb982b7e353 1545 ///If there are any empty names, fill them with AAA to prevent crashes using printString
avi23 9:cbb982b7e353 1546 for (int i = 0; i < 3; ++i) {
avi23 9:cbb982b7e353 1547 if (high_scores[i].name[0] < 'A') {
avi23 9:cbb982b7e353 1548 for (int letter = 0; letter < 3; ++letter) {
avi23 9:cbb982b7e353 1549 high_scores[i].name[letter] = 'A';
avi23 9:cbb982b7e353 1550 }
avi23 9:cbb982b7e353 1551 }
avi23 9:cbb982b7e353 1552 }
avi23 9:cbb982b7e353 1553
avi23 9:cbb982b7e353 1554 }
avi23 9:cbb982b7e353 1555
avi23 9:cbb982b7e353 1556 void SettingsScreen()
avi23 9:cbb982b7e353 1557 {
avi23 9:cbb982b7e353 1558 PrintSettingsText();
avi23 9:cbb982b7e353 1559
avi23 9:cbb982b7e353 1560 while (game_state == settings) {
avi23 9:cbb982b7e353 1561 ///Prints options and cursor
avi23 9:cbb982b7e353 1562 PrintSettingsOptions();
avi23 9:cbb982b7e353 1563
avi23 9:cbb982b7e353 1564 ///Returns to menu if joystick button is pressed
avi23 9:cbb982b7e353 1565 if (joystick.get_button_flag()) {
avi23 9:cbb982b7e353 1566 joystick.set_button_flag(0);
avi23 9:cbb982b7e353 1567
avi23 9:cbb982b7e353 1568 game_state = menu;
avi23 9:cbb982b7e353 1569 }
avi23 9:cbb982b7e353 1570
avi23 9:cbb982b7e353 1571 ///Moves the cursor when the joystick moves
avi23 9:cbb982b7e353 1572 if (g_move_joystick_flag) {
avi23 9:cbb982b7e353 1573 g_move_joystick_flag = false;
avi23 9:cbb982b7e353 1574
avi23 9:cbb982b7e353 1575 MoveCursor(fsm_settings);
avi23 9:cbb982b7e353 1576 }
avi23 9:cbb982b7e353 1577
avi23 9:cbb982b7e353 1578 if (g_shoot_pressed_flag) {
avi23 9:cbb982b7e353 1579 g_shoot_pressed_flag = false;
avi23 9:cbb982b7e353 1580
avi23 9:cbb982b7e353 1581 EditOption();
avi23 9:cbb982b7e353 1582 }
avi23 9:cbb982b7e353 1583
avi23 9:cbb982b7e353 1584 lcd.refresh();
avi23 9:cbb982b7e353 1585 sleep();
avi23 9:cbb982b7e353 1586 }
avi23 9:cbb982b7e353 1587 }
avi23 9:cbb982b7e353 1588
avi23 9:cbb982b7e353 1589 void PrintSettingsText()
avi23 9:cbb982b7e353 1590 {
avi23 9:cbb982b7e353 1591 ///Prints the options
avi23 9:cbb982b7e353 1592 lcd.printString("Settings", 17, 0);
avi23 9:cbb982b7e353 1593 lcd.drawLine(0, 7, 83, 7, 2);
avi23 9:cbb982b7e353 1594 lcd.printString("Light:", 0, 2);
avi23 9:cbb982b7e353 1595 lcd.printString("Mute: ", 0, 3);
avi23 9:cbb982b7e353 1596 lcd.printString("Delete Data", 0, 4);
avi23 9:cbb982b7e353 1597 lcd.printString("Back", 10, 5);
avi23 9:cbb982b7e353 1598 }
avi23 9:cbb982b7e353 1599
avi23 9:cbb982b7e353 1600 void PrintSettingsOptions()
avi23 9:cbb982b7e353 1601 {
avi23 9:cbb982b7e353 1602 ///Prints the active options
avi23 9:cbb982b7e353 1603 char buffer[14] = {0};
avi23 9:cbb982b7e353 1604 sprintf(buffer, "%d%%", (int)(100*fsm_brightness[brightness_state].output));
avi23 9:cbb982b7e353 1605 pc.printf("%s\n", buffer);
avi23 9:cbb982b7e353 1606 lcd.printString(buffer, 42, 2);
avi23 9:cbb982b7e353 1607 if (is_muted) {
avi23 9:cbb982b7e353 1608 lcd.printString("On", 42, 3);
avi23 9:cbb982b7e353 1609 } else {
avi23 9:cbb982b7e353 1610 lcd.printString("Off", 42, 3);
avi23 9:cbb982b7e353 1611 }
avi23 9:cbb982b7e353 1612 ///Draws the cursor
avi23 9:cbb982b7e353 1613 cursor_y_pos = ((fsm_state+2)*8)+3; ///Adds 2 to the fsm state to get the bank, multiplies it by 8 to get the pixel no and offsets it by 3
avi23 9:cbb982b7e353 1614 lcd.drawRect(74, cursor_y_pos, 2, 2, 1);
avi23 9:cbb982b7e353 1615 }
avi23 9:cbb982b7e353 1616
avi23 9:cbb982b7e353 1617 void EditOption()
avi23 9:cbb982b7e353 1618 {
avi23 9:cbb982b7e353 1619 if (fsm_state == 0) { ///Change brightness
avi23 9:cbb982b7e353 1620 brightness_state = fsm_brightness[brightness_state].next_state;
avi23 9:cbb982b7e353 1621 lcd.setBrightness(fsm_brightness[brightness_state].output);
avi23 9:cbb982b7e353 1622 ///Clears displayed brightness
avi23 9:cbb982b7e353 1623 lcd.drawRect(42, 16, 24, 7, 2);
avi23 9:cbb982b7e353 1624 } else if (fsm_state == 1) { ///Mute game
avi23 9:cbb982b7e353 1625 is_muted = !is_muted;
avi23 11:eab3fb334bde 1626 lcd.drawRect(42, 24, 24, 7, 2);
avi23 9:cbb982b7e353 1627 } else if (fsm_state == 2) { ///Delete save data
avi23 9:cbb982b7e353 1628 DeleteGameData();
avi23 9:cbb982b7e353 1629 ///Sets FSM list back to 0 and resets the cursor
avi23 9:cbb982b7e353 1630 lcd.drawRect(74, cursor_y_pos, 2, 2, 2);
avi23 9:cbb982b7e353 1631 fsm_state = 0;
avi23 9:cbb982b7e353 1632 } else if (fsm_state == 3) {
avi23 9:cbb982b7e353 1633 game_state = menu;
avi23 9:cbb982b7e353 1634 }
avi23 9:cbb982b7e353 1635 }
avi23 9:cbb982b7e353 1636
avi23 9:cbb982b7e353 1637 void DeleteGameData()
avi23 9:cbb982b7e353 1638 {
avi23 9:cbb982b7e353 1639 ///Delete game state data
avi23 9:cbb982b7e353 1640 std::ifstream save_data("/sd/game_save.dat", std::ios::binary);
avi23 9:cbb982b7e353 1641 if (save_data.good()) {
avi23 9:cbb982b7e353 1642 ///Close the file and remove it
avi23 9:cbb982b7e353 1643 save_data.close();
avi23 9:cbb982b7e353 1644 remove("/sd/game_save.dat");
avi23 9:cbb982b7e353 1645 }
avi23 9:cbb982b7e353 1646 ///Deletes high score data
avi23 9:cbb982b7e353 1647 std::ifstream high_scores_data("/sd/high_scores.dat", std::ios::binary);
avi23 9:cbb982b7e353 1648 if (high_scores_data.good()) {
avi23 9:cbb982b7e353 1649 ///Closes the file and remove it
avi23 9:cbb982b7e353 1650 high_scores_data.close();
avi23 9:cbb982b7e353 1651 remove("/sd/high_scores.dat");
avi23 9:cbb982b7e353 1652 }
avi23 9:cbb982b7e353 1653 ///Reloads high score list
avi23 9:cbb982b7e353 1654 LoadHighScores();
avi23 9:cbb982b7e353 1655 }
avi23 9:cbb982b7e353 1656
avi23 9:cbb982b7e353 1657 void LPWait(float t)
avi23 9:cbb982b7e353 1658 {
avi23 9:cbb982b7e353 1659 ///Sets the wait flag
avi23 9:cbb982b7e353 1660 g_lp_wait_flag = true;
avi23 9:cbb982b7e353 1661 ///Attachs the timeout to fire at the users request then sleep
avi23 9:cbb982b7e353 1662 lp_wait.attach(&lp_wait_isr, t);
avi23 9:cbb982b7e353 1663 while (g_lp_wait_flag) {
avi23 9:cbb982b7e353 1664 sleep();
avi23 9:cbb982b7e353 1665 }
avi23 9:cbb982b7e353 1666 }
avi23 9:cbb982b7e353 1667
avi23 9:cbb982b7e353 1668 void SplashScreen()
avi23 9:cbb982b7e353 1669 {
avi23 9:cbb982b7e353 1670 ///Prints text and waits for 3 seconds
avi23 9:cbb982b7e353 1671 lcd.printString("Space Invaders", 0, 1);
avi23 9:cbb982b7e353 1672 lcd.printString("Avinash Patel", 3, 3);
avi23 9:cbb982b7e353 1673 lcd.printString("200860407", 15, 4);
avi23 9:cbb982b7e353 1674 LPWait(3);
avi23 9:cbb982b7e353 1675 }
avi23 9:cbb982b7e353 1676
avi23 9:cbb982b7e353 1677 void PlayBuzzer()
avi23 9:cbb982b7e353 1678 {
avi23 9:cbb982b7e353 1679 if (play_sound) {
avi23 9:cbb982b7e353 1680 ///Sets the frequency and activates the buzzer
avi23 9:cbb982b7e353 1681 buzzer.period(1/fsm_buzzer[buzzer_state].frequency);
avi23 9:cbb982b7e353 1682 buzzer.write(0.5);
avi23 9:cbb982b7e353 1683 play_sound = false;
avi23 9:cbb982b7e353 1684 } else {
avi23 9:cbb982b7e353 1685 ///Deactivates the buzzer and sets the next frequency
avi23 9:cbb982b7e353 1686 buzzer.write(0);
avi23 9:cbb982b7e353 1687 buzzer_state = fsm_buzzer[buzzer_state].next_state;
avi23 9:cbb982b7e353 1688 play_sound = true;
avi23 9:cbb982b7e353 1689 }
avi23 0:427469992efe 1690 }