Snake and Physics based jumping game with high scores and different difficulties.

Dependencies:   N5110 SDFileSystem mbed

Revision:
5:ae641b1d04fa
Parent:
4:c2d920b17b14
--- a/main.cpp	Wed Apr 27 12:43:34 2016 +0000
+++ b/main.cpp	Wed May 04 15:01:20 2016 +0000
@@ -3,7 +3,7 @@
 @file main.cpp
 
 @brief Program Implementation
-@brief Revision 1.0
+@brief Revision 1.1
 @author Joel W. Webb
 */
 
@@ -30,21 +30,23 @@
     DirectionName direction;  // current direction
 };
 typedef struct JoyStick Joystick;
-/// Joystick struct for storing data about default Joystick position and Current position
+/// Global Joystick struct for storing data about default Joystick position and Current position
 Joystick joystick;
+
 /// Ticker interrput for polling the joystick
 Ticker pollJoystick;
 /// Ticker for controlling refresh rate of games
 Ticker gametick;
+/// Ticker for sctrolling the refresh rate of the display
+Ticker screentick;
 /// File pointer for accessing SD card locations
-FILE *fp;
+FILE *fp = NULL;
 
 
 int main()
 {
     initInputs();
     playSound(tune_intro);
-    // Initialise file pointer
 
     int snakeDifficulty = 1;
     int plinkDifficulty = 0;
@@ -84,7 +86,7 @@
                         lcd.printString("No Results",0,0);
                         wait(2.0);
                     } else {  // opened file so can write
-                        while ( ! (g_buttonA_flag || g_buttonjoy_flag)) {
+                        while ( ! (g_buttonA_flag | g_buttonjoy_flag)) {
                             fscanf(fp,"%d",&stored_top_score); // ensure data type matches - note address operator (&)
                             fclose(fp);  // ensure you close the file after reading
                             lcd.printString("Highscore:",10,0);
@@ -108,6 +110,7 @@
 
         // Selected Plink
         else if (select == 1) {
+            
             // If select = 3 or -1 then user has chosen 'Back' button
             while( !(select == 3 || select ==-1) ) {
 
@@ -156,10 +159,7 @@
                 }
             }
         }
-
-        sleep();
     }
-
 }
 
 
@@ -310,10 +310,12 @@
 
     // Appropriate strings printed to LCD
     lcd.printString("Game Over",20,0);
