Mirko Pavleski
Published © GPL3+

DIY addictive Arduino 1D Pong game

This is an interesting one-dimensional compact version of the classic "Pong" game made with a minimal number of components

BeginnerFull instructions provided3 hours502
DIY addictive Arduino 1D Pong game

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
I2C 16x2 Arduino LCD Display Module
DFRobot I2C 16x2 Arduino LCD Display Module
×1
Buzzer
Buzzer
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×2
LED (generic)
LED (generic)
×10
Through Hole Resistor, 470 ohm
Through Hole Resistor, 470 ohm
×1
Resistor 10k ohm
Resistor 10k ohm
×2

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Schematic

...

Code

Code

C/C++
...
//#include <LiquidCrystal.h>

#include <Wire.h>

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);


bool willTheBallGoTowardsPlayerTwo = true;
bool isInputAllowed = true;

const int playerOne = 12;
const int goalPlayerOne = 13;
const int buttonPlayerOne = 3;

const int playerTwo = 5;
const int goalPlayerTwo = 4;
const int buttonPlayerTwo = 2;

int scoreOfPlayerOne = 0;
int scoreOfPlayerTwo = 0;

const unsigned long initialMillisecondsPerLED = 400;
const unsigned long initialDeltaMillisecondsPerLED = 50;
unsigned long millisecondsPerLED = initialMillisecondsPerLED;
unsigned long deltaMillisecondsPerLED = initialDeltaMillisecondsPerLED;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

int currentPosition = playerOne;        //Player one starts the game.
int previousPosition = playerOne + 1;
int deltaPosition = 0;

int buttonStatePlayerOne = 0;
int lastButtonStatePlayerOne = 0;
int buttonStatePlayerTwo = 0;
int lastButtonStatePlayerTwo = 0;

void setup() {

 
 lcd.backlight();
 lcd.begin(16,2);
  lcd.clear();
  lcd.setCursor(2, 0); 
  lcd.print("1D-Pong Game");
  lcd.setCursor(3, 1); 
  lcd.print("by mircemk");
  delay(2000.);
 
 lcd.clear(); 
 lcd.setCursor(0, 0);
 lcd.print("Player One: 0");
 lcd.setCursor(0, 1);
 lcd.print("Player Two: 0");
 


  pinMode(4, 1);
  pinMode(5, 1);
  pinMode(6, 1);
  pinMode(7, 1);
  pinMode(8, 1);
  pinMode(9, 1);
  pinMode(10, 1);
  pinMode(11, 1);
  pinMode(12, 1);
  pinMode(13, 1);
  /*Connect pins 4 to 13 to 220ohm resistors, connect the LEDs' longer legs(+) to the resistors,
    connect the other legs(-) of the LEDs' to ground.
    I recommend red LEDs for 4 and 13(Goals), yellow LEDs for 5 and 12(Players), green LEDs for other pins(Field).
  */

  pinMode(2, 0);    //Pushbuttons for players. Pin 2 is for player two. Pin 3 is for player one.
  pinMode(3, 0);    //Connect pushbuttons following the instructions on this page: https://www.arduino.cc/en/Tutorial/DigitalReadSerial
}

void loop()
{
  ListenForInput();
  currentMillis = millis();
  if (currentMillis - previousMillis >= millisecondsPerLED)  //If you don't understand this, see: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
  {
    CheckGoalConditions();
    lcd.clear();
    lcd.setCursor(0, 0);  //(Column,Row)
    lcd.print("Player One: ");
    lcd.setCursor(12, 0); 
    lcd.print(scoreOfPlayerOne);

    lcd.setCursor(0, 1);  //(Column,Row)
    lcd.print("Player Two: ");
    lcd.setCursor(12, 1); 
    lcd.print(scoreOfPlayerTwo);
    CheckEndGame();
    DetermineNextPosition();
    MoveBallToNextPosition();

    previousMillis = currentMillis;

  }
}

void ListenForInput()    //If you don't understand this method. See: https://www.arduino.cc/en/Tutorial/StateChangeDetection
{
  buttonStatePlayerOne = digitalRead(buttonPlayerOne);
  buttonStatePlayerTwo = digitalRead(buttonPlayerTwo);

  if (buttonStatePlayerOne != lastButtonStatePlayerOne && isInputAllowed)
  {
    if (buttonStatePlayerOne == 1)
    {
      if (currentPosition == playerOne)
      {
        ToggleBallDirection();
        IncreaseSpeed();
        
      }
      else
      {
        ScoreForPlayer(2);
        
      }
    }
    lastButtonStatePlayerOne = buttonStatePlayerOne;
  }
  if (buttonStatePlayerTwo != lastButtonStatePlayerTwo && isInputAllowed)
  {
    if (buttonStatePlayerTwo == 1)
    {
      if (currentPosition == playerTwo)
      {
        ToggleBallDirection();
        IncreaseSpeed();
        
      }
      else
      {
        ScoreForPlayer(1);
        
      }
    }
    lastButtonStatePlayerTwo = buttonStatePlayerTwo;
  }
}

