Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407
Dependencies: Joystick N5110 SDFileSystem mbed
Diff: main.cpp
- Revision:
- 9:cbb982b7e353
- Parent:
- 8:b2faec20ed8f
- Child:
- 11:eab3fb334bde
diff -r b2faec20ed8f -r cbb982b7e353 main.cpp --- a/main.cpp Tue May 03 20:16:06 2016 +0000 +++ b/main.cpp Thu May 05 11:01:17 2016 +0000 @@ -30,6 +30,8 @@ lcd.init(); lcd.clear(); + LoadHighScores(); + ///Configures the function pointer for the invaders normal missile move_invader_normal_missile_isr[0] = &move_invader_normal_missile_0_isr; move_invader_normal_missile_isr[1] = &move_invader_normal_missile_1_isr; @@ -37,6 +39,9 @@ ///Samples joystick every 0.05 second move_joystick.attach(&move_joystick_isr, 0.05); + ///Splash Screen + SplashScreen(); + while (true) { if (game_state == menu) { ///Menu screen lcd.clear(); @@ -51,145 +56,19 @@ AttachTickers(); Game(); } else if (game_state == save) { - ///Creates file pointer and attaches the file - FILE *fp; - fp = fopen("/sd/game_save.txt", "w"); - - if (fp == NULL) { ///If file can't be opened then error - lcd.clear(); - lcd.printString("Error Opening", 1, 1); - wait(2.0); - } else { - ///Prints booleans to file - fprintf(fp, "%d\n", invaders_in_state2); - fprintf(fp, "%d,%d,%d,%d,%d,%d\n", invader_direction, cannon_missile_on_screen, ufo_on_screen, ufo_direction, ufo_bonus, is_muted); - ///Prints integers to file - fprintf(fp, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n", score, shot_count, number_of_lives, cannon_xpos, cannon_missile_x_pos, cannon_missile_y_pos, no_of_alive_invaders, down_count, ufo_x_pos); - ///Prints small invader info to file - for (int small = 0; small < 5; ++small) { - fprintf(fp, "%d,%d,%d\n", small_invader[small].x_pos, small_invader[small].y_pos, small_invader[small].status); - } - ///Prints medium invader info to file - for (int medium = 0; medium < 5; ++medium) { - fprintf(fp, "%d,%d,%d\n", medium_invader[medium].x_pos, medium_invader[medium].y_pos, medium_invader[medium].status); - } - ///Prints large invader info to file - for (int large = 0; large < 5; ++large) { - fprintf(fp, "%d,%d,%d\n", large_invader[large].x_pos, large_invader[large].y_pos, large_invader[large].status); - } - ///Stores invader missile data - for (int missile = 0; missile < 2; ++missile) { - fprintf(fp, "%d,%d,%d\n", invader_normal_missile[missile].x_pos, invader_normal_missile[missile].y_pos, invader_normal_missile[missile].fired); - } - ///Stores barrier data - for (int barrier_no = 0; barrier_no < 3; ++barrier_no) { - fprintf(fp, "%d,%d\n", barrier[barrier_no].x_pos, barrier[barrier_no].y_pos); - ///Stores barrier before bitmaps - for (int row = 0; row < 8; ++row) { - for (int col = 0; col < 14; ++col) { - if (col < 13) { - fprintf(fp, "%d,", barrier[barrier_no].before_bitmap[row][col]); - } else { - fprintf(fp, "%d\n", barrier[barrier_no].before_bitmap[row][col]); - } - } - } - ///Stores barrier after bitmaps - for (int row = 0; row < 8; ++row) { - for (int col = 0; col < 14; ++col) { - if (col < 13) { - fprintf(fp, "%d,", barrier[barrier_no].after_bitmap[row][col]); - } else { - fprintf(fp, "%d\n", barrier[barrier_no].after_bitmap[row][col]); - } - } - } - } - - fclose(fp); - game_state = paused; - } + SaveGameData(); } else if (game_state == load) { - ///Creates file pointer and attaches the file - FILE *fp; - fp = fopen("/sd/game_save.txt", "r"); - rewind(fp); - - if (fp == NULL) { ///If file can't be opened then error - lcd.clear(); - lcd.printString("Error Opening", 1, 1); - wait(2.0); - - game_state = menu; - } else { - int test; - ///Prints booleans to file - fscanf(fp, "%d\n", &invaders_in_state2); - test = fscanf(fp, "%d,%d,%d,%d,%d,%d", &invader_direction, &cannon_missile_on_screen, &ufo_on_screen, &ufo_direction, &ufo_bonus, &is_muted); - - pc.printf("Bool: %d\n", test); - ///Prints integers to file - test = fscanf(fp, "%d,%d,%d,%d,%d,%d,%d,%d,%d", &score, &shot_count, &number_of_lives, &cannon_xpos, &cannon_missile_x_pos, &cannon_missile_y_pos, &no_of_alive_invaders, &down_count, &ufo_x_pos); - pc.printf("Int: %d\n", test); - ///Prints small invader info to file - for (int small = 0; small < 5; ++small) { - test = fscanf(fp, "%d,%d,%d", &(small_invader[small].x_pos), &(small_invader[small].y_pos), &(small_invader[small].status)); - pc.printf("Small: %d\n", test); - } - ///Prints medium invader info to file - for (int medium = 0; medium < 5; ++medium) { - test = fscanf(fp, "%d,%d,%d", &(medium_invader[medium].x_pos), &(medium_invader[medium].y_pos), &(medium_invader[medium].status)); - pc.printf("Medium: %d\n", test); - } - ///Prints large invader info to file - for (int large = 0; large < 5; ++large) { - test = fscanf(fp, "%d,%d,%d", &(large_invader[large].x_pos), &(large_invader[large].y_pos), &(large_invader[large].status)); - pc.printf("Large: %d\n", test); - } - ///Stores invader missile data - for (int missile = 0; missile < 2; ++missile) { - test = fscanf(fp, "%d,%d,%d", &(invader_normal_missile[missile].x_pos), &(invader_normal_missile[missile].y_pos), &(invader_normal_missile[missile].fired)); - pc.printf("Missile: %d\n", test); - } - ///Stores barrier data - for (int barrier_no = 0; barrier_no < 3; ++barrier_no) { - test = fscanf(fp, "%d,%d", &(barrier[barrier_no].x_pos), &(barrier[barrier_no].y_pos)); - pc.printf("Barrier: %d\n", test); - ///Stores barrier before bitmaps - for (int row = 0; row < 8; ++row) { - for (int col = 0; col < 14; ++col) { - if (col < 13) { - test = fscanf(fp, "%d,", &(barrier[barrier_no].before_bitmap[row][col])); - pc.printf("Barrier Before: %d\n", test); - } else { - test = fscanf(fp, "%d", &(barrier[barrier_no].before_bitmap[row][col])); - pc.printf("Barrier Before: %d\n", test); - } - } - } - ///Stores barrier after bitmaps - for (int row = 0; row < 8; ++row) { - for (int col = 0; col < 14; ++col) { - if (col < 13) { - test = fscanf(fp, "%d,", &(barrier[barrier_no].after_bitmap[row][col])); - pc.printf("Barrier After: %d\n", test); - } else { - test = fscanf(fp, "%d", &(barrier[barrier_no].after_bitmap[row][col])); - pc.printf("Barrier After: %d\n", test); - } - } - } - } - - - fclose(fp); - game_state = game; - - g_update_screen_flag = true; - g_move_joystick_flag = true; - g_move_enemies_flag = true; - g_fire_buzzer_flag = true; - } + LoadGameData(); + } else if (game_state == over) { + lcd.clear(); + GameOverScreen(); + } else if (game_state == scores) { + lcd.clear(); + ScoreScreen(); + } else if (game_state == settings) { + lcd.clear(); + fsm_state = 0; + SettingsScreen(); } sleep(); @@ -236,6 +115,7 @@ { shoot_button.mode(PullUp); shoot_button.fall(&shoot_pressed_isr); + shoot_button.rise(&shoot_pressed_rise_isr); } void update_screen_isr() @@ -254,9 +134,6 @@ if (!g_shoot_button_debounce_flag) { g_shoot_pressed_flag = true; g_shoot_button_debounce_flag = true; - - ///Attaches a timeout to clear the debounce flag 0.125 seconds after it was set - shoot_button_debounce.attach(&shoot_button_debounce_isr, 0.125); } } @@ -315,20 +192,26 @@ g_fire_buzzer_flag = true; } +void lp_wait_isr() +{ + g_lp_wait_flag = false; +} + +void shoot_pressed_rise_isr() +{ + ///Attaches a timeout to clear the debounce flag in 0.125 seconds + shoot_button_debounce.attach(&shoot_button_debounce_isr, 0.125); +} + void Game() { ///Stays within the loop while the selected state is game while (game_state == game) { pc.printf("Mute: %d\n", is_muted); - ///If the game is over detach all the tickers + ///If the game is over detach all the tickers and set game state to over if (number_of_lives == 0) { DetachTickers(); - - lcd.clear(); - lcd.printString("Game Over.", 1, 2); - char buffer[14]; - sprintf(buffer, "Score: %d", score); - lcd.printString(buffer, 1, 3); + game_state = over; } else if (no_of_alive_invaders == 0) { ///If the player wins a round ///Resets the no of alive invaders no_of_alive_invaders = 15; @@ -395,15 +278,7 @@ if (g_fire_buzzer_flag && !is_muted) { g_fire_buzzer_flag = false; - if (play_sound) { - buzzer.period(1/fsm_buzzer[buzzer_state].frequency); - buzzer.write(0.5); - play_sound = false; - } else { - buzzer.write(0); - buzzer_state = fsm_buzzer[buzzer_state].next_state; - play_sound = true; - } + PlayBuzzer(); } ///Spawns a player bullet if the shoot button is pressed and there isn't a bullet on the screen @@ -466,8 +341,9 @@ if (joystick.get_button_flag()) { joystick.set_button_flag(0); - ///Detach all game tickers + ///Detach all game tickers and turn off PWM DetachTickers(); + buzzer.write(0.0); game_state = paused; } } @@ -484,7 +360,8 @@ score = 0; number_of_lives = 3; down_count = 0; - cannon_xpos = 15; + cannon_xpos = 13; + ufo_on_screen = false; ufo_bonus = false; shot_count = 0; InitSmallInvaders(); @@ -992,8 +869,8 @@ if (ufo_bonus && shot_count == 15) { ///If the shot bonus is active and on the 15th shot, give 300 points score += 300; } else if (shot_count == 23) { ///If the shot bonus isn't active and on the 23rd shot, give 300 points and activate the bonus - ufo_bonus = true; - score += 300; + ufo_bonus = true; + score += 300; } else { ///Randomly assign score between 50, 100, 150 points score += 50 * ((rand() % 3) + 1); } @@ -1118,7 +995,13 @@ int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1; int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3; if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) { - InvaderNormalMissileHitCannon(); + ///Cannon has invunerability for 1s after getting hit + if (!g_cannon_hit_flag) { + g_cannon_hit_flag = true; + InvaderNormalMissileHitCannon(); + ///Attaches a timeout to allow cannon to be hit again + cannon_hit.attach(&cannon_hit_isr, 1); + } invader_normal_missile[missile_no].fired = false; move_invader_normal_missile[missile_no].detach(); } 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)) { @@ -1140,18 +1023,11 @@ void InvaderNormalMissileHitCannon() { ///Decrements the number of lives, pauses the game for 2 seconds - ///Marks the cannon as hit - g_cannon_hit_flag = true; ///Detaches all tickers DetachTickers(); - ///Creates a Timeout object on the stack with a period of 2 seconds to pause the game for 2 seconds - Timeout cannon_hit; - cannon_hit.attach(&cannon_hit_isr, 2); - while (g_cannon_hit_flag) { - sleep(); - } - AttachTickers(); + LPWait(2); --number_of_lives; + AttachTickers(); } ///Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation @@ -1178,10 +1054,13 @@ update_screen.detach(); move_enemies.detach(); - ///Only detaches if missiles are on the screen + ///Only detaches if are on the screen if (cannon_missile_on_screen) { move_cannon_missile.detach(); } + if (ufo_on_screen) { + move_ufo.detach(); + } for (int i = 0; i < 2; ++i) { if (invader_normal_missile[i].fired) { move_invader_normal_missile[i].detach(); @@ -1198,6 +1077,9 @@ if (cannon_missile_on_screen) { move_cannon_missile.attach(&move_cannon_missile_isr, 0.05); } + if (ufo_on_screen) { + move_ufo.attach(&move_ufo_isr, 0.1); + } for (int i = 0; i < 2; ++i) { if (invader_normal_missile[i].fired) { move_invader_normal_missile[i].attach(move_invader_normal_missile_isr[i], 0.05); @@ -1225,16 +1107,18 @@ ///If the button is pressed the selected option will appear on the screen if (g_shoot_pressed_flag) { g_shoot_pressed_flag = false; + game_state = fsm_paused[fsm_state].output; } - ///Resets the joystick flag to false if pressed + ///Returns to the game state when the joystick is pressed if (joystick.get_button_flag()) { joystick.set_button_flag(0); + + game_state = game; } lcd.refresh(); - sleep(); } } @@ -1379,4 +1263,427 @@ ufo_on_screen = false; move_ufo.detach(); } +} + +bool high_scores_sorter(const struct HighScores (&lhs), const struct HighScores (&rhs)) +{ + return lhs.score > rhs.score; +} + +void ScoreScreen() +{ + lcd.printString("High Scores", 8, 0); + lcd.drawLine(0, 7, 83, 7, 2); + + PrintHighScores(); + + lcd.printString("Back", 5, 5); + const int cursor_y_pos = 43; + lcd.drawRect(74, cursor_y_pos, 2, 2, 1); + + lcd.refresh(); + + while (game_state == scores) { + if (joystick.get_button_flag()) { + joystick.set_button_flag(0); + } + if (g_shoot_pressed_flag) { + g_shoot_pressed_flag = false; + + game_state = menu; // If the button is pressed go to the menu state + } + + sleep(); + } +} + +void PrintHighScores() +{ + ///Loops throught the high scores and prints them to the screen + for (int i = 0; i < 3; ++i) { + ///Counts how many digits are in score + int temp_score = high_scores[i].score; + int no_of_digits = 0; + do { + temp_score /= 10; + ++no_of_digits; + } while (temp_score != 0); + + ///Prints name to c-string + char buffer[14]; + sprintf(buffer, "%s", high_scores[i].name); + + ///Prints correct number of spaces to c-string + int no_of_spaces = 14 - no_of_digits; + for (int space = 3; space < no_of_spaces; ++space) { + sprintf(buffer, "%s%s", buffer, " "); + } + + ///Prints score to c-string + sprintf(buffer, "%s%d", buffer, high_scores[i].score); + lcd.printString(buffer, 0, 2 + i); + } +} + +void GameOverScreen() +{ + lcd.printString("Game Over", 18, 0); + char buffer[14]; + sprintf(buffer, "Score: %d", score); + lcd.printString(buffer, 0, 1); + + ///Save score input + if (score > high_scores[2].score) { + lcd.printString("High Score!", 0, 2); + lcd.printChar('A', 27, 3); + lcd.printChar('A', 42, 3); + lcd.printChar('A', 57, 3); + + int name[3] = {0, 0, 0}; + GetNameForScore(name); + + SaveHighScore(name); + } + + ///After high score is inputted or no high score has been reached + lcd.printString("Quit", 5, 5); + const int cursor_y_pos = 43; + lcd.drawRect(74, cursor_y_pos, 2, 2, 1); + + while (game_state == over) { + if (joystick.get_button_flag()) { + joystick.set_button_flag(0); + } + + if (g_shoot_pressed_flag) { + g_shoot_pressed_flag = false; + + game_state = menu; + } + + lcd.refresh(); + sleep(); + } +} + +void GetNameForScore(int (&name)[3]) +{ + int name_cursor_pos = 0; ///Cursor is at first letter + + while (name_cursor_pos < 3) { + ///Prints the name cursor + lcd.drawRect(27+(15*name_cursor_pos), 32, 4, 2, 1); + + if (g_shoot_pressed_flag) { + g_shoot_pressed_flag = false; + + ///Clears the name cursor and moves it + lcd.drawRect(27+(15*name_cursor_pos), 32, 4, 2, 2); + ++name_cursor_pos; + } + + if (g_move_joystick_flag) { + g_move_joystick_flag = false; + + if (joystick.GetYValue() < 0.25f) { + ///Increments the name position, if it is over 25 set it to 0 + if (++name[name_cursor_pos] > 25) { + name[name_cursor_pos] = 0; + } + } else if (joystick.GetYValue() > 0.75f) { + ///Decrements the name position, if it is under 0 set it to 25 + if (--name[name_cursor_pos] < 0) { + name[name_cursor_pos] = 25; + } + } + + lcd.printChar(name[name_cursor_pos] + 65, 27+(15*name_cursor_pos), 3); ///ASCII is offset by 65 + } + + lcd.refresh(); + sleep(); + } +} + +void SaveHighScore(const int (&name)[3]) +{ + ///Saves name and score to struct array, overwritting lowest score + for (int letter = 0; letter < 3; ++letter) { + high_scores[2].name[letter] = name[letter] + 65; + } + high_scores[2].score = score; + + ///Sorts struct array + std::sort(high_scores, high_scores + 3, &high_scores_sorter); + + ///Saves the score + std::ofstream high_score_data("/sd/high_scores.dat", std::ios::binary); + if (high_score_data.good()) { ///Checks to see if file opening was good + high_score_data.write((char *)(&high_scores), sizeof(high_scores)); + ///Flushes the buffer and saves the file + high_score_data.close(); + lcd.printString("Saved", 27, 4); + } else { + lcd.clear(); + lcd.printString("Error", 1, 1); + lcd.printString("Opening", 1, 2); + lcd.printString("File.", 1, 3); + LPWait(2); + } +} + +void SaveGameData() +{ + ///Creates the output file as a binary file + std::ofstream save_data("/sd/game_save.dat", std::ios::binary); + if (save_data.good()) { ///Checks to see if file opening was good + ///Prints booleans to file + save_data.write((char *)(&invaders_in_state2), sizeof(invaders_in_state2)); + save_data.write((char *)(&invader_direction), sizeof(invader_direction)); + save_data.write((char *)(&cannon_missile_on_screen), sizeof(cannon_missile_on_screen)); + save_data.write((char *)(&ufo_on_screen), sizeof(ufo_on_screen)); + save_data.write((char *)(&ufo_direction), sizeof(ufo_direction)); + save_data.write((char *)(&ufo_bonus), sizeof(ufo_bonus)); + + ///Prints integers to file + save_data.write((char *)(&score), sizeof(score)); + save_data.write((char *)(&shot_count), sizeof(shot_count)); + save_data.write((char *)(&number_of_lives), sizeof(number_of_lives)); + save_data.write((char *)(&cannon_xpos), sizeof(cannon_xpos)); + save_data.write((char *)(&cannon_missile_x_pos), sizeof(cannon_missile_x_pos)); + save_data.write((char *)(&cannon_missile_y_pos), sizeof(cannon_missile_y_pos)); + save_data.write((char *)(&no_of_alive_invaders), sizeof(no_of_alive_invaders)); + save_data.write((char *)(&down_count), sizeof(down_count)); + save_data.write((char *)(&ufo_x_pos), sizeof(ufo_x_pos)); + + ///Prints invaders to file + save_data.write((char *)(&small_invader), sizeof(small_invader)); + save_data.write((char *)(&medium_invader), sizeof(medium_invader)); + save_data.write((char *)(&large_invader), sizeof(large_invader)); + + ///Prints invader missiles and barriers to file + save_data.write((char *)(&invader_normal_missile), sizeof(invader_normal_missile)); + save_data.write((char *)(&barrier), sizeof(barrier)); + + ///Flushes the buffer and saves the file + save_data.close(); + } else { + lcd.clear(); + lcd.printString("Error", 1, 1); + lcd.printString("Opening", 1, 2); + lcd.printString("File.", 1, 3); + LPWait(2); + } + + game_state = paused; +} + +void LoadGameData() +{ + ///Creates the input binary file object + std::ifstream save_data("/sd/game_save.dat", std::ios::binary); + if (save_data.good()) { ///Checks to see if file opening was good + ///Gets booleans from file + save_data.read((char *)(&invaders_in_state2), sizeof(invaders_in_state2)); + save_data.read((char *)(&invader_direction), sizeof(invader_direction)); + save_data.read((char *)(&cannon_missile_on_screen), sizeof(cannon_missile_on_screen)); + save_data.read((char *)(&ufo_on_screen), sizeof(ufo_on_screen)); + save_data.read((char *)(&ufo_direction), sizeof(ufo_direction)); + save_data.read((char *)(&ufo_bonus), sizeof(ufo_bonus)); + + ///Gets integers from file + save_data.read((char *)(&score), sizeof(score)); + save_data.read((char *)(&shot_count), sizeof(shot_count)); + save_data.read((char *)(&number_of_lives), sizeof(number_of_lives)); + save_data.read((char *)(&cannon_xpos), sizeof(cannon_xpos)); + save_data.read((char *)(&cannon_missile_x_pos), sizeof(cannon_missile_x_pos)); + save_data.read((char *)(&cannon_missile_y_pos), sizeof(cannon_missile_y_pos)); + save_data.read((char *)(&no_of_alive_invaders), sizeof(no_of_alive_invaders)); + save_data.read((char *)(&down_count), sizeof(down_count)); + save_data.read((char *)(&ufo_x_pos), sizeof(ufo_x_pos)); + + ///Gets invaders from file + save_data.read((char *)(&small_invader), sizeof(small_invader)); + save_data.read((char *)(&medium_invader), sizeof(medium_invader)); + save_data.read((char *)(&large_invader), sizeof(large_invader)); + + ///Gets invader missiles and barriers from file + save_data.read((char *)(&invader_normal_missile), sizeof(invader_normal_missile)); + save_data.read((char *)(&barrier), sizeof(barrier)); + + ///Closes the file + save_data.close(); + + ///Clears the screen buffer + memset(screen_buffer, 0, sizeof(screen_buffer)); + ///Sets the game state flags + game_state = game; + g_update_screen_flag = true; + g_move_joystick_flag = true; + g_move_enemies_flag = true; + g_fire_buzzer_flag = true; + } else { + lcd.clear(); + lcd.printString("Error", 1, 1); + lcd.printString("Opening", 1, 2); + lcd.printString("File.", 1, 3); + LPWait(2); + game_state = menu; + } +} + +void LoadHighScores() +{ + ///Clears high score data before loading file + memset(high_scores, 0, sizeof(high_scores)); + ///Extracts high scores from file + std::ifstream high_score_data("/sd/high_scores.dat", std::ios::binary); + if (high_score_data.good()) { + high_score_data.read((char *)(&high_scores), sizeof(high_scores)); + } + high_score_data.close(); + ///If there are any empty names, fill them with AAA to prevent crashes using printString + for (int i = 0; i < 3; ++i) { + if (high_scores[i].name[0] < 'A') { + for (int letter = 0; letter < 3; ++letter) { + high_scores[i].name[letter] = 'A'; + } + } + } + +} + +void SettingsScreen() +{ + PrintSettingsText(); + + while (game_state == settings) { + ///Prints options and cursor + PrintSettingsOptions(); + + ///Returns to menu if joystick button is pressed + if (joystick.get_button_flag()) { + joystick.set_button_flag(0); + + game_state = menu; + } + + ///Moves the cursor when the joystick moves + if (g_move_joystick_flag) { + g_move_joystick_flag = false; + + MoveCursor(fsm_settings); + } + + if (g_shoot_pressed_flag) { + g_shoot_pressed_flag = false; + + EditOption(); + } + + lcd.refresh(); + sleep(); + } +} + +void PrintSettingsText() +{ + ///Prints the options + lcd.printString("Settings", 17, 0); + lcd.drawLine(0, 7, 83, 7, 2); + lcd.printString("Light:", 0, 2); + lcd.printString("Mute: ", 0, 3); + lcd.printString("Delete Data", 0, 4); + lcd.printString("Back", 10, 5); +} + +void PrintSettingsOptions() +{ + ///Prints the active options + char buffer[14] = {0}; + sprintf(buffer, "%d%%", (int)(100*fsm_brightness[brightness_state].output)); + pc.printf("%s\n", buffer); + lcd.printString(buffer, 42, 2); + if (is_muted) { + lcd.printString("On", 42, 3); + } else { + lcd.printString("Off", 42, 3); + } + ///Draws the cursor + 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 + lcd.drawRect(74, cursor_y_pos, 2, 2, 1); +} + +void EditOption() +{ + if (fsm_state == 0) { ///Change brightness + brightness_state = fsm_brightness[brightness_state].next_state; + lcd.setBrightness(fsm_brightness[brightness_state].output); + ///Clears displayed brightness + lcd.drawRect(42, 16, 24, 7, 2); + } else if (fsm_state == 1) { ///Mute game + is_muted = !is_muted; + } else if (fsm_state == 2) { ///Delete save data + DeleteGameData(); + ///Sets FSM list back to 0 and resets the cursor + lcd.drawRect(74, cursor_y_pos, 2, 2, 2); + fsm_state = 0; + } else if (fsm_state == 3) { + game_state = menu; + } +} + +void DeleteGameData() +{ + ///Delete game state data + std::ifstream save_data("/sd/game_save.dat", std::ios::binary); + if (save_data.good()) { + ///Close the file and remove it + save_data.close(); + remove("/sd/game_save.dat"); + } + ///Deletes high score data + std::ifstream high_scores_data("/sd/high_scores.dat", std::ios::binary); + if (high_scores_data.good()) { + ///Closes the file and remove it + high_scores_data.close(); + remove("/sd/high_scores.dat"); + } + ///Reloads high score list + LoadHighScores(); +} + +void LPWait(float t) +{ + ///Sets the wait flag + g_lp_wait_flag = true; + ///Attachs the timeout to fire at the users request then sleep + lp_wait.attach(&lp_wait_isr, t); + while (g_lp_wait_flag) { + sleep(); + } +} + +void SplashScreen() +{ + ///Prints text and waits for 3 seconds + lcd.printString("Space Invaders", 0, 1); + lcd.printString("Avinash Patel", 3, 3); + lcd.printString("200860407", 15, 4); + LPWait(3); +} + +void PlayBuzzer() +{ + if (play_sound) { + ///Sets the frequency and activates the buzzer + buzzer.period(1/fsm_buzzer[buzzer_state].frequency); + buzzer.write(0.5); + play_sound = false; + } else { + ///Deactivates the buzzer and sets the next frequency + buzzer.write(0); + buzzer_state = fsm_buzzer[buzzer_state].next_state; + play_sound = true; + } } \ No newline at end of file