Basic Pong Game

In this post I will try to give you a basic idea on how to create a very basic pong-like game in C# and Winforms in .NET 4.0.

To start, create a new C# Winforms project and call it whatever you want.

For this project we will need 3 PictureBoxes, 1 Timer, 5 ints and 3 sizes right above the constructor. The pictureboxes represent the ball (picBoxBall) and the 2 paddles (one for the player and one for the AI - picBoxPlayer and picBoxAI). Two of the 5 ints are constant and represent the form's width and height (SCREEN_WIDTH and SCREEN_HEIGHT). Another 2 int are for the ball's speed on the X and Y axis (ballSpeedX and ballSpeedY) and last int is for the Timer's interval (gameTimeInterval). We will call the timer gameTime and the 3 sizes (sizePlayer, sizeAI sizeBall) represent the size of the 3 pictureboxes.

PictureBox picBoxPlayer, picBoxAI, picBoxBall;
        Timer gameTime;

        const int SCREEN_WIDTH = 800;
        const int SCREEN_HEIGHT = 600;
        
        Size sizePlayer = new Size(25, 100);
        Size sizeAI = new Size(25, 100);
        Size sizeBall = new Size(20, 20);

        int ballSpeedX = 3;
        int ballSpeedY = 3;
        int gameTimeInterval = 1;

In the constructor we will need to intilize our controls and the timer's Tick event which I've set the interval to 1. Also, we are going to give the position, size and color of each control.

public gameArea()//gameArea is the form's name
        {
            InitializeComponent();

            picBoxPlayer = new PictureBox();//
            picBoxAI = new PictureBox();//Initializes the PictureBoxes
            picBoxBall = new PictureBox();//

            gameTime = new Timer();//Initializes the Timer

            gameTime.Enabled = true;//Enables the Timer
            gameTime.Interval = gameTimeInterval;//Set the timer's interval

            gameTime.Tick += new EventHandler(gameTime_Tick);//Creates the Timer's Tick event

            this.Width = SCREEN_WIDTH;//sets the Form's Width
            this.Height = SCREEN_HEIGHT;//sets the Form's Height
            this.StartPosition = FormStartPosition.CenterScreen;//opens the form in center of the screen

            picBoxPlayer.Size = sizePlayer;//sets the size of the picturebox
            picBoxPlayer.Location = new Point(picBoxPlayer.Width / 2, ClientSize.Height / 2 - picBoxPlayer.Height / 2);//sets it's location (centered)
            picBoxPlayer.BackColor = Color.Blue;//fills the picturebox with a color
            this.Controls.Add(picBoxPlayer);//adds the picture box to the form

            picBoxAI.Size = sizeAI;
            picBoxAI.Location = new Point(ClientSize.Width - (picBoxAI.Width + picBoxAI.Width / 2), ClientSize.Height / 2 - picBoxPlayer.Height / 2);
            picBoxAI.BackColor = Color.Red;
            this.Controls.Add(picBoxAI);

            picBoxBall.Size = sizeBall;
            picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
            picBoxBall.BackColor = Color.Green;
            this.Controls.Add(picBoxBall);
        }

Next, in the Timer's tick event we will need to update the ball's position by adding the ballSpeedX and ballSpeedY ints to its original location and we will call 4 methods (2 for movement and 2 for collisions) that I will explain later.

void gameTime_Tick(object sender, EventArgs e)
        {
            picBoxBall.Location = new Point(picBoxBall.Location.X + ballSpeedX, picBoxBall.Location.Y + ballSpeedY);
            gameAreaCollisions();//Checks for collisions with the form's border
            padlleCollision();//Checks for collisions with the padlles
            playerMovement();//Updates the player's position
            aiMovement();//Updates the ai's position
        }

The gameAreaCollisions method basically checks to see if the ball hits form's sides. If it hits the upper or lower side of the form it inverts the Y speed and if it hist the left or right side of the form in resets the ball bu using a new method called resetBall (explained later). You will notice that I've used to different "else if", for collision with the left or right side of the form, although we could have used only one with and "or" approach. I did this because I am planning to elaborate on this approach in a later more advanced tutorial.

private void gameAreaCollisions()
        {
            if (picBoxBall.Location.Y > ClientSize.Height - picBoxBall.Height || picBoxBall.Location.Y < 0)
            {
                ballSpeedY = -ballSpeedY;
            }
            else if (picBoxBall.Location.X > ClientSize.Width)
            {
                resetBall();
            }
            else if (picBoxBall.Location.X < 0)
            {
                resetBall();
            }
        }
The resetBall method is called when the ball hits the left or right side of the form and when it does it send the ball back to the center of the screen, reseting the position. In this method you could add score incrementation for example.
private void resetBall()
        {
            picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
        }
Next is the playerMovement method which moves the player's padlle according to the cursor position. The movement on the X axis is constant and only the Y position changes.
private void playerMovement()
        {
            if (this.PointToClient(MousePosition).Y >= picBoxPlayer.Height / 2 && this.PointToClient(MousePosition).Y <= ClientSize.Height - picBoxPlayer.Height / 2)
            {
                int playerX = picBoxPlayer.Width / 2;
                int playerY = this.PointToClient(MousePosition).Y - picBoxPlayer.Height / 2;

                picBoxPlayer.Location = new Point(playerX, playerY);
            }
        }
Next is the aiMovement method which moves the AI paddles to the ball's position on Y axis (the X is always the same) whenever the ball is moving towards him. The ball comes towards the AI's paddle only when it's speed on the X axis is positive as the paddle is located in the right side of the form where the X increases.
private void aiMovement()
        {
            if (ballSpeedX > 0)
            {
                picBoxAI.Location = new Point(ClientSize.Width - (picBoxAI.Width + picBoxAI.Width / 2), picBoxBall.Location.Y - picBoxAI.Height / 2);
            }
        }
Last we have the padlleCollision method which verifies the collision with the paddles. We verify this by using the Bounds.IntersectsWith method the the PicturBox control has. As we did in the gameAreaCollisions method all we have to do is invert the speed, but this time on the X axis. I've used two ifs, although I could have used only one for the next tutorial. You can use only one with the "or" aproach.
private void padlleCollision()
        {
            if (picBoxBall.Bounds.IntersectsWith(picBoxAI.Bounds))
            {
                ballSpeedX = -ballSpeedX;
            }

            if (picBoxBall.Bounds.IntersectsWith(picBoxPlayer.Bounds))
            {
                ballSpeedX = -ballSpeedX;
            }
        }

Now press F5 and play the game. Of course, you will notice that you can't beat the AI as its paddle always moves at the ball's position. This tutorial was meant to give you a basic and general idea on how to create a pong rip off. In a later tutorial, whenever the time will allow it, I will try to show you how to create a basic AI, add some graphics, some sounds and gameplay logics (lives, score, difficulty).

7 comments:

  1. Thanks for making it simple and fun :)

    ReplyDelete
  2. Can build it for somereason :/

    ReplyDelete
  3. the code does not work properly....pls replay me

    ReplyDelete
  4. my slutty teacher did this with us

    ReplyDelete
  5. NICE little example - I misread a few lines here and there and had some odd bugs on my initial run, but once I have ironed it out it works like a charm. Nice little post

    ReplyDelete