Completed Snake Program

Dependencies:   N5110 PinDetect PowerControl mbed

Fork of DocTest by Craig Evans

Files at this revision

API Documentation at this revision

Comitter:
MBirney
Date:
Fri May 01 08:53:21 2015 +0000
Parent:
8:b857684a3983
Child:
10:dbcb96fa049d
Commit message:
Snake Wokring (buzzer function added)

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
--- a/main.cpp	Thu Apr 30 20:53:56 2015 +0000
+++ b/main.cpp	Fri May 01 08:53:21 2015 +0000
@@ -17,13 +17,14 @@
     HARD,
 };
 
+// create enumerated type (0,1 for Game Mode)
 enum GameMode {
     CLASSIC,
     BOUNDARY,
 };
 
 Difficulty currentDifficulty=EASY;// initialise to easy mode
-GameMode   selectedGameMode=CLASSIC;
+GameMode   selectedGameMode=CLASSIC; //initialise to Classic Mode
 
 // struct for Joystick
 typedef struct JoyStick Joystick;
@@ -112,10 +113,11 @@
     lcd.printString("Easy",20,3);
     lcd.printString("Medium",20,4);
     lcd.printString("Hard",20,5);
-    lcd.refresh();
+
     lcd.drawCircle(10,27,2,1);
     lcd.drawCircle(10,35,2,0);
     lcd.drawCircle(10,43,2,0);
+    lcd.refresh();
 
     gameSpeed= 1.0/5; // set easy game speed(for game time)
 }
@@ -128,11 +130,12 @@
     lcd.printString("Easy",20,3);
     lcd.printString("Medium",20,4);
     lcd.printString("Hard",20,5);
-    lcd.refresh();
+
     lcd.drawCircle(10,27,2,0);
     lcd.drawCircle(10,35,2,1);
     lcd.drawCircle(10,43,2,0);
     gameSpeed=1.0/7; // set medium game speed
+    lcd.refresh();
 }
 
 void hardSelected() // display when hard is selected
@@ -144,14 +147,15 @@
     lcd.printString("Easy",20,3);
     lcd.printString("Medium",20,4);
     lcd.printString("Hard",20,5);
-    lcd.refresh();
+
     lcd.drawCircle(10,27,2,0);
     lcd.drawCircle(10,35,2,0);
     lcd.drawCircle(10,43,2,1);
+    lcd.refresh();
     gameSpeed=1.0/12; // set hard game speed
 }
 
-void classicModeSelected()
+void classicModeSelected() //display when classic mode selected
 {
 
 
@@ -161,32 +165,34 @@
     lcd.printString("Game Mode:",2,1);
     lcd.printString("Classic",20,3);
     lcd.printString("Boundary",20,4);
-    lcd.refresh();
+
     lcd.drawCircle(10,27,2,1);
     lcd.drawCircle(10,35,2,0);
+    lcd.refresh();
 
 }
 
-void boundaryModeSelected()
+void boundaryModeSelected() // display when boundary mode selected
 {
-    selectedGameMode=BOUNDARY;
+    selectedGameMode=BOUNDARY;//update selecected game mode
     lcd.clear();
     lcd.printString("Please Select",2,0);
     lcd.printString("Game Mode:",2,1);
     lcd.printString("Classic",20,3);
     lcd.printString("Boundary",20,4);
-    lcd.refresh();
+
     lcd.drawCircle(10,27,2,0);
     lcd.drawCircle(10,35,2,1);
+    lcd.refresh();
 
 }
 
 
