2 Player Pong Using Arduino

42,460

62

39

Posted

Introduction: 2 Player Pong Using Arduino

I started with the Instructable from Kyle Brinckerhoff;

https://www.instructables.com/id/Ardu-pong-the-Arduino-based-pong-console/

 
Thanks Kyle!

and the following at Make magazine
http://blog.makezine.com/archive/2007/08/arduino-pong.html

and I see the original code is attributed to Pete Lamonica

Thanks Pete!!

I am using the paddles instead of the joy stick and I have made it for 2 players. Also I added some sound.

I put the electronics in an Iphone box .

Step 1: Video of the Game

 

Step 2: What I Used

I used the following:

Iphone box
Arduino - I had a Freeduino from Solarbotics that I used.   The picture shows another but I am sure others would work fine.
Atari paddles - I had from an old system being stored in the basement.  I see them on eBay.
An old RCA cord that was in my big box of misc cords
A 9 pin D connector that I got at Radio Shack - pn 276-1538
Also (not shown)
RCA plugs for the cable to attach to - had in my pile of broken things
resistors
75 ohm
 1Kohm 
330 ohm 
2 10k ohm pull down resistors


Some misc hardware - wire, screws,small pieces of wood

Step 3: Prepare the Box


I started with a small piece of wood which I cut to fit inside the box.   The idea was I would secure everything to this piece and then secure the box to the wood.   Holes need to be cut to fit the RCA plugs, the 9 pin connector, and for a USB cable which is needed to attach to Arduino .

I glued another small piece of wood to the larger to be used as a place to secure the Arduino. 

Step 4: Electronics Part1 - the RCA Plugs

Following the instructions from Kyle's Instructable, I soldier a 1k ohm and a 330 ohm resistor to the center pin of the video out RCA jack.
I also connected the 75 ohm that is shown in the diagram . It made the picture a little less bright but much clearer and it stopped a lot of the flickering.

The RCA plug for the sound is straight forward: The center plug goes to Arduino pin 11 and the ground side goes to ground.

The bottom part of the diagram is different than what I did.

Step 5: Electronics Part2 - Connections to Arduino

Basically
Analog pin 1 - goes to paddle 1
Analog pin 2 - goes to paddle 2
Ground - used to ground the 9 pin connector, the RCA  connectors
5v goes to the 5 v on the 9 pin connector


Digital pin2 - goes to the button on Paddle 1(button on paddle 2 is not used)
Digital 8 - goes to video RCA
Digital 9 - goes to video RCA
Digital 11 - goes to sound RCA

Step 6: Electronics Part3 - the 9 Pin Connector

Struggled with this but more through trial and error than anything else, I got to the following:

Looking at the pins from the back of the connector:
The top row (left to right)
pin1 - goes to analog 0
pin 2 -  not used
pin 3 - goes to Digital 2 - the button
pin 4 & pin 5 - not used

bottom row(left to right)
pin  6 - goes to analog 1
pin 7 - goes to ground
pin 8 - goes to 5 v
pin 9 - not used

Step 7: The Code

The code I used is in the text file below.


Early testing was done on the Mickey Mouse TV . 


But it works ok on large TV as shown in step 1.


Step 8: Stuff It in Box


After some testing, I placed everything into the Iphone box and secured it.

I also added a switch to turn the battery power on/off.

Step 9: Hook It Up

Connect the RCA cable to the jacks, the Paddles to the 9 pin connector, switch on TV and power to Arduino and play.

2 People Made This Project!

  • :)-robmawe91

    robmawe91 made it!

  • this was a pretty ea...-koz12

    koz12 made it!

Recommendations

  • Epilog Challenge 9

    Epilog Challenge 9
  • Sew Warm Contest 2018

    Sew Warm Contest 2018
  • Gluten Free Challenge

    Gluten Free Challenge
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

37 Comments

Hey awesome work... I would definitely try that out soon

Please have a look at this instructable as well
https://www.instructables.com/id/Led-Cube-3x3x3-1/

Thank you so much! I love the pong game. I have an arduino nano and a arduino uno. I am going to upload the program to both and combine both wiring onto the breadboard so that the tv screen will have better contrast! Keep up the Good work! Have a good day.

I love this project. Everything works great, except when I run the code, it redraws everything every frame. So it looks like the tv is almost strobing. I can't find a way to fix this. I tried adding another resistor but it didn't help the flickering. Any suggestions on a fix?

RE: FLICKERING. BAD REFRESH. PADDLE ANNOYING. BACKGROUND

