Pong on uLCD with mbed
Overview
This is a Pong game developed using mbed microprocessor. To control the paddle, we use 2 pushbuttons, one move to the right and one move to the left. There is also a button for resetting the game and one to pause the game.
The objective of the game is to destroy all the blocks at the top of the screen. One can do this by moving the paddle at the bottom of the screen and making the ball bounce towards the blocks.
Equipment
Pushbuttons | mbed |
---|---|
Move right | P10 |
Move left | P11 |
Pause | P12 |
Reset | P13 |
uLCD Cable | uLCD Header | mbed |
---|---|---|
5V=VU | 5V | 5V |
Gnd | Gnd | Gnd |
P28 | RX | TX |
P27 | TX | RX |
P29 | Reset | Reset |
Video
Code
Import programlab4-Pong
mini project
main.cpp
#include "mbed.h" #include "uLCD_4DGL.h" uLCD_4DGL uLCD(p28, p27, p29); // create a global lcd object DigitalIn moveRight(p10); DigitalIn moveLeft(p11); DigitalIn pause(p12); DigitalIn resetButton(p13); /**Directions: Start the game by pressing pause button (p12) Push moveRight (p10) to move bottom rectangle right Push moveLeft (p11) to move bottom rectangle left Push pause to pause the game at any time Push resetButton (p13) to reset to game The game automatically resets when player loses or wins. Win by destroying all the blocks at the top Lose by letting the ball fall off bottom of screen **/ //LCD is 127x127 #define RADIUS 5 //Ball size #define NUMBER_OF_BLOCKS 10 //Number of blocks to break #define X_BALL_START 20 //X starting location of ball #define Y_BALL_START 50 //Y starting location of ball #define X_START_RECT 53 //X starting location of rectangle #define X_END_RECT 72 //X ending location of rectangle #define Y_START_RECT 121 //Y starting location of rectangle #define Y_END_RECT 126 //Y ending location of rectangle //Initialize global values that control rectangle, ball and rate of ball int x1Rec = X_START_RECT, x2Rec = X_END_RECT, xBall = X_BALL_START, yBall = Y_BALL_START, vX = -1, vY = 1; //Value 0 or 1 ***** 1 means block at location is alive int numOfBlocks [NUMBER_OF_BLOCKS]; int countBlocksDisappeared = 0; //Keeps track of number of blocks void play(); void pauseGame(); void reset(); void createStartingBlocks(); void checkHit(int index, int x1, int x2, int y1, int y2); void hitDirection(); int main() { uLCD.baudrate(3000000); moveRight.mode(PullUp); moveLeft.mode(PullUp); pause.mode(PullUp); resetButton.mode(PullUp); //Draw outline boundaries uLCD.line(0, 0, 127, 0, WHITE); //top uLCD.line(127, 0, 127, 127, WHITE); //right uLCD.line(127, 127, 0, 127, WHITE); //bottom uLCD.line(0, 127, 0, 0, WHITE); //left //Draw Ball starting location uLCD.filled_circle(X_BALL_START, Y_BALL_START, RADIUS, RED); //Draw Rectangle starting location uLCD.filled_rectangle(X_START_RECT, Y_START_RECT, X_END_RECT, Y_END_RECT, WHITE); //Validate the blocks createStartingBlocks(); while(1) { if(!pause){ wait(.5); play(); } } } void play() { while(1){ //Move rectangle left - up to boundary if(!moveLeft && x1Rec > 2){ //Erase current rectangle uLCD.filled_rectangle(x1Rec, Y_START_RECT, x2Rec, Y_END_RECT, BLACK); //Draw new rectangle x1Rec -=4; x2Rec -=4; uLCD.filled_rectangle(x1Rec, Y_START_RECT, x2Rec, Y_END_RECT, WHITE); } //Move rectangle right - up to boundary if(!moveRight && x2Rec < 125){ //Erase current rectangle uLCD.filled_rectangle(x1Rec, Y_START_RECT, x2Rec, Y_END_RECT, BLACK); //Draw new rectangle x1Rec +=4; x2Rec +=4; uLCD.filled_rectangle(x1Rec, Y_START_RECT, x2Rec, Y_END_RECT, WHITE); } //Draw ball uLCD.filled_circle(xBall, yBall, RADIUS, RED); //Erase ball uLCD.filled_circle(xBall, yBall, RADIUS, BLACK); //Check if hit bottom rectangle if(yBall + RADIUS == 121 && (xBall - RADIUS <= x2Rec && xBall + RADIUS >= x1Rec)) { //flip y direction vY = vY*(-1); hitDirection(); } //Check if hit layer 1 if(yBall - RADIUS >= 1 && yBall - RADIUS <= 6) { checkHit(0, 43, 52, 1, 6); checkHit(1, 53, 62, 1, 6); checkHit(2, 63, 72, 1, 6); checkHit(3, 73, 82, 1, 6); } //Check if hit layer 2 if(yBall - RADIUS >= 7 && yBall - RADIUS <= 12) { checkHit(4, 48, 57, 7, 12); checkHit(5, 58, 67, 7, 12); checkHit(6, 68, 77, 7, 12); } //Check if hit layer 3 if(yBall - RADIUS >= 13 && yBall - RADIUS <= 18) { checkHit(7, 53, 62, 13, 18); checkHit(8, 63, 72, 13, 18); } //Check if hit layer 4 if(yBall - RADIUS >= 19 && yBall - RADIUS <= 24) checkHit(9, 58, 67, 19, 24); //Check if ball hit left or right wall if(xBall <= RADIUS + 1 || xBall >= 126 - RADIUS) vX = vX*(-1); //Check if hit top wall if(yBall <= RADIUS + 1) vY = vY*(-1); //Check if lose if(yBall >= 126 - RADIUS) { //Wipe screen and print lose with large font wait(1); uLCD.cls(); uLCD.locate(0,5); uLCD.text_width(2); uLCD.text_height(2); uLCD.printf("YOU LOSE!"); wait(5); reset(); } //Move ball xBall += vX; yBall += vY; //Pause game if(!pause) pauseGame(); //Reset game if(!resetButton) reset(); //Check for win if(countBlocksDisappeared == 10) { //Wipe screen and print win with large font wait(1); uLCD.cls(); uLCD.locate(0,5); uLCD.text_width(2); uLCD.text_height(2); uLCD.printf("YOU WIN!"); wait(5); reset(); } } } void pauseGame() { //Ensure user has time to stop pressing button wait(1); //Spin until unpause while(pause){} //Give a little time to adjust wait(.5); } void reset() { //Wipe Screen uLCD.cls(); //Draw outline boundaries uLCD.line(0, 0, 127, 0, WHITE); //top uLCD.line(127, 0, 127, 127, WHITE); //right uLCD.line(127, 127, 0, 127, WHITE); //bottom uLCD.line(0, 127, 0, 0, WHITE); //left //restore init conditions x1Rec = X_START_RECT; x2Rec = X_END_RECT; xBall = X_BALL_START; yBall = Y_BALL_START; vX = -1; vY = 1; //Draw Ball starting location uLCD.filled_circle(xBall, yBall, RADIUS, RED); //Draw Rectangle starting location uLCD.filled_rectangle(x1Rec, Y_START_RECT, x2Rec, Y_END_RECT, WHITE); createStartingBlocks(); //Press pause button to restart game pauseGame(); } void createStartingBlocks() { /**Draw Blocks */ //Layer 1 uLCD.filled_rectangle(43, 1, 52, 6, WHITE); uLCD.filled_rectangle(53, 1, 62, 6, WHITE); uLCD.filled_rectangle(63, 1, 72, 6, WHITE); uLCD.filled_rectangle(73, 1, 82, 6, WHITE); //Layer 2 uLCD.filled_rectangle(48, 7, 57, 12, WHITE); uLCD.filled_rectangle(58, 7, 67, 12, WHITE); uLCD.filled_rectangle(68, 7, 77, 12, WHITE); //Layer 3 uLCD.filled_rectangle(53, 13, 62, 18, WHITE); uLCD.filled_rectangle(63, 13, 72, 18, WHITE); //Layer 4 uLCD.filled_rectangle(58, 19, 67, 24, WHITE); //Set validator countBlocksDisappeared = 0; for(int i = 0; i<NUMBER_OF_BLOCKS; i++) numOfBlocks[i] = 1; } void checkHit(int index, int x1, int x2, int y1, int y2) { //Check block if active if(numOfBlocks[index] == 1 && xBall - RADIUS <= x2 && xBall + RADIUS >= x1) { //Inactivate block numOfBlocks[index] = 0; countBlocksDisappeared++; //Flip y direction of ball vY = vY*(-1); //Erase rectangle uLCD.filled_rectangle(x1, y1, x2, y2, BLACK); //Check if necessary to flip x direction of ball hitDirection(); } } void hitDirection() { //Comes from right if(xBall - vX > xBall) { //Check if x direction if(xBall > (x1Rec+x2Rec)/2) vX = vX*(-1); } //Comes from left if(xBall - vX < xBall) { //Check if x direction if(xBall < (x1Rec+x2Rec)/2) vX = vX*(-1); } }
Please log in to post comments.