-void checkSelectedGameMode()
+void checkSelectedGameMode()// updates selected game mode menu depending on joystick direction
 {
 
     switch(selectedGameMode) {
-        case CLASSIC://classicMode;
+        case CLASSIC:
 
             switch (joystick.direction) {
 
@@ -285,9 +291,9 @@
 
 void startingSnake()
 {
-    snakeX.resize(5);
-    snakeY.resize(5);
-    snakeX[0]=20;
+    snakeX.resize(5); // ensure that when game is reset snake vectors are resized back to 5
+    snakeY.resize(5);//
+    snakeX[0]=20; // initial snake position
     snakeX[1]=22;
     snakeX[2]=24;
     snakeX[3]=26;
@@ -300,8 +306,8 @@
 
 
     for (int i=0; i<5; i++) {
-        // lcd.setPixel(snakeX[i],snakeY[i]);
-        lcd.drawRect(snakeX[i],snakeY[i],1,1,1);
+
+        lcd.drawRect(snakeX[i],snakeY[i],1,1,1); // snake is 2X2 pixels so draw rect with one width and 1 height
     }
 
 }
@@ -312,9 +318,9 @@
 //   http://stackoverflow.com/questions/3383286/create-a-random-even-number-between-range
 
 
-    srand(time(NULL));
+    srand(time(NULL)); // using time as a seed for rand
 
-    int randomX = 2 * (1 + rand() % (40 - 1 + 1)) ; //generate random even number between 2 and 80
+    int randomX = 2 * (1 + rand() % (40 - 1 + 1)) ; //generate random even number between 2 and 80 // these are the only coordinates the snake operates in
 
     int randomY = (2 * (4 + rand() % (22 - 4 + 1))) +1; // generate random even number between 8 and 44 then plus 1 for odd number in range of 9-45
 
@@ -322,13 +328,12 @@
     while(lcd.getPixel(randomX,randomY)==1) { // if that pixel is already filled keep generating till a empty space is found
 
         int randomX = 2 * (1 + rand() % (40 - 1 + 1)) ;
-        int randomY = (2 * (4 + rand() % (22 - 4 + 1))) +1; // generate random even number between 8 and 44 then plus 1 for odd number in range of 9-45
+        int randomY = (2 * (4 + rand() % (22 - 4 + 1))) +1;
 
 
     }
-    // lcd.setPixel(randomX,randomY) ;// set the food
-    lcd.drawRect(randomX,randomY,1,1,1);
-    //lcd.setPixel(randomX,randomY);
+
+    lcd.drawRect(randomX,randomY,1,1,1); // set the food to screen
 
     foodX[0]=randomX; // update food position
     foodY[0]=randomY;// update food position
@@ -336,7 +341,7 @@
 //serial.printf("%d",randomX);
 }
 
-void hardBoundary()
+void hardBoundary() // use these boundary conditions if gamemode is BOUNDARY
 {
 
 
@@ -356,7 +361,7 @@
     lcd.refresh();
 
 }
-void classicBoundary()
+void classicBoundary() // use these boundaries if gamemode is classic
 {
 
 
@@ -380,108 +385,115 @@
 
 void updateSnakeArray()
 {
-
-    if (joystick.direction==LEFT && previousDirection==RIGHT) {
-        joystick.direction=RIGHT;
+// code to prevent snake moving in opposite direction to its current path of travel
+    if (joystick.direction==LEFT && previousDirection==RIGHT) { // if snake is travelling right but joystick is left
+        joystick.direction=RIGHT; // cary on right
     }
 
-    if (joystick.direction==RIGHT && previousDirection==LEFT) {
-        joystick.direction=LEFT;
+    if (joystick.direction==RIGHT && previousDirection==LEFT) { // if snake is travelling left but joystick is right
+        joystick.direction=LEFT; //carry on left
     }
 
-    if (joystick.direction==UP && previousDirection==DOWN) {
-        joystick.direction=DOWN;
+    if (joystick.direction==UP && previousDirection==DOWN) {// if snake is travelling down but joystick is up
+        joystick.direction=DOWN; // carry on down
     }
 
-    if (joystick.direction==DOWN && previousDirection==UP) {
-        joystick.direction=UP;
+    if (joystick.direction==DOWN && previousDirection==UP) { // if snake is travelling up but joystick is down
+        joystick.direction=UP; // carry on up
     }
 
-    if (joystick.direction==UNKNOWN || joystick.direction==CENTRE) {
-        joystick.direction= previousDirection;
+    if (joystick.direction==UNKNOWN || joystick.direction==CENTRE) { // if joystick is unknown or centred
+        joystick.direction= previousDirection;  // carry on in previous direction
     }
 
 
-    // lcd.clearPixel(snakeX[0],snakeY[0]);//delete tail
-    lcd.drawRect(snakeX[0],snakeY[0],1,1,2);
+    lcd.drawRect(snakeX[0],snakeY[0],1,1,2); // delete tail of snake by drawing a clear 2x2 block at first element in vectors
 
     for (int i =0; i<snakeX.size(); i++) {  // shift elements
         snakeX[i]=snakeX[i + 1]; // apart from head
         snakeY[i]=snakeY[i+ 1];
     }
 
+//code to set new head coordinates
     switch(joystick.direction) {
 
-        case UP:
-            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2];
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]-2;
+        case UP:  // if travelling up
+            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]; // snake new head x coordinate = previous head c coordinate
+            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]-2; // snake new head y cordinate = previous head y coordinate -2 as it moves up
 
-           if (selectedGameMode==CLASSIC){
-             if(snakeY[snakeY.size()-1] <9) snakeY[snakeY.size()-1]=45;
-             }
+            if (selectedGameMode==CLASSIC) { // when in classic mode no boundaries so need to check if new head is beyond edge limit
+                if(snakeY[snakeY.size()-1] <9) snakeY[snakeY.size()-1]=45; // when travelling up check head against upper edge
+            }
             break;
 
-        case DOWN:
-            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2];
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]+2;
-            
-          if (selectedGameMode==CLASSIC){
-            if(snakeY[snakeY.size()-1] >45) snakeY[snakeY.size()-1]=9;
+        case DOWN:// if travelling down
+            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2];   // snake new head x coordinate = previous head c coordinate
+            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2]+2;// snake new head y cordinate = previous head y coordinate +2 as it moves down
+
+            if (selectedGameMode==CLASSIC) { // when in classic mode no boundaries so need to check if new head is beyond edge limit
+                if(snakeY[snakeY.size()-1] >45) snakeY[snakeY.size()-1]=9; // check new head against bottom edge
             }
             break;
 
         case LEFT:
-            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]-2;
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
-            
-             if (selectedGameMode==CLASSIC){
-             if(snakeX[snakeX.size()-1] <2) snakeX[snakeX.size()-1]=80;
-             }
+            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]-2;  // snake new head x coordinate = previous head x coordinate - 2
+            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];// snake new head y coordinate = previous head y coordinate
+
+            if (selectedGameMode==CLASSIC) { //  when in classic mode no boundaries so need to check if new head is beyond edge limit
+                if(snakeX[snakeX.size()-1] <2) snakeX[snakeX.size()-1]=80; // check head against left edge
+            }
             break;
 
         case RIGHT:
