
Completed Snake Program
Dependencies: N5110 PinDetect PowerControl mbed
Fork of DocTest by
Diff: main.cpp
- Revision:
- 9:77b83754460c
- Parent:
- 8:b857684a3983
- Child:
- 10:dbcb96fa049d
diff -r b857684a3983 -r 77b83754460c main.cpp --- 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(); }