-    if (current_high_score != -1 && current_high_score < score) {
+    if (current_high_score == -2) {
+        lcd.printString("New High Score:",0,1);
+    } else if (current_high_score != -1 && current_high_score < score) {
         lcd.printString("New High Score",0,1);
         lcd.printString("Previously",0,3);
-    } else if (current_high_score != -1 && current_high_score > score) {
+    } else if (current_high_score != -1 && current_high_score >= score) {
         lcd.printString("Score",0,1);
         lcd.printString("High Score",0,3);
     } else {
@@ -325,7 +327,7 @@
     sprintf(buffer,"%d",score);
     lcd.printString(buffer,20,2);
     // Print previous high-score
-    if (current_high_score != -1) {
+    if (current_high_score != -1 && current_high_score != -2) {
         char str[14];
         sprintf(str,"%d",current_high_score);
         lcd.printString(str,20,4);
@@ -352,16 +354,19 @@
 
     // Initialise plink variables
     pvar = initpvar(pvar);
-
     // Game ticker
     int refreshRate = 100;
     float tickerDelay = 1.0/refreshRate;
     pvar.tickerDelay = tickerDelay;
     gametick.attach(&gametick_isr,tickerDelay);
+    // Update screen 30 fps
+    tickerDelay = 1.0/30.0;
+    screentick.attach(&screentick_isr,tickerDelay);
     wait(0.25);
 
     while(!pvar.gameOver) {
         if (g_gametick_flag) {
+            g_gametick_flag = 0;
 
             // Screen scrolling
             pvar = plinkScroll(pvar);
@@ -381,10 +386,10 @@
 
     gametick.detach();
     lcd.clear();
-    
+
     // Handle high scores and printing game over messages to LCD
     pvar = plinkGameOver(pvar);
-    
+
 }
 
 plinkvar initpvar(plinkvar pvar)
@@ -526,7 +531,7 @@
             default:
                 error();
         }
-    } 
+    }
     // If the powerup has been missed then generate new one
     else if (pvar.powerUp.y > 47+pvar.powerUpRadius) {
         pvar.powerUp.x = rand()%(84-1-(pvar.powerUpRadius*2)) + pvar.powerUpRadius;
@@ -571,75 +576,79 @@
 }
 plinkvar plinkDrawScreen(plinkvar pvar)
 {
-    // Drawing on lcd
-    lcd.clear();
-    // Drawing ball/blob
-    // If second blob stage
-    int noPlatform = 1;
-    if (pvar.ballRadius == 2) {
+    if (g_screentick_flag) {
+        g_screentick_flag = 0;
+        // Drawing on lcd
+        lcd.clear();
+        // Print Current Score
+        char buffer[14];
+        sprintf(buffer,"Score: %d",pvar.height);
+        lcd.printString(buffer,0,0);
+        // Drawing ball/blob
+        // If second blob stage
+        int noPlatform = 1;
+        if (pvar.ballRadius == 2) {
+            for (int i=0; i<20; i++) {
+                if (  (int)pvar.pos.y == (pvar.platforms[i].y - 2)  &&  (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2  &&  (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2   ) {
+                    noPlatform = 0;
+                    lcd.drawRect(pvar.pos.x-2,pvar.pos.y-1,4,2,1); // X, Y, Width, Height, Fill
+                    lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x-3,pvar.pos.y+1);
+                    lcd.setPixel(pvar.pos.x+3,pvar.pos.y+1);
+                }
+                // If third blob stage
+                else if ( (int)pvar.pos.y == (pvar.platforms[i].y - 1)  &&  (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2  &&  (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2  ) {
+                    noPlatform = 0;
+                    lcd.drawRect(pvar.pos.x-3,pvar.pos.y-1,6,1,1); // X, Y, Width, Height, Fill
+                    lcd.setPixel(pvar.pos.x-4,pvar.pos.y);
+                    lcd.setPixel(pvar.pos.x+4,pvar.pos.y);
+                    lcd.setPixel(pvar.pos.x-2,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2);
+                    lcd.setPixel(pvar.pos.x+2,pvar.pos.y-2);
+                }
+            }
+        }
+        // Else default blob stage
+        if (noPlatform == 1) {
+            lcd.drawCircle((int)pvar.pos.x,(int)pvar.pos.y,pvar.ballRadius,1); // X, Y, Radius, Fill
+            lcd.refresh();
+        }
+        // Platforms and boundaries drawing
         for (int i=0; i<20; i++) {
-            if (  (int)pvar.pos.y == (pvar.platforms[i].y - 2)  &&  (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2  &&  (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2   ) {
-                noPlatform = 0;
-                lcd.drawRect(pvar.pos.x-2,pvar.pos.y-1,4,2,1); // X, Y, Width, Height, Fill
-                lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x-3,pvar.pos.y+1);
-                lcd.setPixel(pvar.pos.x+3,pvar.pos.y+1);
+            if (pvar.platforms[i].y > 0) {
+                lcd.drawRect( pvar.platforms[i].x-pvar.platformWidth ,pvar.platforms[i].y,pvar.platformWidth*2,1,1); // X, Y, Width, Height, Fill
             }
-            // If third blob stage
-            else if ( (int)pvar.pos.y == (pvar.platforms[i].y - 1)  &&  (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2  &&  (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2  ) {
-                noPlatform = 0;
-                lcd.drawRect(pvar.pos.x-3,pvar.pos.y-1,6,1,1); // X, Y, Width, Height, Fill
-                lcd.setPixel(pvar.pos.x-4,pvar.pos.y);
-                lcd.setPixel(pvar.pos.x+4,pvar.pos.y);
-                lcd.setPixel(pvar.pos.x-2,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2);
-                lcd.setPixel(pvar.pos.x+2,pvar.pos.y-2);
-            }
+        }
+        lcd.drawLine(0,0,0,47,1); // x0,y0,x1,y1,type
+        lcd.drawLine(83,0,83,47,1);
+        // PowerUp drawing
+        if (pvar.powerUp.y > 0-pvar.powerUpRadius && pvar.powerUp.y < 47+pvar.powerUpRadius) {
+            lcd.drawRect(pvar.powerUp.x-pvar.powerUpRadius,pvar.powerUp.y-pvar.powerUpRadius,10,10,0); // X, Y, Width, Height, Fill
+            lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+3);
+            lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+1);
+            lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y);
+            lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-1);
+            lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-2);
+            lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y-3);
+            lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y-3);
+            lcd.setPixel(pvar.powerUp.x-1,pvar.powerUp.y-3);
+            lcd.setPixel(pvar.powerUp.x-2,pvar.powerUp.y-2);
+        }
+
+        lcd.refresh();
+        // Looks more pleasing when the ball pauses to bounce
+        if (noPlatform == 0) {
+            wait(0.03);
         }
     }
-    // Else default blob stage
-    if (noPlatform == 1) {
-        lcd.drawCircle((int)pvar.pos.x,(int)pvar.pos.y,pvar.ballRadius,1); // X, Y, Radius, Fill
-        lcd.refresh();
-    }
-    // Platforms and boundaries drawing
-    for (int i=0; i<20; i++) {
-        if (pvar.platforms[i].y > 0) {
-            lcd.drawRect( pvar.platforms[i].x-pvar.platformWidth ,pvar.platforms[i].y,pvar.platformWidth*2,1,1); // X, Y, Width, Height, Fill
-        }
-    }
-    lcd.drawLine(0,0,0,47,1); // x0,y0,x1,y1,type
-    lcd.drawLine(83,0,83,47,1);
-    // PowerUp drawing
-    if (pvar.powerUp.y > 0-pvar.powerUpRadius && pvar.powerUp.y < 47+pvar.powerUpRadius) {
-        lcd.drawRect(pvar.powerUp.x-pvar.powerUpRadius,pvar.powerUp.y-pvar.powerUpRadius,10,10,0); // X, Y, Width, Height, Fill
-        lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+3);
-        lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+1);
-        lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y);
-        lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-1);
-        lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-2);
-        lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y-3);
-        lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y-3);
-        lcd.setPixel(pvar.powerUp.x-1,pvar.powerUp.y-3);
-        lcd.setPixel(pvar.powerUp.x-2,pvar.powerUp.y-2);
-    }
-
-    lcd.refresh();
-    // Looks more pleasing when the ball pauses to bounce
-    if (noPlatform == 0) {
-        wait(0.03);
-    }
-    char buffer[14];
-    sprintf(buffer,"Score: %d",pvar.height); 
-    lcd.printString(buffer,0,0);
-    
     return pvar;
 }
