Thomas Davies / Mbed 2 deprecated LetTheBallDrop

Dependencies:   N5110 mbed PowerControl

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

Go to the documentation of this file.
00001 /**
00002 @file main.cpp
00003 @brief Source file for main game containing function defintions and main loop.
00004 @autor Thomas Davies
00005 @date May 2015
00006 */
00007 
00008 #include "main.h"
00009 
00010 
00011 int main()
00012 {
00013     DigitalOut backLight(p26);
00014     backLight.write(1);
00015     lcd.Initialize();
00016     powerSave();
00017 
00018     lcd.displayStartScreen();
00019     while(!isRight()) {}       //wait until right button pressed
00020 
00021     wait(0.5);          //just to ignore layover from first button press.
00022 
00023     lcd.displayInstructionScreen();
00024     while(!isRight()) {}    //wait until right button pressed.
00025 
00026     wait(0.5);
00027     lcd.displayInstructionScreen2();
00028     while(!isRight()) {}    //wait until right button pressed.
00029 
00030     lcd.displayCountdown();
00031     lcd.clear();
00032 
00033     bool refresh = false;
00034 
00035     lcd.drawAllPlatforms();
00036     lcd.drawBall();
00037     lcd.refresh();
00038 
00039     gameClock.attach(&clockCounter,0.003);  //attach the master clock!
00040 
00041     //MAIN GAME LOOP
00042     //multiple runs on a single loop. stop with a bool
00043 
00044     char buffer[10];
00045     while(true) {
00046         if (isFirstCheck) { //if first time checking this clock cycle.
00047             if(clockCount %(gameSpeed) == 0) {
00048                 //advance platforms
00049                 advancePlatforms(numPixelsToJump);
00050                 numPlatformShifts ++;
00051 
00052                 if (numPlatformShifts%5 == 0) {
00053                     gameLevel ++;
00054                 }
00055                 refresh = true;
00056             }
00057 
00058             if(clockCount%14 == 0) {
00059                 //ball movement
00060                 if (isLeft() && isBallDirClear(1)) {    //if josystick left and direction is clear
00061                     lcd.eraseBall();
00062                     lcd.setBallPos(lcd.getBallX ()+2,lcd.getBallY ());
00063                     refresh = true;
00064 
00065                 } else if (isRight() && isBallDirClear(0)) {
00066                     lcd.eraseBall();
00067                     lcd.setBallPos(lcd.getBallX ()-2,lcd.getBallY ());
00068                     refresh = true;
00069                 }
00070             }
00071 
00072             //if the ball is in free space, animate it falling!
00073             if (clockCount%(10/numPixelsToJump) == 0) {
00074                 if(isBallFalling(lcd.getBallY ())) {
00075                     lcd.eraseBall();
00076                     lcd.setBallPos(lcd.getBallX (),lcd.getBallY () + numPixelsToJump);
00077                     refresh = true;
00078                     isFirstHit = true;
00079                 }
00080             }
00081 
00082             if ((clockCount%(-45*gameSpeed + 2045) == 0)) {    //starting levels are quick to progress, later slower.
00083                 if (isFirstSpeedUp) //skip first accepted modulus!
00084                     isFirstSpeedUp = false;
00085                 else {
00086                     gameSpeed --;
00087                     isFirstSpeedUp = true;
00088                 }
00089             }
00090 
00091             if (joystickButton.read()) {    //pause menu!
00092                 int oldClock = clockCount;  //save the clock count!
00093                 pauseScreenController();
00094                 clockCount = oldClock;
00095                 wait(0.3);
00096                 lcd.clear();
00097                 refresh = true;
00098             }
00099 
00100             if (refresh) {
00101                 lcd.drawBall();
00102                 lcd.drawAllPlatforms();
00103 
00104                 sprintf(buffer,"lvl:%d",gameLevel);
00105                 lcd.printString(buffer,lcd.getMaxX () - 2,-1);
00106                 lcd.refresh();
00107                 refresh = false;
00108             }
00109 
00110 
00111             //check if ball hit roof
00112             if (lcd.getBallY () == 7) {
00113                 break;
00114             }
00115 
00116 
00117             isFirstCheck = false;
00118         }
00119     }
00120 
00121     gameClock.detach();
00122 
00123     lcd.clear();
00124 
00125     endScreenController();
00126     return 1;
00127 }
00128 
00129 
00130 //#############FUNCTION DEFINITIONS#################//
00131 void advancePlatforms(int n)
00132 {
00133     //ADVANCE
00134     lcd.eraseAllPlatforms();
00135     lcd.shiftAllPlatforms(n);
00136     lcd.drawAllPlatforms();
00137 
00138     //if ball is on platform
00139     if(!isBallFalling(lcd.getBallY ()-n)) {
00140         //auditory feedback if first collision
00141         if (isFirstHit) {
00142             boop();
00143             isFirstHit = false;
00144         }
00145         //move ball up with platform
00146         lcd.eraseBall();
00147         lcd.setBallPos(lcd.getBallX (),lcd.getBallY () -n);
00148     }
00149 
00150 
00151 }
00152 
00153 bool isBallFalling(int bY)
00154 {
00155     int bX = lcd.getBallX ();    //ball X pos
00156     int bR = lcd.getBallR ();    //ball radius
00157 
00158     //find next platform lower than ball
00159     //check Y pos to see if ball is on platform, return false if on plat
00160     //check X pos to see if ball is over gap, return true if over gap
00161     Platform closestPlatform = lcd.nextClosestPlatform(bY - bR);
00162 
00163 
00164     //if bottom of ball on level of platform
00165     if ((bY+bR) == (closestPlatform.y)) {
00166         if (bX > closestPlatform.x && (bX+bR-1) < (closestPlatform.x + lcd.getPlatGapSize ())) { //OVER GAP
00167             return true;
00168         } else {
00169             return false;
00170         }      //On platform!
00171     } else if ((bY+bR) >= (lcd.getMaxY ()-1)) {
00172         return false;
00173     } else  //FREE SPACE
00174         return true;
00175 }
00176 
00177 
00178 bool isBallDirClear(int dir)
00179 {
00180     Platform closestPlatform = lcd.nextClosestPlatform(lcd.getBallY () - lcd.getBallR ()+2);
00181 
00182     int ballRight = lcd.getBallX ();
00183     int ballLeft = ballRight+lcd.getBallR ();
00184     int ballTop = lcd.getBallY ();
00185     int ballBottom = ballTop + lcd.getBallR ();
00186 
00187     if (dir == 1) {
00188         if (ballBottom > closestPlatform.y)    //is ball inside a gap in platform?
00189             if (ballLeft >= (closestPlatform.x+lcd.getPlatGapSize ()))    //is the ball next to gap wall?
00190                 return false;
00191         if (ballLeft < lcd.getMaxX ()) {    //is ball next to left hand wall?
00192             return true;
00193         }
00194     } else if (dir == 0) {
00195         if (ballBottom > closestPlatform.y)    //is ball inside a gap in platform?
00196             if (ballRight <= closestPlatform.x)
00197                 return false;
00198 
00199         if (ballRight > 0) {   //right hand wall check
00200             return true;
00201         }
00202     }
00203     return false;
00204 }
00205 
00206 bool isRight()
00207 {
00208     double count = 0.0;
00209     double total = 0.0;
00210     //obtain an average to negate outliers
00211     while (count < 10) {
00212         count ++;
00213         total += joystickX.read();
00214     }
00215     if ((total/count)> 0.8)
00216         return true;
00217 
00218     return false;
00219 }
00220 
00221 bool isLeft()
00222 {
00223     double count = 0.0;
00224     double total = 0.0;
00225     //obtain an average to negate outliers
00226     while (count < 10) {
00227         count ++;
00228         total += joystickX.read();
00229     }
00230     if ((total/count) <  0.2)
00231         return true;
00232 
00233     return false;
00234 }
00235 
00236 bool isUp()
00237 {
00238     double count = 0.0;
00239     double total = 0.0;
00240     //obtain an average to negate outliers
00241     while (count < 10) {
00242         count ++;
00243         total += joystickY.read();
00244     }
00245 
00246     if ((total/count) <  0.2)
00247         return true;
00248 
00249     return false;
00250 }
00251 bool isDown()
00252 {
00253     double count = 0.0;
00254     double total = 0.0;
00255     //obtain an average to negate outliers
00256     while (count < 10) {
00257         count ++;
00258         total += joystickY.read();
00259     }
00260     if ((total/count) >  0.8)
00261         return true;
00262 
00263     return false;
00264 }
00265 
00266 void clockCounter ()
00267 {
00268     //increment clock count!
00269     clockCount ++;
00270     isFirstCheck = true;
00271 }
00272 
00273 void endScreenController()
00274 {
00275     int cursorLoc = 0;
00276     //cursor location array.
00277     int cursorArray[3][3] = {
00278         {1,0,0},
00279         {0,1,0},
00280         {0,0,1}
00281     };
00282 
00283     //check if user achieved high score
00284     bool record = isRecord();
00285 
00286     //if not a record move mouse start to second option
00287     if (!record)
00288         cursorLoc = 1;
00289 
00290     lcd.displayEndScreen(gameLevel,cursorArray[cursorLoc],record);
00291     bool change = false;
00292 
00293     while (true) {
00294         if (isUp()) {
00295             cursorLoc ++;   //advance cursor menu
00296             change = true;
00297         } else if (isDown()) {
00298             cursorLoc --;   //move back cursor menu
00299             change = true;
00300         }
00301 
00302         //cyclical cursor management
00303         if (cursorLoc == 3)
00304             cursorLoc = 1-record;
00305         else if (cursorLoc == (-record))
00306             cursorLoc = 2;
00307 
00308         //if theres a change to buffer, show it
00309         if (change) {
00310             lcd.displayEndScreen(gameLevel,cursorArray[cursorLoc],record);
00311             wait(0.5);
00312             change = false;
00313         }
00314 
00315         //menu selection manager
00316         if (joystickButton.read()) {
00317             switch(cursorLoc) {
00318                 case 0:
00319                     //take to initial entry page! (only allow if score > top 3)
00320                     wait(0.3);
00321                     highScoreEditor(recordEntryController(),record);
00322 
00323                     wait(1);
00324                     //reset once button pressed!
00325                     while(!joystickButton.read()) {}
00326                     mbed_reset();
00327                     break;
00328                 case 1:
00329                     //take to high score page!
00330                     highScoreEditor("",0);
00331                     wait(1);
00332                     //reset once button pressed.
00333                     while(!joystickButton.read()) {}
00334                     mbed_reset();
00335                     break;
00336                 case 2:
00337                     //restart
00338                     mbed_reset();
00339                     break;
00340             }
00341         }
00342     }
00343 }
00344 
00345 char* recordEntryController()
00346 {
00347     //array of letters to traverse
00348     char *letters = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
00349 
00350     //array of ints, each corresponding to letter in letters array
00351     int ptr[3] = {0,0,0};
00352 
00353     //cursor management variables
00354     int cursorLoc = 0;
00355     int cursorArray[3][3] = {
00356         {1,0,0},
00357         {0,1,0},
00358         {0,0,1}
00359     };
00360 
00361     lcd.displayRecordScreen(cursorArray[cursorLoc],letters[ptr[0]],letters[ptr[1]],letters[ptr[2]]);
00362 
00363     bool change = false;
00364 
00365     while (true) {
00366         if (isUp()) {
00367             cursorLoc ++;
00368             change = true;
00369         } else if (isDown()) {
00370             cursorLoc --;
00371             change = true;
00372         } else if (isLeft()) {
00373             //cyclical letter management
00374             if (ptr[cursorLoc] == 0)
00375                 ptr[cursorLoc] = 25;   //last letter
00376             else
00377                 ptr[cursorLoc] --;  //previous letter
00378             change = true;
00379         } else if (isRight()) {
00380             if (ptr[cursorLoc] == 25)
00381                 ptr[cursorLoc] = 0;  //first letter
00382             else
00383                 ptr[cursorLoc] ++;  //next letter
00384             change = true;
00385         }
00386 
00387         //cyclical mouse management
00388         if (cursorLoc == 3)
00389             cursorLoc = 0;
00390         else if (cursorLoc == -1)
00391             cursorLoc = 2;
00392 
00393         if (change) {
00394             lcd.displayRecordScreen(cursorArray[cursorLoc],letters[ptr[0]],letters[ptr[1]],letters[ptr[2]]);
00395             wait(0.2);
00396             change = false;
00397         }
00398 
00399         if (joystickButton.read()) {
00400             //go to high score screen
00401             static char initials[10];
00402             sprintf(initials,"%c%c%c",letters[ptr[0]],letters[ptr[1]],letters[ptr[2]]);
00403             return initials;
00404         }
00405     }
00406 }
00407 
00408 void highScoreEditor(char *playerInitials,bool isRecord)
00409 {
00410     //check if lvl is in top 3
00411     FILE *fp = fopen("/local/scores.csv","r");  //open for reading.
00412 
00413     char s_hs0[3],s_hs1[3],s_hs2[3];
00414     int d_hs[3];
00415 
00416     //if file exists, parse it
00417     if (fp != NULL) {
00418 
00419         char buffer[2];
00420 
00421         fscanf(fp,"%3s,%s",s_hs0,buffer);
00422         d_hs[0] = atoi(buffer);
00423         fscanf(fp,"%3s,%s",s_hs1,buffer);
00424         d_hs[1] = atoi(buffer);
00425         fscanf(fp,"%3s,%s",s_hs2,buffer);
00426         d_hs[2] = atoi(buffer);
00427 
00428         fclose(fp);
00429     }
00430     //else set arbitrary values!
00431     else {
00432         d_hs[0] = 0;
00433         d_hs[1] = 0;
00434         d_hs[2] = 0;
00435 
00436         strcpy(s_hs0,"---");
00437         strcpy(s_hs1,"---");
00438         strcpy(s_hs2,"---");
00439     }
00440 
00441     if (isRecord) {
00442 
00443         if (gameLevel >= d_hs[2]) {
00444             d_hs[2] = gameLevel;
00445             strncpy(s_hs2,playerInitials,3);
00446         }
00447         if (gameLevel >= d_hs[1]) {
00448             d_hs[2] = d_hs[1];
00449             d_hs[1] = gameLevel;
00450             strncpy(s_hs2,s_hs1,3);
00451             strncpy(s_hs1,playerInitials,3);
00452         }
00453         if (gameLevel >= d_hs[0]) {
00454             d_hs[1] = d_hs[0];
00455             d_hs[0] = gameLevel;
00456             strncpy(s_hs1,s_hs0,3);
00457             strncpy(s_hs0,playerInitials,3);
00458         }
00459 
00460         char buffer[40];
00461         sprintf(buffer,"%s,%d\n%s,%d\n%s,%d",s_hs0,d_hs[0],s_hs1,d_hs[1],s_hs2,d_hs[2]);
00462         fp = fopen("/local/scores.csv","w");
00463         fprintf(fp,buffer);
00464         fclose(fp);
00465     }
00466 
00467     lcd.displayHighScores(s_hs0,s_hs1,s_hs2,d_hs);
00468 }
00469 
00470 bool isRecord ()
00471 {
00472     //check if lvl is in top 3
00473     FILE *fp = fopen("/local/scores.csv","r");  //open for reading.
00474 
00475     //if file doesn't exist, then player has a highscore!
00476     if (fp == NULL)
00477         return true;
00478 
00479     int highScore;
00480     char buffer[2];
00481     char temp[3];
00482 
00483     for (int i = 0; i < 3; i++) {
00484         fscanf(fp,"%3s,%s",temp,buffer);
00485         highScore = atoi(buffer);
00486         if (gameLevel > highScore) {
00487             fclose (fp);
00488             return 1;
00489         }
00490     }
00491     fclose(fp);
00492     return 0;
00493 }
00494 
00495 void boop ()
00496 {
00497     if (isSound == 'Y') {
00498         buzzer.write(1);
00499         lowFlipper.attach_us(&pwmLow,pwmCount);
00500     }
00501 }
00502 
00503 void pwmLow()
00504 {
00505     if (pwmCount != 4000) {
00506         buzzer.write(0);
00507         highFlipper.attach_us(&boop,pwmCount);
00508         pwmCount += 50;
00509     } else
00510         pwmCount = 1000;
00511 
00512 }
00513 
00514 //can toggle sound or quit game.
00515 void pauseScreenController()
00516 {
00517     int cursorLoc = 0;
00518     int cursorArray[3][3] = {
00519         {1,0,0},
00520         {0,1,0},
00521         {0,0,1}
00522     };
00523 
00524     lcd.displayPauseScreen(cursorArray[cursorLoc],isSound);
00525 
00526     bool change = false;
00527     bool resume = false;
00528 
00529     while (!resume) {
00530         if (isUp()) {
00531             cursorLoc ++;
00532             change = true;
00533         } else if (isDown()) {
00534             cursorLoc --;
00535             change = true;
00536         } else if (isLeft() || isRight()) {
00537             if (isSound == 'Y')
00538                 isSound = 'N';
00539             else
00540                 isSound = 'Y';
00541             change = true;
00542         }
00543 
00544         //cyclical mouse management
00545         if (cursorLoc == 3)
00546             cursorLoc = 0;
00547         else if (cursorLoc == -1)
00548             cursorLoc = 2;
00549 
00550         if (change) {
00551             lcd.displayPauseScreen(cursorArray[cursorLoc],isSound);
00552             wait(0.2);
00553             change = false;
00554         }
00555 
00556         if (joystickButton.read()) {
00557             switch (cursorLoc) {
00558                 case 1:
00559                     mbed_reset();
00560                     break;
00561                 case 2:
00562                     resume = true;
00563                     break;
00564                 default:
00565                     break;
00566             }
00567         }
00568     }
00569 }
00570 
00571 void powerSave()
00572 {
00573     PHY_PowerDown();    //power down ethernet
00574     //mbed automatically manages peripheral power, no need to manually disable each
00575 }