The flickering occurs when background refreshes the background but paddles are not displayed (thus they dissapear until they are displayed). To fix this, only refresh the screen when you are ready to update the paddle positions:

background(50); //Delete "background" from draw() and paste inside serialEvent

leftPaddle.display(lpp);

rightPaddle.display(rpp);

I made it too, starting from Pete Lamonica code. My video is here:

I have then re-written a complete new color version for VGA output. Video here:

Following the video description, you can find the istuction to reproduce it!

dont you have another diagram?

Nice project, But I had to rewrite the program...

//Arduino Tv framebuffer
//Alastair Parker
//2007

// Video out voltage levels
#define _SYNC 0x00
#define _BLACK 0x01
#define _GRAY 0x02
#define _WHITE 0x03

// dimensions of the screen
#define WIDTH 38
#define HEIGHT 14

//number of lines to display
#define DISPLAY_LINES 240

// update speed for the main loop of the game
#define UPDATE_INTERVAL 1

// positions of the player paddles
#define PLAYER_RIGHT_X 35
#define PLAYER_LEFT_X 2

// maximum velocity of the ball
#define MAX_VEL 10

// locations of the top and bottom virtual bars
#define SCORE_BAR 3
#define BASE_BAR 13

// time to wait while paused
#define DONE_WAITING 30
#define SCORE_WAITING 30

// max player life
#define MAX_LIFE 6

//positions of player life bars
#define PLAYER_LEFT_LIFE 2
#define PLAYER_RIGHT_LIFE 23

// input pins for the player pots
#define PLAYER_LEFT_PIN 2
// currently the same pin
#define PLAYER_RIGHT_PIN 1

//video pins
#define DATA_PIN 9
#define SYNC_PIN 8

// the video frameBuffer
byte frameBuffer[WIDTH][HEIGHT];

// loop indices
byte index, index2;

// pal video line loop
byte line;
// current drawing line in framebuffer
byte newLine;

// flag used in wait loop to indicate that player just scored
boolean justScored=false;

// positions for the left paddle
byte playerLeft;
byte playerLeftOld=-1;
// life for the left player
byte playerLeftLife = MAX_LIFE;

// positions of the right paddle
byte playerRight;
byte playerRightOld=-1;
// life for the right player
byte playerRightLife = MAX_LIFE;

// positions and velocity of the ball
int ballXVel = -1;
int ballYVel = -5;
byte ballXPos = 14;
byte ballYPos = 7;

// loop counters to control the velocity of the ball
byte ballXLoop =MAX_VEL;
byte ballYLoop =MAX_VEL;

// loop counter to for the main loop delay
int waitingCount = 0;

// start postion of the loading bar
byte loadingBar = 2;

// if the left player should be updated or the right
boolean playerLeftTurn=true;

// if we should be waiting for something to happen
boolean waiting=true;
// if displaying the title
boolean showingTitle = true;

// value of the counter controlling the freq of updates
byte updateCounter=0;

// init the variables
void initGame()
{
playerLeftOld=-1;
playerLeftLife = MAX_LIFE;
playerRightOld=-1;
playerRightLife = MAX_LIFE;
ballXVel = -1;
ballYVel = -5;
ballXPos = 14;
ballYPos = 7;
ballXLoop =MAX_VEL;
ballYLoop =MAX_VEL;
waitingCount = 0;
loadingBar = 2;
playerLeftTurn=true;
waiting=true;
showingTitle = true;
justScored=false;
updateCounter=0;
}

// draw a pixel to the buffer
void setPixel(byte x,byte y)
{
frameBuffer[x][y]= _WHITE;
}

void grayPixel(byte x, byte y)
{
frameBuffer[x][y]= _GRAY;
}

// draw a black pixel to the buffer
void clearPixel(byte x,byte y)
{
frameBuffer[x][y]= _BLACK;
}

// draw a paddle
void drawPaddle(byte x,byte y,byte col)
{
frameBuffer[x][y]= col;
frameBuffer[x][y+1]= col;
}