-plinkvar plinkGameOver(plinkvar pvar){
+plinkvar plinkGameOver(plinkvar pvar)
+{
     // Handle saving high scores to SD card
     // Read previous highscore if one exists
     fp = fopen("/sd/plinkhighscore.txt", "r");
@@ -665,11 +674,13 @@
 
     // Appropriate strings printed to LCD
     lcd.printString("Game Over",20,0);
-    if (current_high_score != -1 && current_high_score < pvar.height) {
+    if (current_high_score == -2) {
+        lcd.printString("New High Score:",0,1);
+    } else if (current_high_score != -1 && current_high_score < pvar.height) {
         lcd.printString("New High Score",0,1);
         lcd.printString("Previously",0,3);
-    } else if (current_high_score != -1 && current_high_score > pvar.height) {
-        lcd.printString("Score",0,1);
+    } else if (current_high_score != -1 && current_high_score >= pvar.height) {
+        lcd.printString("Score:",0,1);
         lcd.printString("High Score",0,3);
     } else {
         lcd.printString("Score:",0,1);
@@ -680,7 +691,7 @@
     sprintf(buffer,"%d",pvar.height);
     lcd.printString(buffer,20,2);
     // Print previous high-score
-    if (current_high_score != -1) {
+    if (current_high_score != -1 && current_high_score != -2) {
         char str[14];
         sprintf(str,"%d",current_high_score);
         lcd.printString(str,20,4);
@@ -714,6 +725,10 @@
 {
     g_gametick_flag = 1;
 }
+void screentick_isr()
+{
+    g_screentick_flag = 1;
+}
 
 
 // Initialises Inputs
@@ -734,6 +749,7 @@
     /// Testing LCD display works (splash screen)
     lcd.init();
     wait(0.5);
+    lcd.setBrightness(0.5); // Brightness set to maximum duty cycle so it isn't affected by changing frequency of buzzer
     lcd.printString("Calibrating",8,0);
     lcd.printString("Do not move",8,1);
     lcd.printString("Joystick",18,2);
@@ -743,14 +759,43 @@
     calibrateJoystick();
     /// read joystick 10 times per second
     pollJoystick.attach(&updateJoystick,1.0/10.0);
-    // Patch for sd casrd access not working first time
-    fp = fopen("sd/test.txt","w");
+
+    // Patch for sd card access not working first time
+    fp = fopen("/sd/test.txt", "w");
     if (fp != NULL) {
         fclose(fp);
     }
+    fp = fopen("/sd/test.txt", "w");
+    if (fp != NULL) {
+        fclose(fp);  // ensure you close the file after writing
+    }
+
+    // If file does not exist then create it
+    fp = fopen("/sd/plinkhighscore.txt","r");
+    if (fp == NULL) {
+        fp = fopen("/sd/plinkhighscore.txt","w");
+        if (fp != NULL) {
+            fprintf(fp,"%d",-2);
+            fclose(fp);
+        }
+    } else {
+        fclose(fp);
+    }
+
+    fp = fopen("/sd/snakehighscore.txt","r");
+    if (fp == NULL) {
+        fp = fopen("/sd/snakehighscore.txt","w");
+        if (fp != NULL) {
+            fprintf(fp,"%d",-2);
+            fclose(fp);
+        }
+    } else {
+        fclose(fp);
+    }
+
     wait(1.0);
-    lcd.clear();
 }
+
 // Hangs on an error
 void error()
 {