Dependencies:   N5110 SDFileSystem mbed

Files at this revision

API Documentation at this revision

Comitter:
el14jw
Date:
Wed May 04 15:01:20 2016 +0000
Parent:
4:c2d920b17b14
Commit message:
Snake and Physics based jumping game

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
sounds.h Show annotated file Show diff for this revision Revisions of this file
diff -r c2d920b17b14 -r ae641b1d04fa main.cpp
--- 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()
 {
diff -r c2d920b17b14 -r ae641b1d04fa main.h
--- a/main.h	Wed Apr 27 12:43:34 2016 +0000
+++ b/main.h	Wed May 04 15:01:20 2016 +0000
@@ -2,7 +2,7 @@
 @file main.h
 
 @brief Header file containing functions prototypes, defines and global variables.
-@brief Revision 1.0.
+@brief Revision 1.1
 @author Joel W. Webb
 @date   March 2016
 */
@@ -109,7 +109,7 @@
 };
 typedef vector vector;
 
-
+/// plinkvar struct is used to pass information to and from the plink functions without resorting to many global variables
 struct plinkvar {
         int difficulty;
         vector pos;
@@ -135,7 +135,7 @@
 volatile int g_buttonjoy_flag; /*!< Joystick Button flag set in ISR */
 volatile int g_joystick_flag; /*!< Joystick x and y values have been polled in ISR */
 volatile int g_gametick_flag; /*!< gametick flag is set in gametick_isr by Ticker gametick */
- 
+volatile int g_screentick_flag; /*!< screentick flag is set in screentick_isr by Ticker screentick */
 volatile const float* noteArray; /*!< Float pointer to next note in array. Used in sound Timeout ISR */
 
 // Menu stringList arrays kept in FLASH
@@ -176,6 +176,11 @@
 @brief Used to control the update speed of games
 */
 void gametick_isr();
+/**
+Interrupt service routine for Ticker screentick
+@brief Used to control the update speed of the LCD display
+*/
+void screentick_isr();
 
 
     // Snake functions
diff -r c2d920b17b14 -r ae641b1d04fa sounds.h
--- a/sounds.h	Wed Apr 27 12:43:34 2016 +0000
+++ b/sounds.h	Wed May 04 15:01:20 2016 +0000
@@ -2,7 +2,7 @@
 @file sounds.h
 
 @brief Header file for containing defines of note frequencies and sound arrays
-@brief Revision 1.0.
+@brief Revision 1.1
 @author Joel W. Webb
 @date March 2016
 */