//draw the title message
void drawArduinoPong()
{
//arduino
setPixel(7,3);
setPixel(8,3);
setPixel(15,3);
setPixel(21,3);
setPixel(6,4);
setPixel(8,4);
setPixel(14,4);
setPixel(15,4);
setPixel(28,4);
setPixel(6,5);
setPixel(7,5);
setPixel(8,5);
setPixel(10,5);
setPixel(11,5);
setPixel(13,5);
setPixel(15,5);
setPixel(17,5);
setPixel(19,5);
setPixel(21,5);
setPixel(23,5);
setPixel(24,5);
setPixel(27,5);
setPixel(29,5);
setPixel(6,6);
setPixel(8,6);
setPixel(10,6);
setPixel(14,6);
setPixel(15,6);
setPixel(18,6);
setPixel(19,6);
setPixel(21,6);
setPixel(23,6);
setPixel(25,6);
setPixel(28,6);

//pong
setPixel(10,8);
setPixel(11,8);
setPixel(15,8);
setPixel(16,8);
setPixel(19,8);
setPixel(22,8);
setPixel(24,8);
setPixel(25,8);
setPixel(26,8);
setPixel(10,9);
setPixel(12,9);
setPixel(14,9);
setPixel(17,9);
setPixel(19,9);
setPixel(20,9);
setPixel(22,9);
setPixel(24,9);
setPixel(10,10);
setPixel(11,10);
setPixel(14,10);
setPixel(17,10);
setPixel(19,10);
setPixel(21,10);
setPixel(22,10);
setPixel(24,10);
setPixel(26,10);
setPixel(10,11);
setPixel(15,11);
setPixel(16,11);
setPixel(19,11);
setPixel(22,11);
setPixel(24,11);
setPixel(25,11);
setPixel(26,11);
}
// do the main game logic regarding the ball and collisions
void updateBall(boolean xEvent)
{
// if checking the x coords of the ball
if(xEvent)
{
/*
TODO

have the yvel start 1t 1

*/

//check for collision with left player
if(ballXPos <PLAYER_LEFT_X+2 & (playerLeft == ballYPos or playerLeft+1 == ballYPos))
{
ballXVel = -1 * ballXVel;
ballXPos=PLAYER_LEFT_X+1;
}
//check for collision with right player
if(ballXPos > PLAYER_RIGHT_X-2 & (playerRight == ballYPos or playerRight+1 == ballYPos))
{
ballXVel = -1 * ballXVel;
ballXPos=PLAYER_RIGHT_X-1;
}

//move the ball in the x direction
if(ballXVel < 1)
{
ballXPos--;
}
else
{
ballXPos++;
}
}

//if checking the y coords
if(!xEvent)
{
//check for top of screen hit
if( ballYPos <= SCORE_BAR )
{
ballYVel = -1 * ballYVel;
ballYPos = SCORE_BAR;
}
//check for bottom of screen hit
if( ballYPos>BASE_BAR )
{
ballYVel = -1 * ballYVel;
ballYPos = BASE_BAR+1;
}

// move the ball in the y direction
if(ballYVel < 1)
{
ballYPos--;
}
else
{
ballYPos++;
}
}

//always check for scoring of points

//right player scores
if(ballXPos==PLAYER_LEFT_X)//0
{
//reset the position of the ball
ballXPos = PLAYER_RIGHT_X - 5;
ballYPos=7;

// change the other players life
clearPixel(PLAYER_LEFT_LIFE+2*playerLeftLife-2,SCORE_BAR-1);
playerLeftLife--;

// indicate that someone scored so the wait doesn't start a new game
justScored=true;
// indicate that we should wait next loop
waiting=true;

// check if game is over
if(playerLeftLife==0)
justScored=false;
}

//left player scores
if(ballXPos==PLAYER_RIGHT_X)//38
{
//reset position of ball
ballXPos = PLAYER_LEFT_X + 5;
ballYPos=7;

//update other players score
clearPixel(PLAYER_RIGHT_LIFE+2*(MAX_LIFE-playerRightLife)+2,SCORE_BAR-1);
playerRightLife--;

// indicate that someone scored so the wain doesn't start a new game
justScored=true;
// indicate that we should wait next loop
waiting=true;

// check for game over
if(playerRightLife==0)
justScored=false;
}

}

// draw the player life bars
void initScreen()
{
for(index=1;index<=MAX_LIFE;++index)
{
grayPixel(index*2,SCORE_BAR-1);
grayPixel(index*2+PLAYER_RIGHT_LIFE,SCORE_BAR-1);
}
}


// draw the ball
void drawBall(byte col)
{
frameBuffer[ballXPos][ballYPos]=col;
}

// clear the screen
void clearScreen()
{
for (index = 0; index < WIDTH; index++)
for (index2=0;index2<=HEIGHT;++index2)
{
frameBuffer[index][index2] = _BLACK;
}
}

// the setup routine
void setup()
{
cli();
pinMode (SYNC_PIN, OUTPUT);
pinMode (DATA_PIN, OUTPUT);
digitalWrite (SYNC_PIN, HIGH);
digitalWrite (DATA_PIN, HIGH);
clearScreen();
drawArduinoPong();
}

