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: N5110 PinDetect PowerControl mbed
main.cpp
00001 #include "mbed.h" 00002 #include "N5110.h" 00003 #include "PinDetect.h" 00004 #include "PowerControl/PowerControl.h" 00005 #include "PowerControl/EthernetPowerControl.h" 00006 #include <vector> 00007 #include <stdlib.h> /* srand, rand */ 00008 #include <time.h> 00009 00010 /* Code for Snake game 00011 00012 B.F. Mills 00013 00014 April 12th 2015 00015 00016 */ 00017 00018 // change this to alter tolerance of joystick direction 00019 #define DIRECTION_TOLERANCE 0.05 00020 00021 // vcc, sce, rst, dc, mosi, sck, backlight 00022 N5110 lcd(p7, p8, p9, p10, p11, p13, p26); 00023 00024 // joystick connections 00025 AnalogIn yPot(p15); 00026 AnalogIn xPot(p16); 00027 DigitalIn button(p17); 00028 00029 // leds 00030 BusOut myleds(LED1, LED2, LED3, LED4); 00031 00032 // buttons 00033 PinDetect buttonA(p30); 00034 PinDetect buttonB(p29); 00035 00036 // timer to regularly read the joystick 00037 Ticker pollJoystick; 00038 // Serial for debug 00039 Serial serial(USBTX,USBRX); 00040 00041 // create enumerated type (0,1,2,3 etc. for direction) 00042 // could be extended for diagonals etc. 00043 enum DirectionName { 00044 UP, 00045 DOWN, 00046 LEFT, 00047 RIGHT, 00048 CENTRE, 00049 UNKNOWN 00050 }; 00051 00052 DirectionName currentDirection ; // enum variable for current direction of snake's movement 00053 DirectionName previousDirection ; // enum variable for previous direction of snake's movement 00054 00055 // enumerated type for game menu screen 00056 enum GameMenu { 00057 STARTUP, 00058 SELECTSPEED, 00059 GAMEPLAY 00060 }; 00061 00062 GameMenu currentGameMenu ; // create game menu variable 00063 00064 // struct for Joystick 00065 typedef struct JoyStick Joystick; 00066 struct JoyStick { 00067 float x; // current x value 00068 float x0; // 'centred' x value 00069 float y; // current y value 00070 float y0; // 'centred' y value 00071 int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed) 00072 DirectionName direction; // current direction 00073 }; 00074 // create struct variable 00075 Joystick joystick; 00076 00077 // struct for a coordinate 00078 struct coordinate { 00079 int x; // x coordinate 00080 int y; // y coordinate 00081 }; 00082 00083 char buffer [14]; // buffer for printing score to screen 00084 00085 // flags 00086 int printFlag = 0; 00087 int Aflag = 0; // flag for notification of A button interrupt 00088 int Bflag = 0; // flag for notification of B button interrupt 00089 int collisionFlag = 0; // flag for notification of self snake collision 00090 int borderFlag = 0; // flag for hitting border in insane mode 00091 00092 // global variables 00093 int score = 0; // score value 00094 bool gameOver ; // boolean variable for game over 00095 int xCentre = 4; // x coordinate for centre of selection circle 00096 int yCentre = 11; // y coordinate for centre of selection circle 00097 float speed ; // wait time for moveSnake function 00098 00099 void pressedA() 00100 { 00101 Aflag = 1; // set flag when A button is pressed 00102 } 00103 00104 void pressedB() 00105 { 00106 Bflag = 1; // set flag when B button is pressed 00107 } 00108 00109 // function prototypes 00110 void calibrateJoystick(); 00111 void updateJoystick(); 00112 void moveSnake(); 00113 void speedSelect(); 00114 00115 std::vector<coordinate> Snake; // create a vector that stores coordinate structs 00116 00117 int main() 00118 { 00119 00120 calibrateJoystick(); // get centred values of joystick 00121 pollJoystick.attach(&updateJoystick,1.0/20.0); // read joystick 20 times per second 00122 00123 lcd.init(); // initialise display 00124 lcd.setBrightness(0.5); // set brightness of backlight 00125 00126 PHY_PowerDown(); // power down ethernet 00127 00128 // set button modes to pull down 00129 buttonA.mode(PullDown); 00130 buttonB.mode(PullDown); 00131 00132 buttonA.attach_asserted(&pressedA); // call pressedA function when button is pressed 00133 buttonB.attach_asserted(&pressedB); // call pressedB function when button is presed 00134 00135 // set sample frequency for buttons (default = 20ms) 00136 buttonA.setSampleFrequency(); 00137 buttonB.setSampleFrequency(); 00138 00139 currentGameMenu = STARTUP; // initialise game menu to be splash screen 00140 gameOver = false; // initialise gameOver as false 00141 00142 00143 while (1) { // infinite loop 00144 00145 if (currentGameMenu == STARTUP) { // start up screen 00146 00147 // splash screen for startup 00148 lcd.printString("SNAKE",28,1); 00149 lcd.printString("PRESS A",21,5); 00150 00151 // draw snake logo 00152 lcd.drawRect(26,27,5,5,0); // bottom rectangle of snake 00153 lcd.drawRect(26,22,5,5,0); // the rectangle directly above 00154 lcd.drawRect(31,22,5,5,0); // the rectangle one to the right 00155 lcd.drawRect(36,22,5,5,0); // one to the right 00156 lcd.drawRect(41,22,5,5,0); // one to the right 00157 lcd.drawRect(51,22,5,5,1); // "food" 00158 lcd.refresh(); 00159 00160 Sleep(); // when flag is not set, go to sleep & wait for interrupt 00161 00162 if (Aflag ) { // if currentGameMenu is STARTUP and A is pressed, 00163 Aflag = 0; // reset flag 00164 lcd.clear(); // clear screen 00165 currentGameMenu = SELECTSPEED; // segue to select speed menu 00166 } 00167 00168 } 00169 00170 if (currentGameMenu == SELECTSPEED) { // select speed menu 00171 00172 // print menu options to screen 00173 lcd.printString("SLOW",10,1); 00174 lcd.printString("MEDIUM",10,3); 00175 lcd.printString("FAST",10,5); 00176 lcd.printString("INSANE",46,1); 00177 00178 lcd.drawCircle(xCentre ,yCentre ,3,1); // draw selection circle (starting on SLOW) 00179 lcd.refresh(); 00180 speedSelect(); 00181 00182 if (Aflag ) { // if currentGameMenu is SELECTSPEED and A is pressed, 00183 Aflag = 0; // reset flag 00184 lcd.clear(); // cleat screen 00185 currentGameMenu = GAMEPLAY; // segue to gameplay 00186 } 00187 00188 Sleep(); // when flag is not set, got to sleep & wait for interrupt 00189 00190 } 00191 00192 if (currentGameMenu == GAMEPLAY) { // gameplay 00193 00194 if (gameOver == false) { // whilst game is not over 00195 00196 if (xCentre + yCentre == 15) { // if the addition of the coordinates of the centre of the selection circle = 15 i.e when selecting SLOW 00197 speed = 0.20; // set wait time for moveSnake 00198 } 00199 if (xCentre + yCentre == 31) { // medium 00200 speed = 0.12; 00201 } 00202 if (xCentre + yCentre == 47) { // fast 00203 speed = 0.04; 00204 } 00205 if (xCentre + yCentre == 53) { // insane 00206 speed = 0.02; 00207 00208 for (int y=0; y<23 ; y++) { // set upper border 00209 lcd.setPixel(43,y); 00210 lcd.refresh(); 00211 } 00212 00213 for (int y=25; y<47; y++) { // set lower border 00214 lcd.setPixel(43,y); 00215 lcd.refresh(); 00216 } 00217 } 00218 00219 previousDirection = RIGHT; // initialise first direction to be right 00220 00221 // set of initial coordinates 00222 coordinate cord0 = {45, 24}; 00223 coordinate cord1 = {46, 24}; 00224 coordinate cord2 = {47, 24}; 00225 coordinate cord3 = {48, 24}; 00226 00227 // add these coordinates to the snake vector 00228 Snake.push_back(cord0); 00229 Snake.push_back(cord1); 00230 Snake.push_back(cord2); 00231 Snake.push_back(cord3); 00232 00233 // set these co-ordinate's pixels 00234 for (int i=0; i<Snake.size(); i++) { 00235 lcd.setPixel(Snake.at(i).x, Snake.at(i).y); 00236 lcd.refresh(); 00237 } 00238 00239 moveSnake(); 00240 } 00241 00242 if (gameOver == true) { // if game is over 00243 00244 // display game over splash screen 00245 lcd.printString("Game Over!",14,1); 00246 lcd.printString("Press B",23,4); 00247 int printScore = sprintf(buffer,"Score = %d",score*5); // print formatted data to buffer 00248 if (printScore <= 14) { // if string fits on display 00249 lcd.printString(buffer,16,3); 00250 } 00251 Snake.clear(); // clear snake vector 00252 00253 while (1) { // flash leds 00254 myleds = 15; 00255 wait(0.5); 00256 myleds = 0; 00257 wait(0.5); 00258 if (Bflag ) // if B is pressed, break out of infinite loop 00259 break; 00260 } 00261 00262 if (Bflag ) { // if B is pressed, 00263 Bflag = 0; // reset flag 00264 collisionFlag = 0; // reset collision flag 00265 score = 0; // reset score 00266 myleds = 0; // switch off leds 00267 borderFlag = 0; 00268 gameOver = false; // reset gameOver to false 00269 lcd.clear(); // clear the screen 00270 currentGameMenu = STARTUP; // go back to startup screen 00271 } 00272 00273 } 00274 } 00275 00276 } 00277 } 00278 00279 // read default positions of the joystick to calibrate later readings 00280 void calibrateJoystick() 00281 { 00282 button.mode(PullDown); 00283 // must not move during calibration 00284 joystick.x0 = xPot; // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) 00285 joystick.y0 = yPot; 00286 } 00287 00288 void updateJoystick() 00289 { 00290 // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred) 00291 joystick.x = xPot - joystick.x0; 00292 joystick.y = yPot - joystick.y0; 00293 // read button state 00294 joystick.button = button; 00295 00296 // calculate direction depending on x,y values 00297 // tolerance allows a little lee-way in case joystick not exactly in the stated direction 00298 if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { 00299 joystick.direction = CENTRE; 00300 } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { 00301 joystick.direction = RIGHT; 00302 } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { 00303 joystick.direction = LEFT; 00304 } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { 00305 joystick.direction = DOWN; 00306 } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { 00307 joystick.direction = UP; 00308 } else { 00309 joystick.direction = UNKNOWN; 00310 } 00311 00312 // set flag for printing 00313 printFlag = 1; 00314 } 00315 00316 void moveSnake() 00317 { 00318 srand(time(NULL)); // use time as seed for rand 00319 00320 int foodX = rand()%82+1; // random x coordinate between 1-82 00321 int foodY = rand()%46+1; // random y coordinate between 1-46 00322 00323 // draw border 00324 lcd.drawRect(0,0,83,47,0); // x-origin, y-origin, width, height, fill 00325 lcd.refresh(); 00326 00327 if (!lcd.getPixel(foodX,foodY)) // if pixel is not already set 00328 lcd.setPixel(foodX,foodY); // set pixel of this coordinate (used for food) 00329 lcd.refresh(); 00330 00331 while (1) { // infinite loop 00332 00333 if (joystick.direction == CENTRE) { // if the joystick is in the centre 00334 currentDirection = previousDirection ; // current direction is the previous direction of movement 00335 } 00336 if (joystick.direction == UNKNOWN) { // if the joystick's direction is unknown 00337 currentDirection = previousDirection ; // current direction is the previous direction 00338 } 00339 00340 // if joystick direction is left, right, up or down, set the current direction to be the joystick's direction 00341 if (joystick.direction == LEFT) { 00342 currentDirection = joystick.direction; 00343 } 00344 if (joystick.direction == RIGHT) { 00345 currentDirection = joystick.direction; 00346 } 00347 if (joystick.direction == UP) { 00348 currentDirection = joystick.direction; 00349 } 00350 if (joystick.direction == DOWN) { 00351 currentDirection = joystick.direction; 00352 } 00353 00354 lcd.clearPixel(Snake.front().x, Snake.front().y); // clear the tail pixel of snake 00355 00356 for (int i=0; i<Snake.size()-1; i++) { // shift along each element in the vector so that.. 00357 Snake.at(i) = Snake.at(i+1); // value of element Snake[0] = Snake[1], Snake[1] = Snake[2] etc. 00358 } 00359 00360 switch (currentDirection ) { // check the current direction 00361 00362 case UP: // if up 00363 if (previousDirection == DOWN) { // check if the previous direction was opposite to the current direction 00364 currentDirection = DOWN; // if so, move in the previous direction 00365 Snake.back().y++; // increment appropiate coordinate value 00366 } else { // if the previous direction wasn't opposite to the current direction, 00367 previousDirection = UP; // set the previous direction 00368 Snake.back().y--; // increment appropiate coordinate value 00369 } 00370 break; 00371 00372 case DOWN: 00373 if (previousDirection == UP) { 00374 currentDirection = UP; 00375 Snake.back().y--; 00376 } else { 00377 previousDirection = DOWN; 00378 Snake.back().y++; 00379 } 00380 break; 00381 00382 case LEFT: 00383 if (previousDirection == RIGHT) { 00384 currentDirection = RIGHT; 00385 Snake.back().x++; 00386 } else { 00387 previousDirection = LEFT; 00388 Snake.back().x--; 00389 } 00390 break; 00391 00392 case RIGHT: 00393 if (previousDirection == LEFT) { 00394 currentDirection = LEFT; 00395 Snake.back().x--; 00396 } else { 00397 previousDirection = RIGHT; 00398 Snake.back().x++; 00399 } 00400 break; 00401 00402 default: 00403 break; 00404 } 00405 00406 if ((Snake.back().x == foodX) && (Snake.back().y == foodY)) { // if the snake head hits the food 00407 00408 switch (currentDirection ) { // check the current direction 00409 00410 case UP: 00411 Snake.push_back(Snake.back()); // add an element, which is equal to the penultimate element, to the end of the vector 00412 Snake.back().y--; // increment the appropiate coordinate of this new element for the direction of movement 00413 foodX = rand()%82 + 1; // x coordinate of food is now a new random number between 1-83 00414 foodY = rand()%46 + 1; // y coordinate of food is now a new random number between 1-47 00415 00416 if (!lcd.getPixel(foodX,foodY)) { 00417 lcd.setPixel(foodX,foodY); 00418 lcd.refresh(); 00419 } 00420 00421 score++; // increment score value 00422 00423 // flash led 00424 myleds = 1; 00425 wait(0.2); 00426 myleds = 0; 00427 break; 00428 00429 case DOWN: 00430 Snake.push_back(Snake.back()); 00431 Snake.back().y++; 00432 foodX = rand()%82 + 1; 00433 foodY = rand()%46 + 1; 00434 00435 if (!lcd.getPixel(foodX,foodY)) { 00436 lcd.setPixel(foodX,foodY); 00437 lcd.refresh(); 00438 } 00439 score++; 00440 00441 myleds = 1; 00442 wait(0.2); 00443 myleds = 0; 00444 break; 00445 00446 case LEFT: 00447 Snake.push_back(Snake.back()); 00448 Snake.back().x--; 00449 foodX = rand()%82 + 1; 00450 foodY = rand()%46 + 1; 00451 00452 if (!lcd.getPixel(foodX,foodY)) { 00453 lcd.setPixel(foodX,foodY); 00454 lcd.refresh(); 00455 } 00456 score++; 00457 00458 myleds = 1; 00459 wait(0.2); 00460 myleds = 0; 00461 break; 00462 00463 case RIGHT: 00464 Snake.push_back(Snake.back()); 00465 Snake.back().x++; 00466 foodX = rand()%82 + 1; 00467 foodY = rand()%46 + 1; 00468 00469 if (!lcd.getPixel(foodX,foodY)) { 00470 lcd.setPixel(foodX,foodY); 00471 lcd.refresh(); 00472 } 00473 score++; 00474 00475 myleds = 1; 00476 wait(0.2); 00477 myleds = 0; 00478 break; 00479 00480 default: 00481 break; 00482 } 00483 00484 } 00485 00486 00487 for (int i = 0; i < Snake.size()-1; i++) { // iterate through all elements in the snake vector 00488 if ((Snake.back().x == Snake.at(i).x) && (Snake.back().y == Snake.at(i).y)) { // if snake head touches any other part of the snake 00489 collisionFlag = 1; // set colision flag 00490 gameOver = true; // set gameOver to true 00491 } 00492 00493 } 00494 00495 if (collisionFlag ) break; // if collision flag is set, break out of infinite loop 00496 00497 if (Snake.back().x > 82) { // if snakeHead's x coordinate is 83 or larger (i.e touching the right hand side border) 00498 gameOver = true; // game over is true 00499 break; // break out of infinite loop 00500 } 00501 00502 if (Snake.back().x < 1) { // touching left hand side border 00503 gameOver = true; 00504 break; 00505 } 00506 00507 if (Snake.back().y > 46) { // touching top border 00508 gameOver = true; 00509 break; 00510 } 00511 00512 if (Snake.back().y < 1) { // touching bottom border 00513 gameOver = true; 00514 break; 00515 } 00516 00517 if (xCentre + yCentre == 53) { // insane 00518 00519 if ((Snake.back().x == 43) && (Snake.back().y < 23)) { // if snake touches upper border 00520 gameOver = true; // game over is true 00521 borderFlag = 1; // set border flag 00522 } 00523 00524 if ((Snake.back().x == 43) && (Snake.back().y > 24)) { // if snake touches lower border 00525 gameOver = true; // game over is true 00526 borderFlag = 1; // set border flag 00527 } 00528 } 00529 00530 if (borderFlag ) break; // if border flag is set, break out of infinite loop 00531 00532 lcd.setPixel(Snake.back().x, Snake.back().y); // set new snakeHead's pixel 00533 lcd.refresh(); 00534 wait(speed ); 00535 00536 } 00537 } 00538 00539 void speedSelect() 00540 { 00541 if (joystick.direction == DOWN) { // if the joystick is moved down 00542 00543 if (xCentre == 4 && yCentre == 11) { // i.e. when the selection circle is on SLOW 00544 lcd.clear(); // clear the screen 00545 00546 // print options 00547 lcd.printString("SLOW",10,1); 00548 lcd.printString("MEDIUM",10,3); 00549 lcd.printString("FAST",10,5); 00550 lcd.printString("INSANE",46,1); 00551 00552 yCentre = 27; // set new y value for centre of selection circle 00553 lcd.drawCircle(xCentre ,yCentre ,3,1); // draw new selection circle 00554 lcd.refresh(); 00555 wait(0.3); 00556 } 00557 00558 else if (xCentre == 4 && yCentre == 27) { // medium 00559 lcd.clear(); 00560 lcd.printString("SLOW",10,1); 00561 lcd.printString("MEDIUM",10,3); 00562 lcd.printString("FAST",10,5); 00563 lcd.printString("INSANE!",46,1); 00564 yCentre = 43; 00565 lcd.drawCircle(xCentre ,yCentre ,3,1); 00566 lcd.refresh(); 00567 wait(0.3); 00568 } 00569 00570 else if (xCentre == 4 && yCentre == 43) { // fast 00571 lcd.clear(); 00572 lcd.printString("SLOW",10,1); 00573 lcd.printString("MEDIUM",10,3); 00574 lcd.printString("FAST",10,5); 00575 lcd.printString("INSANE",46,1); 00576 xCentre = 42; 00577 yCentre = 11; 00578 lcd.drawCircle(xCentre ,yCentre ,3,1); 00579 lcd.refresh(); 00580 wait(0.3); 00581 } 00582 } 00583 00584 if (joystick.direction == UP) { 00585 00586 if (xCentre == 42 && yCentre == 11) { // insane 00587 lcd.clear(); 00588 lcd.printString("SLOW",10,1); 00589 lcd.printString("MEDIUM",10,3); 00590 lcd.printString("FAST",10,5); 00591 lcd.printString("INSANE",46,1); 00592 xCentre = 4; 00593 yCentre = 43; 00594 lcd.drawCircle(xCentre ,yCentre ,3,1); 00595 lcd.refresh(); 00596 wait(0.3); 00597 } 00598 00599 else if (xCentre == 4 && yCentre == 43) { // fast 00600 lcd.clear(); 00601 lcd.printString("SLOW",10,1); 00602 lcd.printString("MEDIUM",10,3); 00603 lcd.printString("FAST",10,5); 00604 lcd.printString("INSANE!",46,1); 00605 yCentre = 27; 00606 lcd.drawCircle(xCentre ,yCentre ,3,1); 00607 lcd.refresh(); 00608 wait(0.3); 00609 } 00610 00611 else if (xCentre == 4 && yCentre == 27) { // medium 00612 lcd.clear(); 00613 lcd.printString("SLOW",10,1); 00614 lcd.printString("MEDIUM",10,3); 00615 lcd.printString("FAST",10,5); 00616 lcd.printString("INSANE",46,1); 00617 yCentre = 11; 00618 lcd.drawCircle(xCentre ,yCentre ,3,1); 00619 lcd.refresh(); 00620 wait(0.3); 00621 } 00622 } 00623 00624 00625 00626 00627 }
Generated on Tue Jul 12 2022 22:52:47 by
1.7.2