Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Joystick N5110 SDFileSystem beep fsmMenu mbed
Fork of SnakeProjectRev1 by
main.cpp
- Committer:
- meurigp
- Date:
- 2016-05-05
- Revision:
- 22:195d66c61bf3
- Parent:
- 21:e03461ea23e9
- Child:
- 24:c6b53a526c4e
File content as of revision 22:195d66c61bf3:
/** @file main.cpp @brief Program implementation of Snake Game */ /* Meurig Phillips 200870500 */ #include "main.h" FILE *fp; // pointer for SD card int main() { /// Setup up interrupt peripherals initInterrupts(); /// Get centred values of joystick calibrateJoystick(); /// Read joystick 20 timer per second pollJoystick.attach(&updateJoystick,0.5/10.0); /// Set rand seed srand(time(NULL)); /// Green LED is pull-up, Red is pull-down greenLed = 1; redLed = 0; /// Init Screen lcd.init(); ///Splash Screen snakeIntro(); /// Menu mainMenu(); } void initInterrupts() { /// ISRs executed on the rise button.rise(&buttonISR); gameTicker.attach(&timer_isr,0.1); RB.mode(PullDown); LB.mode(PullDown); RB.rise(&rb_isr); LB.rise(&lb_isr); } void mainGame() { /// Initialise coordinates depending on game type if(gameType == classicMode) { hardWall(); i = 41; j = 23; } else if(gameType == infiniteMode) { wrapAround(); i = 40; j = 22; } else { specialMap(); i = 13; j = 5; } generateFood(); /// Create random food /// Initialise initSnakeTail(); snakeTailLength = 3; score = 0; fruitValue = 10; pauseCount = 0; while(gamePlaying == true) { lcd.setBrightness(1-pot); /// turn pot right for brightness if (buttonFlag ==1) { buttonFlag = 0; if (pauseCount < 3) { gamePaused(); } buttonFlag = 0; } buttonFlag = 0; if(game_timer_flag) { /// logic implemented & screen updated with every tick game_timer_flag = 0; gameLogic(); } if (printFlag) { /// if joystick input is received, update direction printFlag = 0; moveSnake(); } sleep(); } } void mainMenu() { while(1) { /// Menu options lcd.printString("Classic",0,1); lcd.printString("Infinite",0,3); lcd.printString("Hard Map",0,5); /// Start game when right button is pressed if (rb_flag == 1) { rb_flag = 0; gamePlaying = true; mainGame(); } /// If joystcik is moved if (printFlag ==1) { printFlag = 0; /// Cycle through menu if (joystick.direction == CENTRE) { menuDirection = menuSTOP; } else if (joystick.direction == UP) { menuDirection = menuUP; buzzer.beep(2000,0.2); } else if (joystick.direction == DOWN) { menuDirection = menuDOWN; buzzer.beep(2000,0.2); } } menuFSM(); /// Move selector (*) according to fsm state wait(0.2); if (state ==0) { lcd.clear(); lcd.printString("*",70,1); gameType = classicMode; } else if (state ==1) { lcd.clear(); lcd.printString("*",70,3); gameType = infiniteMode; } else if (state ==2) { lcd.clear(); lcd.printString("*",70,5); gameType = hardMode; } } } void generateFood() { if (gameType == classicMode || gameType == hardMode) { while (randomXoddEven ==0 || randomYoddEven ==0 || lcd.getPixel(randomX,randomY) >= 1) { /// do while x or y is even or pixel is on randomX = rand() % 83 + 1; /// randomX in the range 1 to 83 randomY = rand() % 47 + 1; /// randomY in the range 1 to 47 randomXoddEven = randomX%2; /// find out whether odd or even randomYoddEven = randomY%2; } lcd.drawRect(randomX,randomY,1,1,1); } else { while (randomXoddEven ==1 || randomYoddEven ==1 || lcd.getPixel(randomX,randomY) >= 1) { // do while x or y is odd or pixel is on randomX = rand() % 83 + 1; // randomX in the range 1 to 83 randomY = rand() % 47 + 1; // randomY in the range 1 to 47 randomXoddEven = randomX%2; // find out whether odd or even randomYoddEven = randomY%2; } lcd.drawRect(randomX,randomY,1,1,1); } } void newFruitXY() /// new fruit coordinate values are given before it is passed to the generateFood function { randomX = rand() % 83 + 1; /// randomX in the range 1 to 81 randomY = rand() % 47 + 1; /// randomY in the range 1 to 47 randomXoddEven = randomX%2; /// find out whether odd or even randomYoddEven = randomY%2; } void moveSnake() { if (joystick.direction == LEFT) { if (currentDirection != right) { /// change the currentDirection according to joystick input, providing currentDirection = left; /// it's not the opposite direction to the current direction } } else if (joystick.direction == RIGHT) { if (currentDirection != left) { /// change the currentDirection according to joystick input, providing currentDirection = right; /// it's not the opposite direction to the current direction } } else if (joystick.direction == UP) { if (currentDirection != down) { /// change the currentDirection according to joystick input, providing currentDirection = up; /// it's not the opposite direction to the current direction } } else if (joystick.direction == DOWN) { if (currentDirection != up) { /// change the currentDirection according to joystick input, providing currentDirection = down; /// it's not the opposite direction to the current direction } } } void gameLogic() { lcd.clear(); greenLed = 1; prev_i = snakeTailX[0]; prev_j = snakeTailY[0]; snakeTailX[0] = i; snakeTailY[0] = j; for (int a=1; a<snakeTailLength; a++) { /// loops through snakeTail array and assigns previous seg's coordinates to current one prev2_i = snakeTailX[a]; prev2_j = snakeTailY[a]; snakeTailX[a] = prev_i; snakeTailY[a] = prev_j; prev_i = prev2_i; prev_j = prev2_j; } if (currentDirection == left) { /// shift snake head coordinates according to current direction i -= 2; } /// move left else if (currentDirection == right) { i += 2; } /// move right else if (currentDirection == up) { j -= 2; } /// move up else if (currentDirection == down) { j += 2; } /// move down lcd.drawRect(i,j,1,1,1); /// snake head for (int b=0; b<snakeTailLength; b++) { lcd.drawRect(snakeTailX[b],snakeTailY[b],1,1,1); } lcd.refresh(); lcd.drawRect(randomX,randomY,1,1,1); /// food if (gameType == classicMode) { /// map types hardWall(); } else if (gameType == infiniteMode) { wrapAround(); } else { specialMap(); } if (i == randomX && j == randomY) { /// if fruit is eaten greenLed = 0; buzzer.beep(2000,0.2); scoreCalculation(); snakeTailLength++; newFruitXY(); generateFood(); } if (snakeTailLength > 4) { /// if snake eats itself for (int q=1; q<snakeTailLength; q++) { if (snakeTailX[q] == i && snakeTailY[q] == j) { gameOver(); } } } } void hardWall() { lcd.drawRect(0,0,83,47,0); lcd.refresh(); if (i == 0 || i+1 == 0 || i == 83 || i+1 == 83 || /// if any of the 4 pixels within the snake head touch the border j == 0 || j+1 == 0 || j == 47 || j+1 == 47) { i = 41; j = 23; gameOver(); } } void gameOver() { redLed = 1; if(score > top_score) { // open file for writing ('w') - creates file if it doesn't exist and overwrites // if it does. If you wish to add a score onto a list, then you can // append instead 'a'. This will open the file if it exists and start // writing at the end. It will create the file if it doesn't exist. fp = fopen("/sd/topscore.txt", "w"); int top_score = score; if (fp == NULL) { // if it can't open the file then print error message } else { // opened file so can write fprintf(fp, "%d",top_score); // ensure data type matches fclose(fp); // ensure you close the file after writing } } gamePlaying = false; lcd.clear(); buzzer.beep(294,0.5); wait(0.5); lcd.printString("Game Over",15,0); // width(6) * n(9) = 54, 84-54 = 30, 30/2 = 15 buzzer.beep(277,0.5); wait(0.5); char buffer[14]; int length = sprintf(buffer,"Score:%i",score); /// display score of round if (length <= 14) { // if string will fit on display lcd.printString(buffer,0,1); } // display on screen buzzer.beep(262,2); wait(0.5); // now open file for reading fp = fopen("/sd/topscore.txt", "r"); // int stored_top_score = -1; // -1 to demonstrate it has changed after reading if (fp == NULL) { // if it can't open the file then print error message } else { // opened file so can write fscanf(fp, "%d",&top_score); // ensure data type matches - note address operator (&) char buffer[14]; int length = sprintf(buffer,"HI Score:%i",top_score); // display score of round if (length <= 14) { // if string will fit on display lcd.printString(buffer,0,2); } // display on screen fclose(fp); // ensure you close the file after reading } wait(0.5); redLed = 0; lcd.printString("RB - Restart",0,4); wait(0.5); lcd.printString("LB - Menu",0,5); while(1) { if (rb_flag == 1) { rb_flag = 0; gamePlaying = true; mainGame(); } rb_flag = 0; if (lb_flag == 1) { lb_flag = 0; gamePlaying = false; mainMenu(); } sleep(); } } void specialMap() { lcd.drawRect(0,0,83,47,0); lcd.drawRect(15,9,1,31,1); lcd.drawRect(33,9,1,31,1); lcd.drawRect(49,9,1,31,1); lcd.refresh(); if (i == 0 || i+1 == 0 || i == 83 || i+1 == 83 || /// if any of the 4 pixels within the snake head touch the border j == 0 || j+1 == 0 || j == 47 || j+1 == 47) { i = 13; j = 5; gameOver(); } } void wrapAround() { if (i == -2) { i = 82; } if (i == 84) { i = 0; } if (j == -2) { j = 46; } if (j == 48) { j = 0; } } void scoreCalculation() { score += fruitValue; /// each time fruit is eaten score is calculated and fruit value will increase by 1 fruitValue++; } void initSnakeTail() { if (gameType == classicMode) { prev_i = 39; prev_j = 23; prev2_i = 37; prev2_j = 23; } else if (gameType == infiniteMode) { prev_i = 38; prev_j = 22; prev2_i = 36; prev2_j = 22; } else { prev_i = 11; prev_j = 5; prev2_i = 9; prev2_j = 5; } snakeTailX[0] = i; snakeTailY[0] = j; snakeTailX[1] = prev_i; snakeTailY[1] = prev_j; snakeTailX[2] = prev2_i; snakeTailY[2] = prev2_j; lcd.drawRect(i,j,1,1,1); /// snake head for (int b=0; b<snakeTailLength; b++) { lcd.drawRect(snakeTailX[b],snakeTailY[b],1,1,1); } currentDirection = right; } void snakeIntro() { for(int i=0; i<WIDTH; i++) { for(int j=0; j<HEIGHT; j++) { lcd.setPixel(i,j); } } for (int q=0; q<WIDTH/2; q++) { lcd.drawCircle(WIDTH/2,HEIGHT/2,q,2); wait_ms(2); } /// x,y,radius,white fill lcd.printString("Snake",27,0); buzzer.beep(2000,0.5); wait(0.5); lcd.printString("by",36,2); buzzer.beep(1000,0.5); wait(0.5); lcd.printString("Meurig",24,3); buzzer.beep(500,0.5); wait(0.5); lcd.printString("Phillips",18,4); buzzer.beep(250,2); wait(2); lcd.clear(); } void gamePaused() { wait_ms(100); pauseCount++; lcd.clear(); char buffer[14]; int length = sprintf(buffer,"%i left",3-pauseCount); /// number of pauses left if (length <= 14) { // if string will fit on display lcd.printString(buffer,24,3); } // display on screen lcd.printString("Paused 5",18,1); wait(1); lcd.printString("Paused 4",18,1); wait(1); lcd.printString("Paused 3",18,1); wait(1); lcd.printString("Paused 2",18,1); wait(1); lcd.printString("Paused 1",18,1); wait(1); } void timer_isr() { game_timer_flag = 1; } void rb_isr() { rb_flag = 1; } void lb_isr() { lb_flag = 1; }