0% found this document useful (0 votes)
610 views

Ping Pong Game Using Arduino

This document describes using an Arduino board to create a ping pong game simulation. It provides code and explanations for interfacing an LCD display with Arduino, operating virtual paddles using push buttons, and moving a ball on the display by updating its position and checking for collisions with the paddles. Key components used include an LCD display, push buttons, resistors, and a POT variable resistor. The code stores the game state, including paddle and ball positions, and updates the display after each move.

Uploaded by

Gurmeet Arora
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
610 views

Ping Pong Game Using Arduino

This document describes using an Arduino board to create a ping pong game simulation. It provides code and explanations for interfacing an LCD display with Arduino, operating virtual paddles using push buttons, and moving a ball on the display by updating its position and checking for collisions with the paddles. Key components used include an LCD display, push buttons, resistors, and a POT variable resistor. The code stores the game state, including paddle and ball positions, and updates the display after each move.

Uploaded by

Gurmeet Arora
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Ping Pong Game Using Arduino

Arduino consists of both a physical programmable circuit board (often referred


to as a microcontroller) and a piece of software, or IDE (Integrated
Development Environment) that runs on your computer, used to write and
upload computer code to the physical board.

Why Arduino?
Thanks to its simple and accessible user experience, Arduino has been used in
thousands of different projects and applications. The Arduino software is easy-
to-use for beginners, yet flexible enough for advanced users. It runs on Mac,
Windows, and Linux. Teachers and students use it to build low cost scientific
instruments, to prove chemistry and physics principles, or to get started with
programming and robotics.

Table tennis, also known as Ping Pong, is a game in which two or four
players hit a little, light ball back and forth across a table using a small
paddle. A point is scored when a player fails to return the ball to the other
player.

Components Used:
LCD Display (16*2)
Connecting Wires
Resistors (10K ohms * 4 resistors for push buttons; 220
ohms for Lcd)
Push Buttons (4)
POT(Variable Resistor )
Interfacing LCD with Arduino:

Circuit Connection:
Code:
#include<LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);

void setup()

lcd.begin(16,2);

lcd.setCursor(0,0);

lcd.print("First Row");

void loop()

delay(10); // Delay a little bit to improve simulation performance

}
Operating Paddles of Ping Pong game using Push
Buttons:

Circuit Connection:
Code:
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Holds paddle data in 2 separate arrays for easy

// character printing

// Characters LEDs are turned on by marking them as

// boolean true or false and then converting from binary

// to base 10 16 = 10000 where binary digits go 16 8 4 2 1

//

byte aiPaddleArray[2][8] = {0,0,0,0,0,1,1,1};

byte myPaddleArray[2][8] = {0,0,0,0,0,16,16,16};

// Used to make logic easier for when moving paddles

byte aiPaddleColArray[16] = {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0};

byte myPaddleColArray[16] = {0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0};

// Holds middle pixel for each paddle

byte aiPaddlePos = 6;

byte myPaddlePos = 6;

// Buttons that move the paddle


const int moveRightButton = 8;

const int moveLeftButton = 7;

// Stores whether buttons have been pressed

int rightButState = 0;

int leftButState = 0;

// Store previous button state so we only count input once

int rightLastButState = 0;

int leftLastButState = 0;

// 0 out all the paddle leds