void ToggleBallDirection()
{
  willTheBallGoTowardsPlayerTwo = !willTheBallGoTowardsPlayerTwo;
  isInputAllowed = false;   //Only one direction change per frame is allowed for consistent gameplay.
}

void IncreaseSpeed()
{
  millisecondsPerLED -= deltaMillisecondsPerLED;
  if (deltaMillisecondsPerLED > 50)  //Because of this, it takes a little more time to reach to an insane speed. Adjust or remove this if rounds become too long.
  {
    deltaMillisecondsPerLED -= 50; 
  }
}

void MoveBallToNextPosition()      //Moves the ball one spot.
{
  previousPosition = currentPosition;
  digitalWrite(previousPosition, 0);
  currentPosition = currentPosition + deltaPosition;
  digitalWrite(currentPosition, 1);
  tone(1, 500, 50);
  isInputAllowed = true;
}

void DetermineNextPosition()
{
  if (willTheBallGoTowardsPlayerTwo)
  {
    deltaPosition = -1;
  }
  else
  {
    deltaPosition = 1;
  }
}

void CheckGoalConditions()
{
  if (currentPosition == goalPlayerTwo)
  {
    ScoreForPlayer(1);    
  }
  else if (currentPosition == goalPlayerOne)
  {
    ScoreForPlayer(2);
  }
}

void ScoreForPlayer(int playerWhoScored)
{
  isInputAllowed = false;
  FlashAllLEDs(1, 0);
  if (playerWhoScored == 1)
  {
    scoreOfPlayerOne++;
    
    Reset(1);
      }
  else if (playerWhoScored == 2)
  {
    scoreOfPlayerTwo++;
    
    Reset(2);
  }
  
}

void CheckEndGame()
{
  if (scoreOfPlayerOne == 10)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Player One Win");
    EndGameCeremonyFor(1);
    
  }
  if (scoreOfPlayerTwo == 10)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Player Two Win");
    EndGameCeremonyFor(2);
    
  }
}

void Reset(int playerCurrentlyScored)
{
  if (playerCurrentlyScored == 1)
  {
    digitalWrite(playerOne, 1);
    currentPosition = playerOne;
    willTheBallGoTowardsPlayerTwo = true;
    tone(1, 200 ,150 );
  }
  else if (playerCurrentlyScored == 2)
  {
    digitalWrite(playerTwo, 1);
    currentPosition = playerTwo;
    willTheBallGoTowardsPlayerTwo = false;
      tone(1, 300 ,150 );
      
  }

  delay(1000);                //Are three seconds enough for players to process the score?  
  millisecondsPerLED = initialMillisecondsPerLED;            //Sets speed to initial value at the beginning of each round.
  deltaMillisecondsPerLED = initialDeltaMillisecondsPerLED; 
}


void EndGameCeremonyFor(int winner)
{
  FlashAllLEDs(50, winner);
  TurnOffAllLEDsForPlayer(0);
  scoreOfPlayerOne = 0;
  scoreOfPlayerTwo = 0;
  delay(1000);
   lcd.clear();
    lcd.setCursor(4, 0);
    lcd.print("Starting");
     lcd.setCursor(4,1);
    lcd.print("New Game");
    delay(2000);
}

void TurnOnAllLEDsForPlayer(int player)
{
  if (player != 1)          //When this method is called with (2), only these pins(player two's) will turn on
  {
    digitalWrite(4, 1);
    digitalWrite(5, 1);
    digitalWrite(6, 1);
    digitalWrite(7, 1);
    digitalWrite(8, 1);
    tone(1, 1000, 35);
  }
  if (player != 2)          //When this method is called with (1), only these pins(player one's) will turn on
  {
    digitalWrite(9, 1);
    digitalWrite(10, 1);
    digitalWrite(11, 1);
    digitalWrite(12, 1);
    digitalWrite(13, 1);
    tone(1, 1000, 35);
  }
}

void TurnOffAllLEDsForPlayer(int player)
{
  if (player != 1)          //When this method is called with (2), only these pins(player two's) will turn off
  {
    digitalWrite(4, 0);
    digitalWrite(5, 0);
    digitalWrite(6, 0);
    digitalWrite(7, 0);
    digitalWrite(8, 0);
  }
  if (player != 2)          //When this method is called with (1), only these pins(player one's) will turn off
  {
    digitalWrite(9, 0);
    digitalWrite(10, 0);
    digitalWrite(11, 0);
    digitalWrite(12, 0);
    digitalWrite(13, 0);
  }
}

void FlashAllLEDs(int blinkCount, int player) //Second parameter(int player) is for when you want to flash only one player's LEDs. Use 1 for player one, use 2 for player two. 
{
  for (int i = 0; i < blinkCount; i++)
  {
    TurnOnAllLEDsForPlayer(player);
    delay(35);
    TurnOffAllLEDsForPlayer(player);
    delay(35);
  }
}

Credits

Mirko Pavleski
173 projects • 1398 followers
Contact

Comments

Please log in or sign up to comment.