-            snakeX[snakeX.size()-1]= snakeX[snakeX.size()-2]+2;
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
-            
-             if (selectedGameMode==CLASSIC){
-             if(snakeX[snakeX.size()-1] >80) snakeX[snakeX.size()-1]=2;
-             }
+            snakeX[snakeX.size()-1]= snakeX[snakeX.size()-2]+2; // snake new head x coordinate = previous head x coordinate + 2
+            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];// snake new head y coordinate = previous head y coordinate
+
+            if (selectedGameMode==CLASSIC) { //  when in classic mode no boundaries so need to check if new head is beyond edge limit
+                if(snakeX[snakeX.size()-1] >80) snakeX[snakeX.size()-1]=2;
+            }
 
             break;
 
-        case CENTRE:
-            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
-            break;
-        case UNKNOWN:
-            snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
-            snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
-            break;
+            /* case CENTRE:
+                 snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
+                 snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
+                 break;
+             case UNKNOWN:
+                 snakeX[snakeX.size()-1]=snakeX[snakeX.size()-2]+2;
+                 snakeY[snakeY.size()-1]=snakeY[snakeY.size()-2];
+                 break;*/
 
     }
 }
-void playTune()
+void gameOverTune() //
 {
 
-    //float frequency[]={440,659};
-    // float beat[]={1,1,};
-    // Buzzer=0.3;
-    //  Buzzer.period(1/(440));// time =1/f
-    //wait(1);
-    //Buzzer.period(1/(659));
+ //   float frequency[]={440,659};
+    //float beat[]={1,1,};
+    
+      Buzzer.period(1.0/(220)); // set PWM period 1/f  A
+Buzzer=0.5; // set duty cycle
+wait(0.5); // wait time 
+Buzzer.period(1.0/(164)); // E
+wait(0.5);//
+Buzzer=0;// set duty cycle 0
 
-    //Buzzer=0;
+  //   set PWM period
 
-    // set PWM period
+}
 