void ClearPaddles(){

for(int i = 0; i < 2; i++){

for(int j = 0; j < 8; j++){

aiPaddleArray[i][j] = 0;

myPaddleArray[i][j] = 0;

void PrintPaddles(){
// Grab the character array stored in myPaddleArray using a pointer

byte* mPTemp1 = myPaddleArray[0];

byte* mPTemp2 = myPaddleArray[1];

byte* aiPTemp1 = aiPaddleArray[0];

byte* aiPTemp2 = aiPaddleArray[1];

// Each character must have a unique character ID and array to print

lcd.createChar(0, mPTemp1);

lcd.createChar(1, mPTemp2);

lcd.createChar(2, aiPTemp1);

lcd.createChar(3, aiPTemp2);

// Move cursor to 13 column on the 1st row

lcd.setCursor(14, 0);

// Draw the character

lcd.write(byte(0));

lcd.setCursor(14, 1);

lcd.write(byte(1));
lcd.setCursor(1, 0);

lcd.write(byte(2));

lcd.setCursor(1, 1);

lcd.write(byte(3));

for(int i = 0; i < 8; i++){

Serial.println(mPTemp1[i]);

// Clear paddle characters and then add character data

void SetupPaddles(){

ClearPaddles();

myPaddleArray[0][5] = 16;

myPaddleArray[0][6] = 16;

myPaddleArray[0][7] = 16;

aiPaddleArray[0][5] = 1;

aiPaddleArray[0][6] = 1;

aiPaddleArray[0][7] = 1;
PrintPaddles();

void MovePaddleUp(){

// Make sure the paddle can't go off the board

if(myPaddlePos != 1){

// Decrementing the paddle moves it up

myPaddlePos--;

UpdatePaddlesAfterMove();

void MovePaddleDown(){

if(myPaddlePos != 14){

myPaddlePos++;

UpdatePaddlesAfterMove();

}
void UpdatePaddlesAfterMove(){

// Cycle through all bools turning on the next 1 above and off the 1
below

for(int i = 0; i < 16; i++){

if((i == (myPaddlePos-1)) || (i == myPaddlePos) || (i ==


(myPaddlePos+1))){

myPaddleColArray[i] = 16;

} else {

myPaddleColArray[i] = 0;

// Update the arrays used for printing the paddle characters

for(int j = 0; j < 8; j++){

myPaddleArray[0][j] = myPaddleColArray[j];

for(int k = 8; k < 16; k++){

myPaddleArray[1][k-8] = myPaddleColArray[k];

void setup() {

Serial.begin(9600);
// State that the display has 2 rows with 16

// characters per row

lcd.begin(16, 2);

// Setup buttons so we can receive input

pinMode(moveRightButton, INPUT);

pinMode(moveLeftButton, INPUT);

// Print paddles on the screen

SetupPaddles();

void loop() {

// Get current button state

rightButState = digitalRead(moveRightButton);

leftButState = digitalRead(moveLeftButton);

// Check the button state change

if(rightButState != rightLastButState){
// Check if button was pressed

if(rightButState == HIGH){

// Move paddle up if you can and redraw

MovePaddleUp();

PrintPaddles();

// Added to avoid bouncing

delay(50);

// Store last button state

rightLastButState = rightButState;

// Check the button state change

if(leftButState != leftLastButState){

// Check if button was pressed

if(leftButState == HIGH){

// Move paddle up if you can and redraw

MovePaddleDown();
PrintPaddles();

// Added to avoid bouncing

delay(50);

// Store last button state

leftLastButState = leftButState;

}
Moving Ball in Game:
Circuit diagram is same as above
Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// ---------- NEW ----------

// Stores the whole gameBoard


byte gameBoard[16][80] = {};

// Delay for updating the ball


int ballUpdateTime = 100;

// Ball starts off going horizontal


byte ballXDir = 0;

// Call starts off going left


byte ballYDir = -1;

// Starting ball x/y for storing in gameBoard


byte ballX = 7;
byte ballY = 35;

// Temporarily stores character created for drawing


// the ball before drawing to LCD
byte ballCharArray[8] = {};

// Stores scores
byte playerScore = 0;
byte aiScore = 0;

// Holds middle pixel for each paddle


// Hit above go up / below go down / center go straight
byte aiPaddlePos = 8;
byte myPaddlePos = 8;

// Ball steps
// 1. Ball starts moving to the right
// 2. With each move
// A. Delete previous space
// B. Light new space
// C. Check if paddle is in new space
// i. Check if ball hits PaddlePos, above PaddlePos, or below Paddle Pos
// ii. Change ballXDir & ballYDir accordingly
// a. PaddlePos : -XDir, YDir = 0
// b. PaddlePos - 1 : -XDir, YDir - 1
// c. PaddlePos + 1 : -XDir, YDir + 1
// iii. Clear old ball
// D. Check if top wall is hit
// i. XDir not changed, YDir - 1
// ii. Clear old ball
// E. Check if bottom wall is hit
// i. XDir not changed, YDir + 1
// ii. Clear old ball
// D. Check if passes paddle
// i. Change score
// ii. Play sound
// iii. Draw ball in center of board
// iv. Clear old ball
// v. YDir = 0, XDir = -XDir

int GetLEDRowValue(byte ledRow, byte maxColumn){


// The starting column to create
int minColumn = maxColumn - 4;

// Stores the base 10 value representing the binary


// value which defines what lights to turn on
int ledValue = 0;

// Multiplies values by 16, 8, 4, 2, 1


int multiplier = 1;

// Cycle through binary values while multiplying


// to create the base 10 value
for(int i = maxColumn; i >= minColumn; i--){
ledValue += (gameBoard[ledRow][i] * multiplier);
multiplier *= 2;
}
return ledValue;
}

// Generate the 8 values that make up the character to draw


void GenerateBallArray(){

// The max column to use when forming the character using


// data in the gameBoard array
byte maxCol = ((ballY / 5) * 5) + 4;
byte minCol = maxCol - 4;

// 0 for top LCD row and 8 for bottom


byte startRow = (ballX <= 7) ? 0 : 8;

// Get last row value


byte endRow = startRow + 8;

// Get values in gameBoard and create new array with


// just the balls character array
if(startRow == 0){
for(int i = startRow; i < endRow; i++){
ballCharArray[i] = GetLEDRowValue(i, maxCol);
}
} else {
for(int i = startRow; i < endRow; i++){
ballCharArray[i-8] = GetLEDRowValue(i, maxCol);
}
}
}

byte charNum = 0;

void PrintBall(){

// Calculate the column we will draw in


byte LCDCol = ballY / 5;

// Either the top or bottom row


byte LCDRow = (ballX <= 7) ? 0 : 1;

// Character number to associate with the character


charNum = ballY / 5;
/*
for(int i = 0; i < 8; i++){
Serial.print(ballCharArray[i]);
Serial.print(" ");
}
Serial.println("\n");
*/
// Assign array to the charNum
lcd.createChar(charNum, ballCharArray);

// Move the cursor into position


lcd.setCursor(LCDCol,LCDRow);
/*
Serial.print("charNum ");
Serial.println(charNum);
Serial.print("Printing to Column ");
Serial.println(LCDCol);
Serial.print("Printing to Row ");
Serial.println(LCDRow);
*/

// Draw the character


lcd.write(byte(charNum));
}

// Start at X: 7 Y: 35
void SetupBall(){
// Send ball in opposite direction
ballYDir *= -1;

// Put ball on the gameboard


gameBoard[7][35] = true;
}

void AwardAPoint(){
if(ballY <= 8){
playerScore++;
} else {
aiScore++;
}
delay(100);

// Send ball toward other player


ballYDir *= -1;
}

void UpdateBall(){

// Short wait before update


delay(ballUpdateTime);
if((ballY <= 8) || (ballY >= 71)){
AwardAPoint();
} else if((ballX == 0) || (ballX == 15)){
// Hit top or bottom of screen and change Y Direction
ballXDir *= -1;
} else if((ballY == 69) && (ballX == myPaddlePos)){
// If hit players paddle in middle
Serial.println("MIDDLE\n");
ballYDir *= -1;
} else if((ballY == 69) && (ballX == (myPaddlePos + 1))){
// If hit players paddle on bottom
Serial.println("BOTTOM\n");
ballYDir *= -1;
ballXDir = 1;
} else if((ballY == 69) && (ballX == (myPaddlePos - 1))){
// If hit players paddle on top
Serial.println("TOP\n");
ballYDir *= -1;
ballXDir = -1;
}

// Delete last ball position and add new 1 to the gameboard


gameBoard[ballX][ballY] = false;

// Increase ball direction based on direction set on X & Y


ballX += ballXDir;
ballY += ballYDir;

// Set new position as true


gameBoard[ballX][ballY] = true;

// Create the array for the ball character


GenerateBallArray();
// Clears whole LCD
lcd.clear();

PrintBall();
}

void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
SetupBall();
GenerateBallArray();
PrintBall();
}

void loop() {
UpdateBall();
}
Final Game Code
I have tried to bring the best out of me by making this code, Still there is
some Synchronisation issue which I was unable to resolve at my level.
Someone Copied my code from tinkercard, Thus I request you not to
disqualify me if found same code somewhere.
Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte gameBoard[16][80] = {};


int ballUpdateTime = 200;
byte ballXDir = 0;
byte ballYDir = -1;
byte ballX = 7;
byte ballY = 35;
byte ballCharArray[8] = {};
byte playerScore = 0;
byte aiScore = 0;
byte aiPaddlePos = 6;
byte myPaddlePos = 6;

byte aiPaddleArray[2][8] = {0,0,0,0,0,1,1,1};


byte myPaddleArray[2][8] = {0,0,0,0,0,16,16,16};
byte aiPaddleColArray[16] = {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0};
byte myPaddleColArray[16] = {0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0};
const int moveRightButton = 8;
const int moveLeftButton = 7;
int rightButState = 0;
int leftButState = 0;
int rightLastButState = 0;
int leftLastButState = 0;

void ClearPaddles(){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 8; j++){
aiPaddleArray[i][j] = 0;
myPaddleArray[i][j] = 0;
}
}
}

void PrintStuff(){
lcd.clear();

byte* mPTemp1 = myPaddleArray[0];


byte* mPTemp2 = myPaddleArray[1];
byte* aiPTemp1 = aiPaddleArray[0];
byte* aiPTemp2 = aiPaddleArray[1];
lcd.createChar(0, mPTemp1);
lcd.createChar(1, mPTemp2);
lcd.createChar(14, aiPTemp1);
lcd.createChar(15, aiPTemp2);
lcd.setCursor(14, 0);
lcd.write(byte(0));
lcd.setCursor(14, 1);
lcd.write(byte(1));
lcd.setCursor(1, 0);
lcd.write(byte(14));
lcd.setCursor(1, 1);
lcd.write(byte(15));

byte charNum = 0;

if((ballY > 9) && (ballY < 70)){


byte LCDCol = ballY / 5;
byte LCDRow = (ballX <= 7) ? 0 : 1;
charNum = ballY / 5;
lcd.createChar(charNum, ballCharArray);
lcd.setCursor(LCDCol,LCDRow);
lcd.write(byte(charNum));
}
}

void PrintPaddles(){
byte* mPTemp1 = myPaddleArray[0];
byte* mPTemp2 = myPaddleArray[1];
byte* aiPTemp1 = aiPaddleArray[0];
byte* aiPTemp2 = aiPaddleArray[1];
lcd.createChar(0, mPTemp1);
lcd.createChar(1, mPTemp2);
lcd.createChar(14, aiPTemp1);
lcd.createChar(15, aiPTemp2);
lcd.setCursor(14, 0);
lcd.write(byte(0));
lcd.setCursor(14, 1);
lcd.write(byte(1));
lcd.setCursor(1, 0);
lcd.write(byte(14));
lcd.setCursor(1, 1);
lcd.write(byte(15));
}

void SetupPaddles(){
ClearPaddles();
myPaddleArray[0][5] = 16;
myPaddleArray[0][6] = 16;
myPaddleArray[0][7] = 16;
aiPaddleArray[0][5] = 1;
aiPaddleArray[0][6] = 1;
aiPaddleArray[0][7] = 1;
PrintPaddles();
}

void MovePaddleUp(){
if(myPaddlePos != 1){
myPaddlePos--;
aiPaddlePos--;
UpdatePaddlesAfterMove();
}
}

void MovePaddleDown(){
if(myPaddlePos != 14){
myPaddlePos++;
aiPaddlePos++;
UpdatePaddlesAfterMove();
}
}

void UpdatePaddlesAfterMove(){
for(int i = 0; i < 16; i++){
if((i == (myPaddlePos-1)) || (i == myPaddlePos) || (i ==
(myPaddlePos+1))){
myPaddleColArray[i] = 16;
aiPaddleColArray[i] = 1;
} else {
myPaddleColArray[i] = 0;
aiPaddleColArray[i] = 0;
}
}
for(int j = 0; j < 8; j++){
myPaddleArray[0][j] = myPaddleColArray[j];
aiPaddleArray[0][j] = aiPaddleColArray[j];
}
for(int k = 8; k < 16; k++){
myPaddleArray[1][k-8] = myPaddleColArray[k];
aiPaddleArray[1][k-8] = aiPaddleColArray[k];
}
}

int GetLEDRowValue(byte ledRow, byte maxColumn){


int minColumn = maxColumn - 4;
int ledValue = 0;
int multiplier = 1;
for(int i = maxColumn; i >= minColumn; i--){
ledValue += (gameBoard[ledRow][i] * multiplier);
multiplier *= 2;
}
return ledValue;
}

void GenerateBallArray(){

byte maxCol = ((ballY / 5) * 5) + 4;


byte minCol = maxCol - 4;
byte startRow = (ballX <= 7) ? 0 : 8;
byte endRow = startRow + 8;
if(startRow == 0){
for(int i = startRow; i < endRow; i++){
ballCharArray[i] = GetLEDRowValue(i, maxCol);
}
} else {
for(int i = startRow; i < endRow; i++){
ballCharArray[i-8] = GetLEDRowValue(i, maxCol);
}
}
}

void SetupBall(){
ballYDir *= -1;
gameBoard[7][35] = true;
}

void AwardAPoint(){
if(ballY <= 8){
playerScore++;
} else {
aiScore++;
}
delay(100);
ballYDir *= -1;
}

void UpdateBall(){
delay(ballUpdateTime);
if((ballY <= 8) || (ballY >= 71)){
AwardAPoint();
} else if((ballX == 0) || (ballX == 15)){
ballXDir *= -1;
} else if((ballY == 69) && (ballX == myPaddlePos)){
ballYDir *= -1;
} else if((ballY == 69) && (ballX == (myPaddlePos + 1))){
ballYDir *= -1;
ballXDir = 1;
} else if((ballY == 69) && (ballX == (myPaddlePos - 1))){
ballYDir *= -1;
ballXDir = -1;
}
gameBoard[ballX][ballY] = false;
ballX += ballXDir;
ballY += ballYDir;
gameBoard[ballX][ballY] = true;
GenerateBallArray();
PrintStuff();
}

void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
pinMode(moveRightButton, INPUT);
pinMode(moveLeftButton, INPUT);
lcd.print("Game Loading..");
delay(1500);
lcd.clear();
SetupBall();
GenerateBallArray();
SetupPaddles();
PrintStuff();
}

void loop() {
UpdateBall();

rightButState = digitalRead(moveRightButton);
leftButState = digitalRead(moveLeftButton);
if(rightButState != rightLastButState){
if(rightButState == HIGH){
MovePaddleUp();
PrintStuff();
}
delay(50);
rightLastButState = rightButState;
}
if(leftButState != leftLastButState){
if(leftButState == HIGH){
MovePaddleDown();
PrintStuff();
}
delay(50);
leftLastButState = leftButState;
}

Certificate
I hereby Certify that the above work Is my own and is not copied.

You might also like