void loop()
{
// iterate over the lines on the tv
for ( line =0;line< DISPLAY_LINES;++line)
{

// HSync
// front porch (1.5 us)
PORTB = _BLACK;
delayMicroseconds(1.5);
//sync (4.7 us)
PORTB = _SYNC;
delayMicroseconds(4.7);
// breezeway (.6us) + burst (2.5us) + colour back borch (1.6 us)
PORTB = _BLACK;
delayMicroseconds(0.6+2.5+1.6);


//calculate which line to draw to
newLine = line >>4;
delayMicroseconds(1);

//display the array for this line
// a loop would have been smaller, but it messes the timing up
PORTB = frameBuffer[0][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[1][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[2][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[3][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[4][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[5][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[6][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[7][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[8][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[9][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[10][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[11][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[12][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[13][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[14][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[15][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[16][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[17][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[18][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[19][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[20][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[21][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[22][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[23][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[24][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[25][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[26][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[27][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[28][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[29][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[30][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[31][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[32][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[33][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[34][newLine];
delayMicroseconds(1);
PORTB = frameBuffer[35][newLine];
delayMicroseconds(1);

// klugdge to correct timings
PORTB = frameBuffer[36][newLine];
PORTB=PORTB;
PORTB=PORTB;
PORTB=PORTB;
delayMicroseconds(3);
}


//vsync
PORTB = _SYNC;

// if delaying for some reason
if(waiting)
{
// increment the waiting counter
waitingCount++;

// if waiting is over for a new game
if(waitingCount==DONE_WAITING & !justScored)
{
waitingCount=0;
// if on title screen
if(showingTitle)
{
// draw the loading bar
grayPixel(loadingBar,BASE_BAR);
loadingBar+=2;

// done loading
if (loadingBar > 37)
{
showingTitle=false;
clearScreen();
initGame();
initScreen();
waiting=false;
}
}
}

// waiting because someone scored
if(waitingCount==SCORE_WAITING & justScored)
{
justScored=false;
waitingCount=0;
waiting=false;
}
// wait for the remainder of the sync period
delayMicroseconds(305);
}
// not waiting
else
{
// increment the update delay counter
updateCounter++;
if( updateCounter >= UPDATE_INTERVAL)
{
//player movement
if(playerLeftTurn)
{
drawPaddle(PLAYER_LEFT_X,playerLeftOld,_BLACK);
playerLeft = analogRead(PLAYER_LEFT_PIN)>>6;
if(playerLeft<SCORE_BAR)
playerLeft=SCORE_BAR;
if(playerLeft>BASE_BAR)
playerLeft=BASE_BAR;
drawPaddle(PLAYER_LEFT_X,playerLeft,_WHITE);
playerLeftOld=playerLeft;
playerLeftTurn=false;
}
else
{
drawPaddle(PLAYER_RIGHT_X,playerRightOld,_BLACK);
playerRight = analogRead(PLAYER_RIGHT_PIN)>>6;
if(playerRight<SCORE_BAR)
playerRight=SCORE_BAR;
if(playerRight>BASE_BAR)
playerRight=BASE_BAR;
drawPaddle(PLAYER_RIGHT_X,playerRight,_WHITE);
playerRightOld=playerRight;
playerLeftTurn=true;
}
// remainder of sync period
delayMicroseconds(10);
updateCounter=0;
}
else
// remainder of sync period
delayMicroseconds(250);

// perform ball x velocity delay
ballXLoop--;
if(ballXLoop <= abs(ballXVel) and ballXVel != 0)
{
//ball movement;
drawBall(_BLACK);
updateBall(true);
ballXLoop=MAX_VEL;
}

// perform ball y velocity delay
ballYLoop--;
if(ballYLoop <= abs(ballYVel) and ballYVel != 0)
{
//ball movement;
drawBall(_BLACK);
updateBall(false);
ballYLoop=MAX_VEL;
}
// draw new ball
drawBall(_GRAY);
}
}

If any one can help me get the sound to work please help me!!!

Hi i have a question, When I plug the game in everything works fine exept for that the game starts without me pressing the button. then i cant controll the game with the paddles they just stand there and jump up and down a little. have anyone had the same problem and what can i do to fix it.
ps there is nothing wrong with the paddles ds

hello,
Usually when I have had problems with the electronics not working exactly correct, it turns out to be something with the grounds. Admittedly this is a pretty non specific answer but maybe someone else can help. I usually just do a lot of trial and error .