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.
