Racing Cars game using N5110 LCD and thumb Joystick
Dependencies: N5110 PowerControl beep mbed
main.cpp
- Committer:
- el13gs
- Date:
- 2015-05-11
- Revision:
- 8:699055e89c7d
- Parent:
- 7:edf0f1fcb16b
File content as of revision 8:699055e89c7d:
/** @file main.cpp @brief Contains all functions implementations, and main program */ #include "main.h" int main() { Peripheral_PowerDown(0xFFFFFFFF); //turn off all peripherals /* turn on only the required peripherals */ Peripheral_PowerUp(0x800000); Peripheral_PowerUp(0x200000); Peripheral_PowerUp(0x40); Peripheral_PowerUp(0x8000); Peripheral_PowerUp(0x1000); sprintf(soundString,"%s","YES"); //set the Sound Initial String to YES calibrateJoystick(); // get centred values of joystick pollJoystick.attach(&updateJoystick,1.0/20.0); // read joystick 30 times per second lcd.setXYAddress(0,0);//set the XY address to 0.0 as initialising condition initTable();//initialise the array table lcd.init();//initialise LCD screen lcd.refresh(); /* PRINT WELCOMING MESSAGES */ lcd.printString("RACING CARS",9,1); wait(0.5); lcd.printString("GAME",29,2); wait(0.5); lcd.printString("by Giorgos",14,4); wait(0.5); lcd.printString("Savvides",16,5); wait(2); lcd.clear(); lcd.refresh(); lcd.printString("USE JOYSTICK",0,0); lcd.printString("AND BUTTONS ",0,1); lcd.printString("ON THE RIGHT",0,2); lcd.printString("TO NAVIGATE",0,3); lcd.printString("HAVE FUN!!!",12,5); wait(3.5); start.rise(&startButtonPressed); // Call function startButtonPressed when START button pressed reset.rise(&resetButtonPressed); // Call function resetButtonPressed when RESET button pressed MainMenu: /* INITIAL DISPLAY IN MAIN MENU */ int menuPointer=1; // set the Pointer in Main Menu initially to 1 startButtonFlag=0; // reset the pointing flags resetButtonFlag=0; // reset the pointing flags clearCells(84,48); // clear the whole Screen Cells lcd.refresh(); // refresh are done after and before setting or clearing Pixels lcd.drawCircle(22,19,2,1); //initial condition draw pointer around Play submenu lcd.drawCircle(53,19,2,1); //initial condition draw pointer around Play submenu lcd.printString("MAIN MENU",15,0); //print title lcd.printString("Play",26,2); //print submenu title lcd.printString("Options",20,3); //print submenu title lcd.drawLine(15,9,65,9,1);//underline main menu title wait(0.1); /* While start Button is not pressed user can navigate through main Menu Submenus */ while(startButtonFlag==0) { /* when joystick moves down, pointer selects Options subMenu */ if (joystick.direction==DOWN) { lcd.drawCircle(16,27,2,1); //draw pointer around Options submenu when selected lcd.drawCircle(64,27,2,1); //draw pointer around Options submenu when selected lcd.clearCircle(53,19,2,1); //clear pointer around Play submenu lcd.clearCircle(22,19,2,1); //clear pointer around Play submenu menuPointer=2; //set Pointer to 2 } /* when joystick moves up, pointer selects Options subMenu */ if(joystick.direction==UP) { lcd.drawCircle(22,19,2,1); //draw pointer around Play submenu when selected lcd.drawCircle(53,19,2,1); //draw pointer around Play submenu when selected lcd.clearCircle(16,27,2,1); //clear pointer around Options submenu lcd.clearCircle(64,27,2,1); //clear pointer around Options submenu menuPointer=1; //set Pointer to 1 } sleep(); } /* SELECT POINTER CONDITION */ switch(menuPointer) { /* Case when Play was selected */ case 1: /*INITIAL GAME CONDITIONS */ startButtonFlag=0; //reset start Button Flag gamePlays=1; // Begin the game with pointer set to 1 lives=5; // set lives to 5 round=1; // set round number to 1 coins=0; // set coin number to 0 clearCells(84,48); //clear the whole LCD screen lcd.refresh(); lcd.printString("READY?",20,3); wait(0.75); lcd.printString("GET SET",20,3); wait(1); lcd.printString(" GO !!!",20,3); wait(1); lcd.clear(); lcd.refresh(); gameReset(); // set and draw initial player and enemies position timer.attach(&movePlayer,0.1);// attach timer to call function that moves the Player while(gamePlays) { //print Round number on buffer and display sprintf(roundBuffer,"%d",round); lcd.printString(roundBuffer,74,3); lcd.refresh(); //print Lives number on buffer and display sprintf(livesBuffer,"%d",lives); lcd.printString(livesBuffer,74,1); lcd.refresh(); //print Coins number on buffer and display sprintf(coinsBuffer,"%d",coins); lcd.printString(coinsBuffer,72,5); lcd.refresh(); enemy1MovesDown(); //move enemy 1 downwards checkPlayerPos(); //check player position frequently if (gamePlays==0) { // if gameplay is 0 returns to initial MAIN MENU goto MainMenu; } lcd.refresh(); enemy2MovesDown(); //move enemy 2 downwards checkPlayerPos(); if (gamePlays==0) { goto MainMenu; } lcd.refresh(); enemy3MovesDown(); //move enemy 3 downwards checkPlayerPos(); if (gamePlays==0) { goto MainMenu; } coinMoves(); // move coin downwards lcd.refresh(); checkPlayerPos(); if (gamePlays==0) { goto MainMenu; } } break; case 2: int optionsMenu=1; // set options Menu enabled optionsPointer=1; startButtonFlag=0; //reset START Button Flag clearCells(84,48); // clear all screen Cells lcd.refresh(); wait(0.02); /* PRINT OPTIONS SUBMENU DISPLAY */ lcd.printString("OPTIONS",18,0); lcd.printString("Exit",23,5); lcd.printString("Brightness",6,3); lcd.printString("Sound",6,2); lcd.drawLine(15,8,61,8,1); //underline Options Menu title /* Print brightness value ranged from 1 to 10 to user */ sprintf(brightnessBuffer,"%d",brightnessDisplay); lcd.printString(brightnessBuffer,68,3); /* Print Sound string value , "YES" or "NO"*/ lcd.printString(soundString,40,2); /* USER NAVIGATES WHILE IN OPTIONS MENU */ while(optionsMenu) { /* If direction is up pointer value decrease by 1 (cannot decrease to less than 1) */ if (joystick.direction==UP) { optionsPointer--; if(optionsPointer==0) { optionsPointer=1; } } wait(0.05); /* If direction is down, pointer value increase by 1 (cannot increase to more than 3) */ if(joystick.direction==DOWN) { optionsPointer++; if(optionsPointer>3) { optionsPointer=3; } } /* CASES FOR EACH POINTER VALUE */ /* when it is 1, Sound submenu is selected */ if (optionsPointer==1) { /* print Circle pointer around Sound submenu */ lcd.drawCircle(2,19,2,1); lcd.clearCircle(2,27,2,1); lcd.clearCircle(19,44,2,1); /* if pointer is 1 and joystick direction is left, sound is enabled (=1)*/ if(joystick.direction==LEFT) { sounds=1; lcd.refresh(); sprintf(soundString,"%s","YES"); lcd.printString(soundString,40,2); } /* if pointer is 1 and joystick direction is right, sound is disabled (=0)*/ if(joystick.direction==RIGHT) { sounds=0; lcd.refresh(); sprintf(soundString,"%s","NO "); //print string in buffer lcd.printString(soundString,40,2); //display value of buffer } sleep(); } /* when it is 2, brightness submenu is selected */ if (optionsPointer==2) { /* print Circle pointer around Brightness submenu */ lcd.drawCircle(2,27,2,1); lcd.clearCircle(2,19,2,1); lcd.clearCircle(19,44,2,1); /* if pointer is 2 and joystick direction is left, brightness decreases by 0.1*/ if(joystick.direction==LEFT) { brightness=brightness-.1; brightnessDisplay=brightnessDisplay-1; // user displayed value also decrease if(brightness<0.1||brightnessDisplay<0) { // brightnessDisplay and brightness never go below 0 and 0.1 respectively brightnessDisplay=1; brightness=0.1; } lcd.setBrightness(brightness); //sets the brightness /* print brightness Display on screen */ sprintf(brightnessBuffer,"%d",brightnessDisplay); lcd.printString(brightnessBuffer,68,3); } /* if pointer is 2 and joystick direction is right, brightness increases by 0.1*/ if(joystick.direction==RIGHT) { brightness=brightness+.1; brightnessDisplay=brightnessDisplay+1; // user displayed value also increase if(brightness>0.9||brightnessDisplay>9) {// brightnessDisplay and brightness never go above 9 and 0.9 respectively brightnessDisplay=9; brightness=0.9; } lcd.setBrightness(brightness); //sets the brightness /* print brightness Display on screen */ sprintf(brightnessBuffer,"%d",brightnessDisplay); lcd.printString(brightnessBuffer,68,3); } sleep(); } if (optionsPointer==3) { /* print Circle pointer around Exit submenu */ lcd.drawCircle(19,44,2,1); lcd.clearCircle(2,19,2,1); lcd.clearCircle(2,27,2,1); /* if START button is press while pointer is on Exit goes back to Main Menu label */ if(startButtonFlag) { startButtonFlag=0; wait(0.5); optionsMenu=0; goto MainMenu; } sleep(); } wait(0.05); sleep(); } break; } } void startButtonPressed() { startButtonFlag=!startButtonFlag; } void resetButtonPressed() { resetButtonFlag=!resetButtonFlag; } void movePlayer() { if (gamePlays) { /* if direction is RIGHT clears the previous Car shape and draws the next one by increasing the x position */ if (joystick.direction==RIGHT&&x+w<58) { clearRect(x,v,w,h); lcd.refresh(); x=x+4; lcd.drawRect(x,v,w,h,0); lcd.refresh(); } /* if direction is LEFT clears the previous Car shape and draws the next one by decreasing the x position */ if (joystick.direction==LEFT&&x+w>10) { clearRect(x,v,w,h); lcd.refresh(); x=x-4; lcd.drawRect(x,v,w,h,0); lcd.refresh(); } /* if direction is UP clears the previous Car shape and draws the next one by decreasing the y position */ if (joystick.direction==UP && v>2) { clearRect(x,v,w,h); lcd.refresh(); v=v-4; lcd.drawRect(x,v,w,h,0); lcd.refresh(); } /* if direction is DOWN clears the previous Car shape and draws the next one by increasing the y position */ if (joystick.direction==DOWN && v<32) { clearRect(x,v,w,h); lcd.refresh(); v=v+4; lcd.drawRect(x,v,w,h,0); lcd.refresh(); } } } void calibrateJoystick() { button.mode(PullDown); // must not move during calibration joystick.x0 = xPot; // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) joystick.y0 = yPot; } void updateJoystick() { joystick.x = xPot - joystick.x0; joystick.y = yPot - joystick.y0; // read button state joystick.button = button; // calculate direction depending on x,y values // tolerance allows a little lee-way in case joystick not exactly in the stated direction if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = CENTRE; } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = UP; } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = DOWN; } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = LEFT; } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = RIGHT; } else { joystick.direction = UNKNOWN; } // set flag for printing printFlag = 1; } void clearRect(int x,int v,int w,int h) { // loop through the array cells, clear the Pixels and array cells value(=0) for(int i=x; i<=x+w; i++) { for(int j=v; j<=v+h; j++) { lcd.clearPixel(i,j); table[i][j]=0; } } } void enemy1MovesDown() { clearRect(enemy1x,(j-a),w,h); // clears the previous Enemy Car lcd.refresh(); lcd.drawRect(enemy1x,j,w,h,1); //draws the next enemy Car lcd.refresh(); setRectCells(enemy1x,j,w,h); //set the current enemy cells to 1 lcd.refresh(); wait(0.05); j=j+a; //increase the y-position counter if(j>70) { // after reaching certain y position, randomize it again br j=-(rand()%95+85); } } void enemy2MovesDown() { clearRect(enemy2x,(p-a),w,h); // clears the previous Enemy Car lcd.refresh(); lcd.drawRect(enemy2x,p,w,h,1); //draws the next enemy Car lcd.refresh(); setRectCells(enemy2x,p,w,h); //set the current enemy cells to 1 lcd.refresh(); wait(0.05); p=p+a; //increase the y-position counter if(p>70) { p=-(rand()%60+40); } } void enemy3MovesDown() { clearRect(enemy3x,(q-a),w,h); lcd.refresh(); lcd.drawRect(enemy3x,q,w,h,1); lcd.refresh(); setRectCells(enemy3x,q,w,h); lcd.refresh(); wait(0.05); lcd.refresh(); q=q+a; if (q>70) { q=-(rand()%34+3); } } void setRectCells(int x,int v,int w,int h) { // Sets the Rectangle Array Cells equal to 1, indicating there is an enemy for(int i=x; i<=x+w; i++) { for(int j=v; j<=v+h; j++) { if(j>0&&j<48) { table[i][j]=1; } } } } void initTable() { // initialise the Array's cells, set them equal to 0 for (int i=0; i<=83; i++) { for(int j=0; j<=47; j++) { table[i][j]=0; } } } void checkPlayerPos() { // frequently calling this function to check if player touched an enemy or a coin /* if player cells equal to 1, means he touched enemy, so loose function is being called */ if (table[x+w][v+h]==1||table[x][v+h]==1||table[x][v]==1||table[x+w][v]==1) { loose(); } /* if player cells equal to 2, means he touched a coin */ if (table[x+w][v+h]==2||table[x][v+h]==2||table[x][v]==2||table[x+w][v]==2) { coins=coins+5; //each coin's value is 5,total coins increase by 5 clearCoin(c); //clear the collected Coin lcd.drawRect(x,v,w,h,0);//redraw Player boundaries that were cleared by Coin if(sounds) { // if sound is enabled in options menu sound produced when got a coin buzzer.beep(2200,0.4); //produce sound of frequency 2200 Hz and duration 0.4 s buzzer.beep(1000,0.2); lcd.setBrightness(brightness); //set brightness again, frequency produced interfere with LCD pin } coinAppear=0; //switch coin status to disappear /* then Check the total number of coins, to produce to next Round */ if(coins==30) { // if coins are 40 proceed to next Round round=2; // change Round Value gamePlays=0; // stop gameplay, preventing user moving on screen clearCells(84,48); //clear all Cells lcd.refresh(); lcd.printString("ROUND 2",10,2); //print Round message wait(1); clearCells(84,48);// clear all Cells lcd.refresh(); gamePlays=1;//start gameplay gameReset();//reset player and enemies positions a=6; //change enemies acceleration (a is added to y positions counter) } if(coins==70) { // if coins are 70 proceed to next Round round=3; // change Round Value gamePlays=0;// stop gameplay, preventing user moving on screen clearCells(84,48); //clear all Cells lcd.refresh(); lcd.printString("ROUND 3",10,2); //print Round message wait(1); clearCells(84,48); // clear all Cells lcd.refresh(); gamePlays=1; //start gameplay gameReset(); //reset player and enemies positions a=8; //change enemies acceleration (a is added to y positions counter) } if(coins==90) { // if coins are 90, player WINS the game timer.detach(); //stop player moving clearCells(84,48); //clear pixels lcd.clear(); //clear LCD lcd.refresh(); lcd.printString("CONGRATS!",0,2); //print win message lcd.printString("YOU WON!",8,3); //print win message wait(4); gamePlays=0; //game finishes } } } void coinMoves() { if(table[xPos][c]==1||table[xPos][c+4]==1||table[xPos+4][c+4]==1) { //prevent coin from appearing above enemies clearCoin(c); //clear current Coin coinAppear=0; //make coin disappear (prevent from being redrawn) } clearCoin(c); //clear current Coin c=c+4; // increase Coin's y coordinate counter drawCoin(c); //draw next Coin position if(c>80) { // if counter exceeds 80, randomizes x and y positions and make it reappear c=-(rand()%10); xPos=rand()%52+4; coinAppear=1; } } void drawCoin(int c) { if (c>4&&c<48&&coinAppear==1) { //check if coin c point(y pos) is within LCD limits lcd.drawCircle(xPos,c,4,0); //Draw Coin Circle Pixels setCircleCells(xPos,c,4);// Set Coin array's cells values to 2 // "c" character Print on coin lcd.setPixel(xPos,c-1); lcd.setPixel(xPos,c+2); lcd.setPixel(xPos+1,c-1); lcd.setPixel(xPos+1,c+2); lcd.setPixel(xPos-1,c); lcd.setPixel(xPos-1,c+1); lcd.refresh(); } } void clearCoin(int c) { if(c>4&&c<48&&coinAppear==1) { // if c point of the Coin within the LCD limits lcd.clearCircle(xPos,c,4,1); //Clear the Coin clearCircleCells(xPos,c,4);// Set Coin array's cells values to 0 lcd.refresh(); } } void loose() { if (sounds) { //check if sound is enabled and produce a "loose" sound of frequency 400 Hz buzzer.beep(400,0.2); lcd.setBrightness(brightness); //set brightness } timer.detach(); //detach moving Player function timer, so player cannot move lives=lives-1; //decrease lives value startButtonFlag=0; //reset START button flag resetButtonFlag=0;//reset SELECT button flag if(lives==0) { //if lives are equal to 0, Game Over is displayed clearCells(84,48); lcd.refresh(); lcd.clear(); wait(1); while(startButtonFlag==0&&resetButtonFlag==0) { //while no button is pressed lcd.printString("Game Over!!!",0,0); lcd.printString("Press START",0,2); lcd.printString("to try again",0,3); lcd.printString("or RESET",0,4); lcd.printString("to exit :)",0,5); } if(startButtonFlag) { //START button pressed, resets the game a=4; gamePlays=1; lives=5; coins=0; round=1; clearCells(84,48); gameReset(); startButtonFlag=0; wait(1); timer.attach(&movePlayer,0.1); } if (resetButtonFlag) { //RESET button pressed, sets gameplay to 0 ( when gameplay is 0 , returns to MAIN MENU) gamePlays=0; resetButtonFlag=0; } } else { clearCells(60,48); //else if lives are not 0, clearCells and reset the game lcd.refresh(); gameReset(); // reset player and enemies values wait(2); gamePlays=1;// game is being played timer.attach(&movePlayer,0.1); //attach move Player function } } void gameReset() { initTable(); // initialise the array (set cells values to 0) x=26; //initial player x position v=30; //initial player y position lcd.drawRect(x,v,w,h,0); //draw player at initial position lcd.refresh(); j=-70; // enemy y position, initialise q=-10; // enemy y position, initialise p=-40; // enemy y position, initialise } void setCircleCells(int x0,int y0,int radius) { //function from N5110 Library, works only for filled circle int x = radius; int y = 0; while(x >= y) { setLineCells(x+x0,y+y0,-x+x0,y+y0,0); //set line's Cells values to 2 setLineCells(y+x0,x+y0,-y+x0,x+y0,0);//set line's Cells values to 2 setLineCells(y+x0,-x+y0,-y+x0,-x+y0,0);//set line's Cells values to 2 setLineCells(x+x0,-y+y0,-x+x0,-y+y0,0);//set line's Cells values to 2 y++; } } void clearCircleCells(int x0,int y0,int radius) { //function from N5110 Library, works only for filled circle int x = radius; int y = 0; while(x >= y) { clearLineCells(x+x0,y+y0,-x+x0,y+y0,0);//set line's Cells values to 0 clearLineCells(y+x0,x+y0,-y+x0,x+y0,0);//set line's Cells values to 0 clearLineCells(y+x0,-x+y0,-y+x0,-x+y0,0);//set line's Cells values to 0 clearLineCells(x+x0,-y+y0,-x+x0,-y+y0,0);//set line's Cells values to 0 y++; } } void clearCells(int x,int y) { // loops through cells, clears the pixels and set the cells value equal to 0 for(int i=0; i<=x; i++) { for (int j=0; j<=y; j++) { lcd.clearPixel(i,j); table[i][j]=0; } } lcd.refresh(); } void setLineCells(int x0,int y0,int x1,int y1,int type) { //function from N5110 Library int y_range = y1-y0; // calc range of y and x int x_range = x1-x0; int start,stop,step; // if dotted line, set step to 2, else step is 1 step = (type==2) ? 2:1; // make sure we loop over the largest range to get the most pixels on the display // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels // or else we'll only end up with 1 pixel in the x column if ( abs(x_range) > abs(y_range) ) { // ensure we loop from smallest to largest or else for-loop won't run as expected start = x1>x0 ? x0:x1; stop = x1>x0 ? x1:x0; // loop between x pixels for (int x = start; x<= stop ; x+=step) { // do linear interpolation int y = y0 + (y1-y0)*(x-x0)/(x1-x0); table[x][y]=2; // set table values to 2 } } else { // ensure we loop from smallest to largest or else for-loop won't run as expected start = y1>y0 ? y0:y1; stop = y1>y0 ? y1:y0; for (int y = start; y<= stop ; y+=step) { // do linear interpolation int x = x0 + (x1-x0)*(y-y0)/(y1-y0); table[x][y]=2; // set table values to 2 } } } void clearLineCells(int x0,int y0,int x1,int y1,int type) { //function from N5110 Library int y_range = y1-y0; // calc range of y and x int x_range = x1-x0; int start,stop,step; // if dotted line, set step to 2, else step is 1 step = (type==2) ? 2:1; // make sure we loop over the largest range to get the most pixels on the display // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels // or else we'll only end up with 1 pixel in the x column if ( abs(x_range) > abs(y_range) ) { // ensure we loop from smallest to largest or else for-loop won't run as expected start = x1>x0 ? x0:x1; stop = x1>x0 ? x1:x0; // loop between x pixels for (int x = start; x<= stop ; x+=step) { // do linear interpolation int y = y0 + (y1-y0)*(x-x0)/(x1-x0); table[x][y]=0; // set Table Cell to 0 } } else { // ensure we loop from smallest to largest or else for-loop won't run as expected start = y1>y0 ? y0:y1; stop = y1>y0 ? y1:y0; for (int y = start; y<= stop ; y+=step) { // do linear interpolation int x = x0 + (x1-x0)*(y-y0)/(y1-y0); table[x][y]=0; // set Table Cell to 0 } } }