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

uLCD

pushbuttons

/media/uploads/vinceli/img_20141021_014019.jpg /media/uploads/vinceli/img_20141021_014115.jpg /media/uploads/vinceli/img_20141021_014131.jpg /media/uploads/vinceli/img_20141021_014213.jpg

Pushbuttonsmbed
Move rightP10
Move leftP11
PauseP12
ResetP13
uLCD CableuLCD Headermbed
5V=VU5V5V
GndGndGnd
P28RXTX
P27TXRX
P29ResetReset

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.