ELEC2645 (2015/16)
/
Dodgemania
Wall dodging game utilising a joystick and Nokia 5110 LCD display
main.cpp
- Committer:
- el14moh
- Date:
- 2016-05-05
- Revision:
- 10:dd2886f3ac0a
- Parent:
- 9:ca800196baeb
File content as of revision 10:dd2886f3ac0a:
#include "main.h" int main() { initSerial(); // Initialises serial port srand(time(NULL)); // Generate seed for random number generation calibrateJoystick(); // Zeroes current position of joystick button.rise(&button_isr); // Attach button to ISR function button.mode(PullDown); // Select button mode initDisplay(); // Initialise LCD display initHiscores(); // Initialise highscores introScreen(); // Plays intro animation with title game_running = 0; while(1) { g_button_flag = 0; // force flag off to prevent menu items being accidently selected setTickers(10); // calls ticker functions 10 times per second (slower speed to make menu control easier) state = 0; // start on top menu item by default menu(); // Brings up game menu (Help and Scores contained in menu() function, selecting a gameplay option moves on from menu) setTickers(20); // Calls ticker functions 20 times per second playGame(); // Begins gameplay resultsScreen(); // Show final player score and previous highscore } } void moveBall() // Reads joystick direction and moves position of the player { if (joystick.direction == UP) { j-=1; } else if (joystick.direction == DOWN) { j+=1; } else if (joystick.direction == LEFT) { i-=1; } else if (joystick.direction == RIGHT) { i+=1; } else if (joystick.direction == UPRIGHT) { j-=1; i+=1; } else if (joystick.direction == UPLEFT) { j-=1; i-=1; } else if (joystick.direction == DOWNRIGHT) { j+=1; i+=1; } else if (joystick.direction == DOWNLEFT) { j+=1; i-=1; } } void moveWall() // Moves walls along the screen { // Random variables to determine if wall moves this loop or not leftwall.random = rand()%20; // 1/20 chance rightwall.random = rand()%20; downwall.random = rand()%50; // 1/50 chance upwall.random = rand()%50; // LEFT WALL if (leftwall.moveFlag == 1) { // if wall is moving leftwall.x-=1; // move wall left if (leftwall.x<8) { // if wall hits a border leftwall.moveFlag = 0; // stop wall moving leftwall.cooldown = 0; // reset the cooldown for the wall } } else { // if wall has stopped moving if (leftwall.genFlag == 0) { // if a new wall HASN'T been generated leftwall.y = rand() % 27+8; // make new random y-coordinate (note - range of random values prevents holes in the walls going beyond border) leftwall.x = 82; // reset x-coordinate to rightmost position leftwall.genFlag = 1; // wall has been generated } else { // if a new wall HAS been generated if (leftwall.cooldown > 80) { // if new wall hasnt started moving in 4 seconds, force it to move leftwall.moveFlag = 1; // start wall moving leftwall.genFlag = 0; // clear 'wall generated' flag } else if ((leftwall.random == 1)&&(rightwall.cooldown > 60)) { // else 2 second window in which wall may randomly start moving before it is forced to leftwall.moveFlag = 1; // start wall moving leftwall.genFlag = 0; // clear 'wall generated' flag } else { // else if wall has not started moving again leftwall.moveFlag = 0; // wall is stopped } } } // RIGHT WALL if (counter > 200) { // After 10 seconds of gameplay if (rightwall.moveFlag == 1) { rightwall.x+=1; // move wall right if (rightwall.x>80) { // if wall goes off right edge (accounting for border) rightwall.moveFlag = 0; rightwall.cooldown = 0; } } else { if ((rightwall.genFlag == 0)) { rightwall.y = rand() % 27+8; // random y-coordinate (note - range of random values prevents holes in the walls going beyond border) rightwall.x = 6; // moves wall back to left side rightwall.genFlag = 1; } else { if (rightwall.cooldown > 80) { rightwall.moveFlag = 1; rightwall.genFlag = 0; } else if ((rightwall.random == 1) && (leftwall.cooldown > 60)) { rightwall.moveFlag = 1; rightwall.genFlag = 0; } else { rightwall.moveFlag = 0; } } } } // DOWN WALL if (counter > 600) { // After 30 seconds of gameplay if (downwall.moveFlag == 1) { if (counter % 2 == 1) { // horizontal walls move half the speed of vertical walls downwall.y+=1; // move wall down } if (downwall.y>44) { // if wall goes off bottom edge (accounting for border) downwall.moveFlag = 0; } } else { if (downwall.genFlag == 0) { downwall.x = rand() % 52+19; // random x-coordinate (note - range of random values prevents holes in the walls going beyond border) downwall.y = 1; downwall.genFlag = 1; } else { if (downwall.cooldown > 120) { // 6s cooldown downwall.moveFlag = 1; downwall.genFlag = 0; } else if ((downwall.random == 1)&&(upwall.cooldown > 60)) { downwall.moveFlag = 1; downwall.genFlag = 0; } else { downwall.moveFlag = 0; } } } } // UP WALL if (counter > 1200) { // After 60 seconds of gameplay if (upwall.moveFlag == 1) { if (counter % 2 == 1) { // horizontal walls move half the speed of vertical walls upwall.y-=1; // move wall up } if (upwall.y<3) { // if wall goes off bottom edge (accounting for border) upwall.moveFlag = 0; } } else { if (upwall.genFlag == 0) { upwall.x = rand() % 52+19; // random x-coordinate (note - range of random values prevents holes in the walls going beyond border) upwall.y = 46; upwall.genFlag = 1; } else { if (upwall.cooldown > 120) { // 6s cooldown upwall.moveFlag = 1; upwall.genFlag = 0; } else if ((upwall.random == 1)&&(downwall.cooldown > 60)) { upwall.moveFlag = 1; upwall.genFlag = 0; } else { upwall.moveFlag = 0; } } } } } void checkBorderCollision() // Checks if player has hit border { // if floor if ( j >= 47 - (PLAYERRADIUS+3)) { j = 47 - (PLAYERRADIUS+3); // Forces player position } // if roof if ( j <= (PLAYERRADIUS+3)) { j = (PLAYERRADIUS+3); // Forces player position } // if right wall if ( i >= 83 - (PLAYERRADIUS+3)) { i = 83 - (PLAYERRADIUS+3); // Forces player position } // if left wall if ( i <= (PLAYERRADIUS+8)) { i = (PLAYERRADIUS+8); // Forces player position } } void invincible() // Briefly allows player to move through walls { if (g_button_flag) { g_button_flag = 0; if ((saves > 0) && (mortal == true)) { // Invincibility is available and not currently used saves_cool=0; mortal = false; saves_cool++; saves--; } } if (mortal == false) { saves_cool++; // Countdown variable for invincibility if (saves_cool > 30) { // Ticker called 20 times per second, therefore 1.5s of invincibility mortal = true; saves_cool=0; // Resets countdown variable } } } void checkWallCollision() // Checks for any collisions (i.e. player has hit a wall or side of the screen) { if (mortal) { // If player has not triggered invincibility // LEFT WALL // (- - - - - - - If wall has passed inside of player radius - - - - - - -) (- - If player has hit side of wall gap - -) if ((((i - PLAYERRADIUS) <= leftwall.x) && (leftwall.x <= (i + PLAYERRADIUS))) && (j > (leftwall.y+3) || j < (leftwall.y-3))) { game_running = 0; } // RIGHT WALL // (- - - - - - - If wall has passed inside of player radius - - - - - - -) (- - If player has hit side of wall gap - -) if ((((i - PLAYERRADIUS) <= rightwall.x) && (rightwall.x <= (i + PLAYERRADIUS))) && (j > (rightwall.y+3) || j < (rightwall.y-3))) { game_running = 0; } // DOWN WALL // (- - - - - - - If wall has passed inside of player radius - - - - - - -) (- - If player has hit side of wall gap - -) if ((((j - PLAYERRADIUS) <= downwall.y) && (downwall.y-1 <= (j + PLAYERRADIUS))) && (i > (downwall.x+9) || i < (downwall.x-9))) { // if player x is 4 or more than wall x, it has missed the gap game_running = 0; } // UP WALL // (- - - - - - - If wall has passed inside of player radius - - - - - - -) (- - If player has hit side of wall gap - -) if ((((j - PLAYERRADIUS) <= upwall.y+1) && (upwall.y <= (j + PLAYERRADIUS))) && (i > (upwall.x+9) || i < (upwall.x-9))) { game_running = 0; } } } void updateScreen() // refreshes the screen, redraws player and walls { lcd.clear(); if (mortal) { lcd.drawCircle(i,j,PLAYERRADIUS,1); } else { if (counter % 2 == 0) { // Make player blink if invincible lcd.drawCircle(i,j,PLAYERRADIUS,1); } } // Draws remaining invincibilty indicators if (saves > 0) { lcd.drawCircle(2,7,1,1); } if (saves > 1) { lcd.drawCircle(2,15,1,1); } if (saves > 2) { lcd.drawCircle(2,23,1,1); } if (saves > 3) { lcd.drawCircle(2,31,1,1); } if (saves > 4) { lcd.drawCircle(2,39,1,1); } // Draw border draw_border(); // Draw walls // LEFT WALL lcd.drawLine(leftwall.x,leftwall.y+5,leftwall.x,44,1); lcd.drawLine(leftwall.x,leftwall.y-5,leftwall.x,3,1); lcd.drawLine(leftwall.x+1,leftwall.y+5,leftwall.x+1,44,1); lcd.drawLine(leftwall.x+1,leftwall.y-5,leftwall.x+1,3,1); // RIGHT WALL if (counter > 200) { // After 10 seconds of gameplay lcd.drawLine(rightwall.x,rightwall.y+5,rightwall.x,44,1); lcd.drawLine(rightwall.x,rightwall.y-5,rightwall.x,3,1); lcd.drawLine(rightwall.x-1,rightwall.y+5,rightwall.x-1,44,1); lcd.drawLine(rightwall.x-1,rightwall.y-5,rightwall.x-1,3,1); } // DOWN WALL if (counter > 600) { // After 30 seconds of gameplay lcd.drawLine(downwall.x+11,downwall.y,80,downwall.y,1); lcd.drawLine(downwall.x-11,downwall.y,8,downwall.y,1); lcd.drawLine(downwall.x+11,downwall.y-1,80,downwall.y-1,1); lcd.drawLine(downwall.x-11,downwall.y-1,8,downwall.y-1,1); } // UP WALL if (counter > 1200) { // After 60 seconds of gameplay lcd.drawLine(upwall.x+11,upwall.y,80,upwall.y,1); lcd.drawLine(upwall.x-11,upwall.y,8,upwall.y,1); lcd.drawLine(upwall.x+11,upwall.y+1,80,upwall.y+1,1); lcd.drawLine(upwall.x-11,upwall.y+1,8,upwall.y+1,1); } // Flash screen if a wall is about to appear from a new direction if (counter == 170) { lcd.inverseMode(); } else if (counter == 570) { lcd.inverseMode(); } else if (counter == 1470) { lcd.inverseMode(); } else { lcd.normalMode(); } lcd.refresh(); } void gameTicker_isr() // Sets flag for timer interrupt { g_timer_flag = 1; } void button_isr() // Sets flag for button interrupt { g_button_flag = 1; } void initDisplay() // initialises the LCD display { lcd.init(); wait(0.5); // wait for LCD to initialise lcd.normalMode(); lcd.setBrightness(1.0F-backlight); // brightness pot on PCB is soldered in the wrong direction, (1.0F-backlight) inverts the reading } void calibrateJoystick() // Read default positions of the joystick to calibrate later readings { button.mode(PullDown); // Must not move during calibration joystick.x0 = xPot; // Initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) joystick.y0 = yPot; } void updateJoystick() // Reads direction the joystick has been moved { // Read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred) joystick.x = xPot - joystick.x0; joystick.y = yPot - joystick.y0; // Read button state joystick.button = button; // Calculate direction depending on x,y values // Tolerance allows a little lee-way in case joystick not exactly in the stated direction if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = CENTRE; } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = UP; } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = DOWN; } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = LEFT; } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = RIGHT; } else if ( joystick.y > DIRECTION_TOLERANCE && joystick.x > DIRECTION_TOLERANCE) { joystick.direction = UPLEFT; } else if ( joystick.y > DIRECTION_TOLERANCE && joystick.x < DIRECTION_TOLERANCE) { joystick.direction = UPRIGHT; } else if ( joystick.x > DIRECTION_TOLERANCE && joystick.y < DIRECTION_TOLERANCE) { joystick.direction = DOWNLEFT; } else if ( joystick.x < DIRECTION_TOLERANCE && joystick.y < DIRECTION_TOLERANCE) { joystick.direction = DOWNRIGHT; } else { joystick.direction = UNKNOWN; } } void initSerial() // Sets baud rate for serial { serial.baud(115200); } void initGame() // Initialises gameplay variables { g_button_flag = 0; leftwall.y = rand() % 27+8; leftwall.x = 82; rightwall.y = rand() % 27+8; rightwall.x = 6; downwall.x = rand() % 52+19; downwall.y = 0; upwall.x = rand() % 52+19; upwall.y = 0; rightwall.cooldown = 61; counter = 0; score = 0; saves = 5; i = 42; j = 24; } void flash() // Produces a brief flash on screen { lcd.inverseMode(); wait(0.2); lcd.normalMode(); } void printHelp() // Prints instructions { while (1) { lcd.printString("Try and",0,1); lcd.printString("survive for",0,2); lcd.printString("as long as ",0,3); lcd.printString("possible!",0,4); lcd.refresh(); if (g_button_flag) { playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } g_button_flag = 0; while(1) { lcd.printString("Get through",0,1); lcd.printString("the holes in",0,2); lcd.printString("the walls with",0,3); lcd.printString("the joystick",0,4); lcd.refresh(); if (g_button_flag) { playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } g_button_flag = 0; while(1) { lcd.printString("Press the",0,1); lcd.printString("stick to",0,2); lcd.printString("be briefly",0,3); lcd.printString("untouchable",0,4); lcd.refresh(); if (g_button_flag) { playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } g_button_flag = 0; while(1) { lcd.printString("But don't use",0,1); lcd.printString("it too much!",0,2); lcd.printString("you can only",0,3); lcd.printString("do it 5 times",0,4); lcd.refresh(); if (g_button_flag) { playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } g_button_flag = 0; while(1) { lcd.printString("Lastly, keep",0,1); lcd.printString("an eye on the",0,2); lcd.printString("borders of",0,3); lcd.printString("the screen...",0,4); lcd.refresh(); if (g_button_flag) { playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } g_button_flag = 0; while(1) { lcd.printString("See where the",0,1); lcd.printString("holes are",0,2); lcd.printString("before the",0,3); lcd.printString("walls move!",0,4); lcd.refresh(); if (g_button_flag) { g_button_flag = 0; playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } } void printScores() // Prints previous scores { while(1) { lcd.printString("Highscores",13,0); lcd.printString("1st:",6,2); lcd.printString("2nd:",6,3); lcd.printString("3rd:",6,4); char first[14]; char second[14]; char third[14]; int one = sprintf(first,"%d",hiscore.one); int two = sprintf(second,"%d",hiscore.two); int three = sprintf(third,"%d",hiscore.three); lcd.printString(first,30,2); lcd.printString(second,30,3); lcd.printString(third,30,4); lcd.refresh(); if (g_button_flag) { g_button_flag = 0; playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } } void draw_border() // Draws game border { lcd.drawLine(7,2,81,2,1); lcd.drawLine(7,2,7,45,1); lcd.drawLine(81,2,81,45,1); lcd.drawLine(7,45,81,45,1); lcd.drawLine(5,0,83,0,1); lcd.drawLine(5,0,5,47,1); lcd.drawLine(83,0,83,47,1); lcd.drawLine(5,47,83,47,1); lcd.drawRect(6,0,1,2,1); lcd.drawRect(6,45,1,2,1); lcd.drawRect(81,0,1,2,1); lcd.drawRect(81,45,1,2,1); lcd.refresh(); } void calculateHighscores() // Determines if player score is a new highscore { if (score > hiscore.one) { hiscore.three = hiscore.two; hiscore.two = hiscore.one; hiscore.one = score; } else if ((hiscore.one > score)&&(score > hiscore.two)) { hiscore.three = hiscore.two; hiscore.two = score; } else if ((hiscore.two > score)&&(score > hiscore.three)) { hiscore.three = score; } } void initHiscores() // Initialises highscores { hiscore.one = 0; hiscore.two = 0; hiscore.three = 0; } void playNote(int freq, float time) // Plays a tone of specific frequency and duration { if(backlight < 0.5F) { // Use potentiometer to switch sound on and off buzzer.period(1.0/freq); buzzer.write(0.0); buzzer.write(0.5); wait(time); buzzer.write(0.0); } else { // If muted wait(time); // Wait included so that function still takes the same time to execute } } void countdown() // Countdown for start of game { wait(0.5); lcd.printString("3",40,2); playNote(NOTE_C4,0.2); wait(0.3); lcd.drawRect(10,10,64,28,2); lcd.refresh(); wait(0.5); lcd.printString("2",40,2); playNote(NOTE_C4,0.2); wait(0.3); lcd.drawRect(10,10,64,28,2); lcd.refresh(); wait(0.5); lcd.printString("1",40,2); playNote(NOTE_C4,0.2); wait(0.3); lcd.drawRect(10,10,64,28,2); lcd.refresh(); wait(0.5); lcd.drawRect(10,10,64,28,2); lcd.refresh(); lcd.printString("Go!",36,2); playNote(NOTE_G4,0.5); lcd.drawRect(10,10,64,28,2); lcd.refresh(); } void introScreen() // Introduction animation { wait (1.0); lcd.printString("Dodgemania",13,2); // Print game title on screen wait (2.5); for (int z=0; z<88; z++) { lcd.drawCircle(z,20,4,1); lcd.clearPixel(z-3,16); lcd.clearPixel(z-4,17); lcd.clearPixel(z-4,18); lcd.clearPixel(z-5,19); lcd.clearPixel(z-5,20); lcd.clearPixel(z-5,21); lcd.clearPixel(z-4,22); lcd.clearPixel(z-4,23); lcd.clearPixel(z-3,24); lcd.refresh(); wait(0.01); } lcd.clear(); wait(0.5); flash(); } void proceed() // Moves to selected menu option { if (menu_item == 1) { playNote(NOTE_B2,0.1); initGame(); game_running = 1; } else if (menu_item == 2) { playNote(NOTE_B2,0.1); initGame(); counter = 1200; // Note - initGame must be called here as calling it after the menu loop will reset the counter, ergo no hard mode game_running= 1; } else if (menu_item == 3) { playNote(NOTE_B2,0.1); flash(); lcd.clear(); printHelp(); } else if (menu_item == 4) { playNote(NOTE_B2,0.1); flash(); lcd.clear(); printScores(); } } void setTickers(int speed) // Dettaches tickers and reattaches them with specified speed { gameTicker.detach(); gameTicker.attach(&gameTicker_isr,1.0/speed); pollJoystick.detach(); pollJoystick.attach(&updateJoystick,1.0/speed); } void congratulate() // Congratulates player if they got a highscore { if (score >= hiscore.one) { // New highscore wait(1.0); lcd.printString("HIGHSCORE!",13,5); // Highscore melody playNote(NOTE_E3,0.1); wait(0.1); playNote(NOTE_C3,0.05); wait(0.05); playNote(NOTE_C3,0.05); wait(0.05); playNote(NOTE_C3,0.05); wait(0.15); playNote(NOTE_G3,0.1); wait(0.1); playNote(NOTE_E3,0.1); wait(0.1); playNote(NOTE_G3,0.1); wait(0.1); playNote(NOTE_C4,0.5); wait(0.1); lcd.printString("CONGRATS!!",13,5); playNote(NOTE_E2,0.2); } else if ((score >= hiscore.two) && (score < hiscore.one)) { // Second place // Endgame melody playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.3); } else if ((score >= hiscore.three) && (score < hiscore.two)) { // Third place // Endgame melody playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.3); } else { // No highscore // Endgame melody playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.05); wait(0.05); playNote(NOTE_A2,0.3); } } void menu() { while(game_running == 0) { // If game is not started if (g_timer_flag) { g_timer_flag = 0; if ((joystick.direction == UP)||(joystick.direction == UPRIGHT)||(joystick.direction == UPLEFT)) { menu_direction = 2; } else if ((joystick.direction == DOWN)||(joystick.direction == DOWNRIGHT)||(joystick.direction == DOWNLEFT)) { menu_direction = 1; } else { menu_direction = 0; } menu_item = fsm[state].output; // Which menu item the cursor is on state = fsm[state].next_state[menu_direction]; // Moves up or down the menu, or stays on the same item, depending on joystick direction lcd.clear(); lcd.printString("Start Easy",12,1); lcd.printString("Start Hard",12,2); lcd.printString("Help",12,3); lcd.printString("Scores",12,4); // Place cursor next to appropriate menu item if (menu_item == 1) { lcd.drawCircle(6,11,2,1); } else if (menu_item == 2) { lcd.drawCircle(6,19,2,1); } else if (menu_item == 3) { lcd.drawCircle(6,27,2,1); } else { lcd.drawCircle(6,35,2,1); } lcd.refresh(); if (((menu_direction == 1)&&(menu_item != 4))||((menu_direction == 2)&&(menu_item != 1))) { playNote(NOTE_G2,0.05); // Menu scrolling sound } if (g_button_flag) { // If button press g_button_flag = 0; if (menu_item == 1) { playNote(NOTE_B2,0.1); initGame(); game_running = 1; } else if (menu_item == 2) { playNote(NOTE_B2,0.1); initGame(); counter = 1200; // Note - initGame must be called here as calling it after the menu loop will reset the counter, ergo no hard mode game_running= 1; } else if (menu_item == 3) { playNote(NOTE_B2,0.1); flash(); lcd.clear(); printHelp(); } else if (menu_item == 4) { playNote(NOTE_B2,0.1); flash(); lcd.clear(); printScores(); } } } } // When one of the two gameplay options are selected, the loop is broken and moves onto countdown/gameplay flash(); lcd.clear(); draw_border(); // Draw game border countdown(); // Countdown to game start } void playGame() { while (game_running == 1) { // Gameplay loop if ( g_timer_flag ) { // Ticker interrupt g_timer_flag = 0; // Clear flag moveWall(); // Move wall obstacles across screen moveBall(); // Move player invincible(); // Check if invincibility has been enabled checkBorderCollision(); // Check if player has hit a border checkWallCollision(); // Check if player has hit a wall updateScreen(); // Redraw screen with new object positions counter++; // Increment counter each cycle (approx. 20 points a second) score++; // This is seperate from counter for the purposes of keeping score 0 when Hard Start is selected to allow 4 walls from the start // Increase wall cooldown variable leftwall.cooldown++; rightwall.cooldown++; downwall.cooldown++; upwall.cooldown++; } sleep(); // Put processor to sleep till next interrupt } // Briefly freezes screen and plays game-over melody if player hits wall flash(); playNote(NOTE_E4,0.1); playNote(NOTE_C4,0.1); playNote(NOTE_A3,0.1); playNote(NOTE_A2,0.3); wait(0.9); lcd.clear(); wait(0.2); } void resultsScreen() { calculateHighscores(); // Determines if player has a new highscore lcd.printString("Game Over!",14,0); lcd.refresh(); wait(1.0); lcd.printString("HiScore:",3,3); lcd.printString("Score:",3,2); char score_buffer[14]; char hiscore_buffer[14]; int length_one = sprintf(score_buffer,"%d",score); int length_two = sprintf(hiscore_buffer,"%d",hiscore.one); if (score <= 9999) { // 9999 is highest number that fits on screen lcd.printString(score_buffer,54,2); lcd.printString(hiscore_buffer,54,3); } else { lcd.printString ("Wow!",54,2); // if score is too large to fit in box, print text instead (would require 8.3 minutes of gameplay...) lcd.printString ("Wow!",54,3); } lcd.refresh(); congratulate(); // Congratulates the player if they have a new highscore lcd.refresh(); while(1) { // Remain on screen until button is pressed if (g_button_flag) { g_button_flag = 0; playNote(NOTE_E2,0.1); flash(); lcd.clear(); break; } } }