-// set duty cycle
-    //wait(0.5*beat[i]);
-}
+void eatFoodTune(){
+      Buzzer.period(1.0/(440)); // set PWM period 1/f  A
+Buzzer=0.5; // set duty cycle
+wait(0.1); // wait time 
+Buzzer=0;// set duty cycle 0
+    }
+    
 void gameOver()
 {
     leds=1;
-    startGame.detach();
-    lcd.drawRect(snakeX.back(),snakeY.back(),1,1,2);
+    startGame.detach(); // stop snake game from updating
+    lcd.drawRect(snakeX.back(),snakeY.back(),1,1,2); // highlight the point of game over
     wait(0.2);
     lcd.refresh();
     lcd.drawRect(snakeX.back(),snakeY.back(),1,1,1);
@@ -497,7 +509,7 @@
     lcd.inverseMode();
 
 
-    lcd.printString("Your Score" ,12,0);
+    lcd.printString("Your Score" ,12,0);// print score
     lcd.printString("=" ,34,1);
 
     int updatedScore=score;
@@ -512,29 +524,22 @@
 
     //
     lcd.refresh();
-    playTune();
+    gameOverTune();
 
     //gamePlaying=0;
-
-
-
 }
 
-
-
-void checkForCollision()
+void checkForCollision() // when in BOUNDARY MODE check snake head every move against walls
 {
 
     if (snakeX.back()==0|| snakeX.back()==82 || snakeY.back()==7 ||snakeY.back()>=47) {
         myleds=15;
 
-        gameOver();
+        gameOver(); // if collision then end game
     }
 }
 
