Gaming is good way to learn coding. It makes learning an easy and fun path to learn, Arduino coding is no exception. That’s why we learn Arduino through making cool games.
Arduino UNO From Banggood 👇👇👇👇
https://www.banggood.in/custlink/vvDHa0trIB
This post is about the famous game the ping pong you can start making it on Arduino and 16×2 LCD and here is a simple simulation on Tinkercad.
First, we see the circuit components:
Circuit Connections:
Arduino UNO is connected to 16×2 LCD through four pins of data enable pin and register select connected to 11 and 12 read write contrast v node connected to ground vcc and ground of LCD connected to vcc and ground of Arduino the backlight led connected to positive and the negative terminal of backlight led connected to ground through one kilo ohm resistor and here are four push buttons used to control the game pull down to the ground through one kilo ohm resistor
Arduino UNO From Banggood 👇👇👇👇
https://www.banggood.in/custlink/vvDHa0trIB
Arduino Code:
We start by including the lcd library then defining the lcd pins then the push button pins and define the variables here is the class of the function of the pedal that used to control the function of the pedals.
Arduino UNO From Banggood 👇👇👇👇
https://www.banggood.in/custlink/vvDHa0trIB
\
#include <LiquidCrystal.h>
#include <avr/interrupt.h>
//----------------------------------------MACROS------------------------------------------
// Assigning LCD PINS
#define RS 12
#define EN 11
#define D4 6
#define D5 7
#define D6 8
#define D7 9
// Buttons that move the paddle
#define Player_1_moveDownButton 10 // Player 1's Down Button is connected to digital pin 4
#define Player_1_moveUpButton 5 // Player 1's Down Button is connected to digital pin 4
#define Player_2_moveDownButton 2 // Player 2's Down Button is connected to digital pin 4
#define Player_2_moveUpButton 3 // Player 2's Down Button is connected to digital pin 4
// Assigning Player Numbers
#define Player_1 1
#define Player_2 2
// Delay for updating the ball
#define DiagonalballUpdateTime 21
#define HorizontalballUpdateTime 15
//Starting Position of the Ball
#define Start_X 35
#define Start_Y 7
#define Button_Pressed (p1_UpButState | p1_DownButState | p2_UpButState | p2_DownButState)
void(* resetFunc) (void) = 0; //declaring reset function at address 0
// Global Variables for Pin Change Interrupt Service Routine
volatile boolean x_Up = true;
volatile boolean x_Down = true;
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7); // Creating Object of type Liquid Crystal
//------------------------------------PADDLE CLASS------------------------------------------
class Paddle
{
public:
// Storing Value of each row of the Character Column for the Player's Paddle
uint8_t PaddleColArray[16] = {0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0};
uint8_t PaddlePos = 6; // Recording Paddles's middle position as reference to move it
uint8_t Score = 0; // Score of each Player
// When the Player presses the "UP" Button
void MovePaddleUp()
{
// Make sure the paddle doesn't go off the board
if(PaddlePos != 1)
{
PaddlePos--;
PaddleColArray[PaddlePos+2]=0;
PaddleColArray[PaddlePos-1]=4;
}
}
// When the Player presses the "DOWN" Button
void MovePaddleDown()
{
if(PaddlePos != 14)
{
PaddlePos++;
PaddleColArray[PaddlePos-2]=0;
PaddleColArray[PaddlePos+1]=4;
}
}
// Printing Paddles using each Player's Number
void PrintPaddles(uint8_t Player_Num)
{
if(Player_Num == 2)
{
// Each character must have a unique character ID and array to print
lcd.createChar(0, PaddleColArray);
lcd.createChar(1, PaddleColArray+8);
// Move cursor to 15th character on the 1st row
lcd.setCursor(14, 0);
lcd.write(byte(0));
// Move cursor to 15th character on the 1st row
lcd.setCursor(14, 1);
lcd.write(byte(1));
}
//if(Player_Num == 1)
else
{
lcd.createChar(2, PaddleColArray);
lcd.createChar(3, PaddleColArray+8);
lcd.setCursor(1, 0);
lcd.write(byte(2));
lcd.setCursor(1, 1);
lcd.write(byte(3));
}
}
};
// Creating Objects of Class "Paddle"
Paddle p1, p2;
//------------------------------------PRINT_GAME CLASS------------------------------------------
class Print_Game
{
public:
// Printing texts when the game starts
void Start_Game()
{
lcd.print(F(" PING PONG "));
//Set the Cursor at the starting of 2nd row
lcd.setCursor(0, 1);
lcd.print(F("PRESS A BUTTON"));
// Variables to record the state of Push-Buttons
uint8_t p1_UpButState = 0;
uint8_t p1_DownButState = 0;
uint8_t p2_UpButState = 0;
uint8_t p2_DownButState = 0;
// Waiting till any one of the button is pressed
while(!(Button_Pressed))
{
// Low Level Code for digitalread() function for each input pin
p1_UpButState = ((PIND & (1 << Player_1_moveUpButton)) );
p1_DownButState = ((PINB & (1 << (Player_1_moveDownButton-8))) );
p2_UpButState = ((PIND & (1 << Player_2_moveUpButton)) );
p2_DownButState = ((PIND & (1 << Player_2_moveDownButton)) );
}
lcd.clear(); //Clearing LCD to start the game
}
// Printing score each time a player scores
void Print_Score()
{
// Clearing the LCD to print scores
lcd.clear();
lcd.print(F("PLAYER1 PLAYER2"));
lcd.setCursor(3 ,1);
lcd.print(p1.Score);
lcd.setCursor(12 ,1);
lcd.print(p2.Score);
// Scores remain on the display for 2 seconds
delay(2000);
// Clearing the display to continue the game
lcd.clear();
}
// Printing the Winner on Display
void Print_Winner(int Player_Num)
{
lcd.setCursor(0 ,0);
lcd.print(F(" GAME OVER "));
lcd.setCursor(1, 1);
lcd.print(F("PLAYER "));
lcd.print(Player_Num);
lcd.setCursor(11 ,1);
lcd.print(F("WINS"));
// Text remains on screen for 5 seconds
delay(5000);
// Resetting the Game
resetFunc();
}
};
// Creating an Object of Print_Game Class
Print_Game g;
//------------------------------------BALL CLASS------------------------------------------
class Ball
{
private:
// Flag to reset the ball and paddles when a point is scored
uint8_t Point_Scored = 0;
// X and Y Direction Components of the Ball
uint8_t ballYDir = 0; // Ball starts off going horizontal
uint8_t ballXDir = -1; // Call starts off going left
// Location of the Ball
uint8_t ballY = Start_Y;
uint8_t ballX = Start_X;
// Row values of Character of the LCD in which the Ball is present
uint8_t ballCharArray[8] = {0, 0, 0, 0, 0, 0, 0, 16};
public:
// Declaring member fucntions defined outside of class
void GenerateBallArray();
void PrintBall();
void UpdateBall(uint8_t , uint8_t);
void AwardAPoint();
};
//----------------------------Member Fuctions of Class BALL---------------------------------
// Generate the 8 values that make up the character to draw
void Ball :: GenerateBallArray()
{
for(uint8_t i=0; i<8; i++)
{
if(i == (ballY % 8))
{
ballCharArray[i] = 2 << (4 - (ballX % 5));
}
else
{
ballCharArray[i] = 0;
}
}
}
void Ball :: PrintBall()
{
// Calculate the column we will draw in
uint8_t LCDCol = ballX / 5;
// Either the top or bottom row
uint8_t LCDRow = (ballY <= 7) ? 0 : 1;
// Assign array to the charNum
lcd.createChar(4, ballCharArray);
// Move the cursor into position
lcd.setCursor(LCDCol,LCDRow);
// Draw the character
lcd.write(byte(4));
}
// Updating the Ball's Position
void Ball :: UpdateBall(uint8_t P1_PaddlePos, uint8_t P2_PaddlePos)
{
// Short wait before update
// Handling different delays so that
// ball has same speed when it's going diagonally
if(ballYDir) // When it's going Diagonally
{
delay(DiagonalballUpdateTime);
}
else // When it's going Horizontally
{
delay(HorizontalballUpdateTime);
}
//-------------CALCULATING BALL'S NEXT POSITION------------
//If the Ball goes off-board
if((ballX <= 6) || (ballX >= 73))
{
AwardAPoint();
}
//If Ball is at the Player 2 edge
else if(ballX == 72)
{
// IF THE BALL STRIKES THE MIDDLE POSITION OF THE PADDLE
if(ballY == P2_PaddlePos)
{
ballXDir = -1;
}
// IF THE BALL STRIKES THE BOTTOM POSITION OF THE PADDLE
else if(ballY == (P2_PaddlePos + 1))
{
ballXDir = -1;
if(ballY == 15) // If the ball strikes the paddle at the bottom corner of the display
{
ballYDir = -1;
}
else
{
ballYDir = 1;
}
}
// IF THE BALL STRIKES THE TOP POSITION OF THE PADDLE
else if(ballY == (P2_PaddlePos - 1)){
ballXDir = -1;
if(ballY == 0) // If the ball strikes the paddle at the upper corner of the display
{
ballYDir = 1;
}
else
{
ballYDir = -1;
}
}
}
//If Ball is at the Player 1 edge
else if(ballX == 7)
{
// IF THE BALL STRIKES THE MIDDLE POSITION OF THE PADDLE
if(ballY == P1_PaddlePos)
{
ballXDir = 1;
}
// IF THE BALL STRIKES THE BOTTOM POSITION OF THE PADDLE
else if(ballY == (P1_PaddlePos + 1)){
ballXDir = 1;
if(ballY == 15) // If the ball strikes the paddle at the bottom corner of the
{
ballYDir = -1;
}
else
{
ballYDir = 1;
}
}
// IF THE BALL STRIKES THE TOP POSITION OF THE PADDLE
else if(ballY == (P1_PaddlePos - 1))
{
ballXDir = 1;
if(ballY == 0) // If the ball strikes the paddle at the upper corner of the display
{
ballYDir = 1;
}
else
{
ballYDir = -1;
}
}
}
// If the Ball Hit top or bottom of display then change Y Direction
else if((ballY == 0) || (ballY == 15))
{
ballYDir *= -1;
}
//Resetting the Ball and Paddles IF a point is scored
if(Point_Scored == 1)
{
// Resetting the Ball
ballX = Start_X;
ballY = Start_Y;
ballXDir *= -1;
ballYDir = 0;
// Resetting the Paddles
p1.PaddlePos = 6;
p2.PaddlePos = 6;
for(uint8_t i=0; i<16; i++)
{
if((i==5) || (i==6) || (i==7))
{
p1.PaddleColArray[i] = 4;
p2.PaddleColArray[i] = 4;
}
else
{
p1.PaddleColArray[i] = 0;
p2.PaddleColArray[i] = 0;
}
}
Point_Scored = 0; //Resetting the Point_Scored Flag
}
// Delete Ball from it's Current Location
uint8_t LCDCol = ballX / 5;
uint8_t LCDRow = (ballY <= 7) ? 0 : 1;
lcd.setCursor(LCDCol, LCDRow);
lcd.print(" ");
// Change ball's position based on direction set on X & Y
ballX += ballXDir;
ballY += ballYDir;
// Create the array for the ball character
GenerateBallArray();
// Printing ball after calculating the new location
PrintBall();
}
// Increase player's score each time one scores
void Ball :: AwardAPoint()
{
if(ballX <= 8) // When Player 2 Scores
{
p2.Score++;
}
else // When Player 2 Scores
{
p1.Score++;
}
// When one of the player reaches the winning score of 10
if(p1.Score == 10) // If Player 1 reaches 10 first
{
g.Print_Winner(Player_1); // Printing Player 1 as Winner
}
else if(p2.Score == 10) // If Player 2 reaches 10 first
{
g.Print_Winner(Player_2); // Printing Player 2 as Winner
}
// Printing the Score of both players
g.Print_Score();
Point_Scored = 1; // Setting the Flag to reset the locations of Paddles and Ball
}
// Creating an Object of class BALL
Ball b;
//---------------------------------------SETUP---------------------------------------------
void setup()
{
// The display has 2 rows with 16 characters per row
lcd.begin(16, 2);
// Setup buttons so we can receive input
DDRD &= ~(1<<Player_1_moveUpButton);
// Low level version of the statement: pinMode( Player_1_moveUpButton, INPUT);
// Similarly, setting all other pins to input
DDRD &= ~(1<<Player_1_moveDownButton);
DDRD &= ~(1<<Player_2_moveUpButton);
DDRD &= ~(1<<Player_2_moveDownButton);
// Printing the first statement
g.Start_Game();
// Print paddles on LCD
p1.PrintPaddles(Player_1);
p2.PrintPaddles(Player_2);
// Print Ball on LCD
b.PrintBall();
// Enabling Pin Change Interrup for Player 1's "UP" Button
PCMSK2 |= (1 << PCINT21);
PCICR |= (1 << PCIE2);
// Enabling Pin Change Interrup for Player 1's "DOWN" Button
PCMSK0 |= (1 << PCINT2);
PCICR |= (1 << PCIE0);
// Enabling Global interrupts
sei();
//Player 2 will input through Interrupts
attachInterrupt(digitalPinToInterrupt(Player_2_moveDownButton), P2_Move_Down, RISING);
attachInterrupt(digitalPinToInterrupt(Player_2_moveUpButton), P2_Move_Up, RISING);
}
//---------------------------------------LOOP---------------------------------------------
void loop()
{
//Printing Both Paddles
p1.PrintPaddles(Player_1);
p2.PrintPaddles(Player_2);
//Updating Ball's Position
b.UpdateBall(p1.PaddlePos, p2.PaddlePos);
}
//-----INTERRUPT SERVICE ROUTINES----FOR PLAYER 2--------------
void P2_Move_Down()
{
p2.MovePaddleDown();
}
void P2_Move_Up()
{
p2.MovePaddleUp();
}
//----PIN CHANGE INTERRUPT SERVICE ROUTINES----FOR PLAYER 1-----
// Interrupt Routine for Player 1 "UP" Button
ISR(PCINT2_vect)
{
// The if statements make sure that interrupts does something
// only on rising edge of the clock
if(x_Up)
{
p1.MovePaddleUp();
x_Up = false;
}
else
{
x_Up = true;
}
}
// Interrupt Routine for Player 1 "DOWN" Button
ISR(PCINT0_vect)
{
// The if statements make sure that interrupts does something
// only on rising edge of the clock
if(x_Down)
{
p1.MovePaddleDown();
x_Down = false;
}
else
{
x_Down = true;
}
}
Arduino Ping Pong Simulation
Arduino Ping Pong on Tinkercad. Here is the Simulation. You can try it right here.
- My Six Years Old Son Wanted to Build His own Flying CarBuilding My Son’s Dream: A Flying Car with Tinkercad and Arduino Ever since my 6-year-old son could talk, he’s been fascinated by the idea of flying cars. He would sketch designs, build models with his toys, and talk about how one day he would soar above the ground in a car with wings. His dream… Read more: My Six Years Old Son Wanted to Build His own Flying Car
- How I made My Kids #Arduino #Flying Car #Tinkercad Dream #Aviation #AeroArduinoIntroduction: Welcome to a new project from AeroArduino, where we turn dreams into reality! In this exciting project, we’re bringing to life a childhood dream of creating an Arduino flying car using TinkerCAD. If you haven’t subscribed yet, be sure to hit that subscribe button to stay updated with our latest projects. Circuit Connection: Let’s… Read more: How I made My Kids #Arduino #Flying Car #Tinkercad Dream #Aviation #AeroArduino
- Easy #Tinkercad #Arduino distance measurement using ultrasonic sensor #AeroArduino
- Building a Smart Ultrasonic Car With Code Blocks on TinkercadToday, I want to share an exciting project that brings together ultrasonic sensors, motors, and a sprinkle of programming magic to create a Smart Ultrasonic Car. Imagine a little robotic vehicle that can sense its surroundings and make decisions on the fly – that’s exactly what we’re diving into! The Heart of the Project: Ultrasonic… Read more: Building a Smart Ultrasonic Car With Code Blocks on Tinkercad
- Super Simulation for Accelerometer with Arduino in TinkercadIntroduction The world of electronics education often relies on simulation software to bridge theoretical knowledge and practical application. TinkerCAD stands as a prominent platform for simulating electronic components, aiding enthusiasts and learners in experimenting virtually. In this tutorial, we’ll explore how to overcome the absence of an accelerometer component in TinkerCAD by using a creative… Read more: Super Simulation for Accelerometer with Arduino in Tinkercad
- Monitoring Soil Moisture with Arduino and LCD: A Step-by-Step GuideHow to Build Step-by-Step Arduino Soil Moisture Sensor With Tinkercad Simulation – DIY Guide on AeroArduino
- Revolutionizing Aircraft Ground Handling: The Advantages of Remotely Controlled TugsIntroduction: The aviation industry has witnessed minimal innovation in aircraft tugs, resulting in outdated and inefficient ground handling operations. However, the advent of remotely controlled aircraft tugs has the potential to transform ground handling practices. These advanced tugs offer numerous advantages over traditional counterparts, including increased efficiency, improved safety, and reduced environmental impact. In this… Read more: Revolutionizing Aircraft Ground Handling: The Advantages of Remotely Controlled Tugs
- The Mighty Antonov AN-22: Revolutionizing Cargo Transportation in the SkiesIntroduction: In the realm of aviation, where technological advancements continually push boundaries, the Antonov AN-22 shines as a true marvel. With its massive size and unparalleled cargo-carrying capabilities, this iconic propeller aircraft has carved its name in the annals of aviation history. Join us as we delve into the world of the Antonov AN-22 and… Read more: The Mighty Antonov AN-22: Revolutionizing Cargo Transportation in the Skies