Pong is a two-dimensional sports game that is similar to table tennis. It is one of the earliest video games, first released in 1972. Since then, it has been recreated multiple times in different programming languages. Today, you will learn how to make your own version of the game using simple programming concepts in C#.
Let’s begin.
Creating the Field
First, you need to prepare the field with an upper and a lower border and two rackets. Declare two constants of type int that define the dimensions of the field – fieldWidth and fieldLength. To visualize the upper and the lower border, use the string method Repeat on the fieldTile character variable.
const int fieldLength = 50, fieldWidth = 15;
const char fieldTile = '#';
string line = string.Concat(Enumerable.Repeat(fieldTile, fieldLength));
Then create the game loop and print the borders on the console. The first line starts from coordinates 0,0 and the second one – 0, fieldWidth(15).
while(true)
{
Console.SetCursorPosition(0,0);
Console.WriteLine(line);
Console.SetCursorPosition(0,fieldWidth);
Console.WriteLine(line);
}
Next, make a variable for the rackets’ size – racketLength, for the character used to visualize them – racketTile, and for their positions – leftRacketHeight and rightRacketHeight.
const int racketLength = fieldWidth / 4;
const char racketTile = '|';
int leftRacketHeight = 0;
int rightRacketHeight = 0;
To make the rackets appear on the field,add a for loop in the game loop.
for(int i = 0; i < racketLength; i++)
{
Console.SetCursorPosition(0, i + 1 + leftRacketHeight);
Console.WriteLine(racketTile);
Console.SetCursorPosition(fieldLength - 1, i + 1 + rightRacketHeight);
Console.WriteLine(racketTile);
}
Player Movement
Make a loop that will continue until a key is pressed. After the loop, check which key has been pressed using a switch and update the rackets’ positions based on that. Clear the previous positions with another for loop.
while(!Console.KeyAvailable)
{
}
//Check which key has been pressed
switch(Console.ReadKey().Key)
{
case ConsoleKey.UpArrow:
if(rightRacketHeight > 0)
{
rightRacketHeight--;
}
break;
case ConsoleKey.DownArrow:
if(rightRacketHeight < fieldWidth - racketLength - 1)
{
rightRacketHeight++;
}
break;
case ConsoleKey.W:
if(leftRacketHeight > 0)
{
leftRacketHeight--;
}
break;
case ConsoleKey.S:
if(leftRacketHeight < fieldWidth - racketLength - 1)
{
leftRacketHeight++;
}
break;
}
//Clear the rackets’ previous positions
for(int i = 1; i < fieldWidth; i++)
{
Console.SetCursorPosition(0,i);
Console.WriteLine(" ");
Console.SetCursorPosition(fieldLength - 1,i);
Console.WriteLine(" ");
}
Adding a Ball
What you need to know about the ball is its coordinates, the character representation on the field, and its direction.
int ballX = fieldLength / 2;
int ballY = fieldWidth / 2;
const char ballTile = 'O';
bool isBallGoingDown = true;
bool isBallGoingRight = true;
Let’s go back to the empty while loop that waits for a key to be pressed. It has to update the ball’s position.
while(!Console.KeyAvailable)
{
Console.SetCursorPosition(ballX, ballY);
Console.WriteLine(ballTile);
Thread.Sleep(100); //Adds a timer so that the players have time to react
Console.SetCursorPosition(ballX, ballY);
Console.WriteLine(" "); //Clears the previous position of the ball
//Update position of the ball
if(isBallGoingDown)
{
ballY++;
} else
{
ballY--;
}
if(isBallGoingRight)
{
ballX++;
} else
{
ballX--;
}
}
However, this code does not limit the movement of the ball to the borders of the field. You need to add more conditions to the same while loop and declare variables to store the players’ points.
int leftPlayerPoints = 0;
int rightPlayerPoints = 0;
if(ballY == 1 || ballY == fieldWidth - 1)
{
isBallGoingDown = !isBallGoingDown; //Change direction
}
if(ballX == 1)
{
//Left racket hits the ball and it bounces
if(ballY >= leftRacketHeight + 1 && ballY <= leftRacketHeight + racketLength)
{
isBallGoingRight = !isBallGoingRight;
}
else //Ball goes out of the field; Right player scores
{
rightPlayerPoints++;
ballY = fieldWidth / 2;
ballX = fieldLength / 2;
Console.SetCursorPosition(scoreboardX, scoreboardY);
Console.WriteLine($"{leftPlayerPoints} | {rightPlayerPoints}");
if(rightPlayerPoints == 10)
{
goto outer;
}
}
}
if(ballX == fieldLength - 2)
{
//Right racket hits the ball and it bounces
if(ballY >= rightRacketHeight + 1 && ballY <= rightRacketHeight + racketLength)
{
isBallGoingRight = !isBallGoingRight;
}
else //Ball goes out of the field; Left player scores
{
leftPlayerPoints++;
ballY = fieldWidth / 2;
ballX = fieldLength / 2;
Console.SetCursorPosition(scoreboardX, scoreboardY);
Console.WriteLine($"{leftPlayerPoints} | {rightPlayerPoints}");
if(leftPlayerPoints == 10)
{
goto outer;
}
}
}
Scoreboard Visualization
To add a scoreboard, you need variables that store its position.
int scoreboardX = fieldLength / 2 -2;
int scoreboardY = fieldWidth + 1;
The scoreboard is printed on the console every time a player increases their score. Let’s say the game ends when one of the players reaches 10 points. You need to break out of the game loop with the goto command.
//Left Player
leftPlayerPoints++;
ballY = fieldWidth / 2;
ballX = fieldLength / 2;
Console.SetCursorPosition(scoreboardX, scoreboardY);
Console.WriteLine("${leftPlayerPoints} | {rightPlayerPoints}")
if(leftPlayerPoints == 10)
{
goto outer;
}
//Right Player
rightPlayerPoints++;
ballY = fieldWidth / 2;
ballX = fieldLength / 2;
Console.SetCursorPosition(scoreboardX, scoreboardY);
Console.WriteLine("${leftPlayerPoints} | {rightPlayerPoints}")
if(rightPlayerPoints == 10)
{
goto outer;
}
Outside of the game loop put a marker, clear the console and reset the cursor. Check who the winner is and print the appropriate message.
outer:;
Console.Clear();
Console.SetCursorPosition(0,0);
if(rightPlayerPoints == 10)
{
Console.WriteLine("Right player won!");
}
else
{
Console.WriteLine("Left player won!");
}
If you’ve followed all the steps your project should be finished and working now. You can always adjust the values of the variables. For example, you can make the field bigger or smaller or increase the speed of the ball to make the game more challenging.
To check out the final code and compare it to yours click the link below.
Lesson Topics
- Creating a Field
- Implementing Player Movement
- Adding a Ball
- Scoreboard Visualization