-
-
-void checkForFood()
+void checkForFood() // check if snake has eaten food
 {
 
     if (snakeX.back()==foodX[0] && snakeY.back()==foodY[0]) {   // if  x and y of head match food
@@ -543,7 +548,7 @@
         switch(joystick.direction) {
 
             case RIGHT:
-                snakeX.insert (snakeX.begin() +0,foodX[0]-2 );
+                snakeX.insert (snakeX.begin() +0,foodX[0]-2 ); // insert new element to tail of snake vector
                 snakeY.insert (snakeY.begin() ,foodY[0]);
                 //snakeX.push_back(foodX[0]+2);
                 // snakeY.push_back(foodY[0]);
@@ -573,21 +578,21 @@
                 // snakeY.push_back(foodY[0]+2);
                 break;
         }
-        lcd.drawRect(snakeX[0],snakeY[0],1,1,1);
+eatFoodTune();
+        lcd.drawRect(snakeX[0],snakeY[0],1,1,1); // draw the new tail
+
+        int updatedScore; // to store updated score
 
-        int updatedScore;
-        // snakeX.insert (snakeX.begin() + 0, );
-        //snakeY.insert (snakeY.begin() + 0, );
 
-        updatedScore= score+5;
+        updatedScore= score+5; // 5 points for every food eaten
         score=updatedScore;
-        int length = sprintf(buffer,"%2d",updatedScore);
+        int length = sprintf(buffer,"%2d",updatedScore);// print updated score to screen
 
         if (length <= 14)  // if string will fit on display
             lcd.printString(buffer,0,0);
         // lcd.refresh();
 
-        randomiseFood();
+        randomiseFood(); // randomise new food
 
     }
 
@@ -596,12 +601,12 @@
 
 void startButtonPressed()
 {
-    if (menuState==0) {
-        menuState=1;
+    if (gameState==0) { // when at first menu if pressed
+        gameState=1; // move to second menu
     }
 
-  else  if (menuState==1) {
-        menuState=2;
+    else  if (gameState==1) { // when at second menu
+        gameState=2; // move to gameplay
     }
 
 }
@@ -633,18 +638,16 @@
 void pauseButtonPressed()
 {
 
-    if (gamePaused==0) {
+    if (gamePaused==0) { // if game isnt already paused
 
-        startGame.detach();
+        startGame.detach(); // stop game updating
 
-        gamePaused=1;
-        leds=2;
+        gamePaused=1; // update paused status
+        leds=2; // show amber led
 
     }
 
-    else {
-
-
+    else { // if game is paused start game
         startGame.attach(&updateGameISR,gameSpeed);
 
         gamePaused=0;
@@ -654,10 +657,10 @@
 
 }
 
-void checkForCollisionWithSelf(int i)
+void checkForCollisionWithSelf(int i) // checks snake head with all other parts of snake
 {
-    if(snakeX.back()==snakeX[i] && snakeY.back()==snakeY[i]) {
-        gameOver();
+    if(snakeX.back()==snakeX[i] && snakeY.back()==snakeY[i]) { // if both x and y coordinates of any part of snake match head
+        gameOver(); // end game
     }
 
 
@@ -666,7 +669,7 @@
 {
     lcd.inverseMode();
     easySelected();
-    joystick.direction=UNKNOWN;
+    joystick.direction=UNKNOWN; // unknown so does not start scrolling
     calibrateJoystick();  // get centred values of joystick
 
 }
@@ -674,105 +677,97 @@
 void ModeMenu()
 {
     classicModeSelected();
-    joystick.direction=UNKNOWN;
+    joystick.direction=UNKNOWN;// unknown so does not start scrolling
     calibrateJoystick();  // get centred values of joystick
 }
 
 void resetButtonPressed()
 {
-    //gamePlaying=0;
-    menuState=0;
+
+    gameState=0; // when reset button pressed bring back to first menu screen
 }
 
 
 int main()
 {
-   
+ startButton.setSampleFrequency();
     lcd.init();
     resetButton.mode(PullDown);
     startButton.mode(PullDown);
     button.mode(PullDown);
-    startButton.rise(&startButtonPressed);
+  //  startButton.rise(&startButtonPressed);
+    startButton.attach_asserted( &startButtonPressed );
     resetButton.rise(&resetButtonPressed);
     button.rise(&pauseButtonPressed);
     displaySplash();
-     leds=1;
+    leds=1;
     wait(4);
-//serial.printf("starting");
+
     while(1) {
-        leds=1;
+        leds=1;// red light
         startUpMenu();
-        while (menuState==0) {
+        while (gameState==0) { // wait until user has selected difficulty
             updateJoystick();
             checkSelectedDifficulty();
             updateBrightness();
             //serial.printf("check difficulty loop");
-            
-             if (menuState==1){
+
+            if (gameState==1) { // initialise mode menu
                 ModeMenu();
-                }
+            }
         }
 
 
-        while(menuState==1) {
-           // ModeMenu();
-           
+        while(gameState==1) { // wait unit user has pressed start button and selected a game mode
+
             updateJoystick();
             checkSelectedGameMode();
             updateBrightness();
-           
+
         }
 
-        if (menuState==2) {
+        if (gameState==2) { // initialise game
 
             lcd.clear();
-            lcd.normalMode();  
-            if (selectedGameMode==BOUNDARY) hardBoundary();
+            lcd.normalMode(); // normal colours for gameplay
+            if (selectedGameMode==BOUNDARY) hardBoundary(); // depending on game mode selcted set walls
             if (selectedGameMode==CLASSIC) classicBoundary();
-            
-   // normal colour mode
-         
-            previousDirection=RIGHT;
+            previousDirection=RIGHT; // snake has to be moving right when reset (reset bug fix)
             joystick.direction=RIGHT; // make sure when game reset that joystick is reset to right
-            startingSnake();
-            randomiseFood();
-            int score=5;
+            startingSnake(); // print starting snake
+            randomiseFood(); // show random food
+            int score=5;// initial score is 5
             int length = sprintf(buffer,"%2d",score);
             if (length <= 14)  // if string will fit on display
                 lcd.printString(buffer,0,0);
             // lcd.drawRect(0,0,83,7,0);
             lcd.refresh();
-            startGame.attach(&updateGameISR,gameSpeed);
+            startGame.attach(&updateGameISR,gameSpeed); // start game isr speed determined by difficulty chosen
 
-            while (menuState==2) {
+            while (gameState==2) { // while user doesnt press reset
 
                 //  serial.printf("enter game loop");
-                if(updateGameFlag==1) {
-                    leds=4;
-                    //updateJoystick();
-                    updateGameFlag=0;
-                    updateJoystick();
-                    // lcd.clearPixel(snakeX[0],snakeY[0]);
-                    // updateSnakeDirection();
-                    updateSnakeArray();
-                    for (int i=0; i<snakeX.size(); i++) {
+                if(updateGameFlag==1) { // check flag
+                    leds=4; // green LED when game playing
+
+                    updateGameFlag=0; // reset flag
+                    updateJoystick(); // check joystick direction
+
+                    updateSnakeArray(); // update the array
+                    for (int i=0; i<snakeX.size(); i++) { // for all elements of snake draw 2x2 image
                         lcd.drawRect(snakeX[i],snakeY[i],1,1,1);
-                        // lcd.setPixel(snakeX[i],snakeY[i]);
+
                     }
                     lcd.refresh();
-                    previousDirection=joystick.direction;
+                    previousDirection=joystick.direction; // update previous joystick direction
 
-                    if (selectedGameMode==BOUNDARY) checkForCollision();
-                    
-                    
-                    checkForFood();
+                    if (selectedGameMode==BOUNDARY) checkForCollision();// if in boundary mode check for a collision
 
+                    checkForFood(); // check if snake has eaten food
 
                     for (int i=0; i<snakeX.size()-1; i++) {
                         checkForCollisionWithSelf(i);
                         updateBrightness();
-                        //serial.printf("%d",snakeX.size());
-                        // printVectorContent();
 
                     }
 
--- a/main.h	Thu Apr 30 20:53:56 2015 +0000
+++ b/main.h	Fri May 01 08:53:21 2015 +0000
@@ -10,21 +10,29 @@
 #include <vector>
 #include "mbed.h"
 #include "N5110.h"
+#include "PinDetect.h"
 #define DIRECTION_TOLERANCE 0.1
 
+
 AnalogIn pot(p20);
 PwmOut Buzzer(p21);
 
 //        VCC,SCE,RST,D/C,MOSI,SCLK,LED
+
 /** 
 @namespace lcd
 @brief connections lcd mosi connections for nokia N5110
 */ 
 N5110 lcd(p7,p8,p9,p10,p11,p13,p26);
 
+/** 
+@namespace myleds
+@brief connections lcd mosi connections for nokia N5110
+*/ 
+
 BusOut myleds(LED1,LED2,LED3,LED4);
 BusOut leds(p22,p23,p24);
-InterruptIn startButton(p5);
+PinDetect startButton(p5);
 InterruptIn resetButton(p6);
 int score=5;
 Ticker pollJoystick;
@@ -42,11 +50,11 @@
 int snake[84][47];
 bool gamePlaying =0;
 bool gamePaused=0;
-vector<int> snakeX (5);
-vector<int> snakeY (5,27);
-int foodX[1];
-int foodY[1];
-int menuState=0;
+vector<int> snakeX (5); // vector to store all x coordinates of snake
+vector<int> snakeY (5,27);// vector to store all y coordinates of snake
+int foodX[1];// store x value of food
+int foodY[1];// store y value of food
+int gameState=0;// 
 
 
 float gameSpeed;//change depending on difficulty selected