Click here to Skip to main content
15,883,901 members
Articles / Game Development
Tip/Trick

C# Simple Pingpong Game

Rate me:
Please Sign up or sign in to vote.
4.89/5 (25 votes)
27 Apr 2015CPOL4 min read 187.6K   13.6K   33   18
I was bored at work, so I made a classic game to entertain myself.

Introduction

This is the game we all know, the classic Ping pong game.

Image 1

This is a simple version of the game, but very customizable and fun.

The Creation Process

I started the program with just making the ball bounce back and fourth against the walls, left to right.

  • To do this, I first made what I call the WorldFrame. I added a Panel in the right size and location.
  • In this panel, I then created a picturebox representing the ball called "pb_Ball".
  • After this, I made a timer called "timer_Movement" and had its interval set to 1 ms.
    • The tick event of this timer is what makes the ball move, I use a Boolean to check whether to go left or right. If the ball hits either of the walls, it changes the Boolean and makes the ball go in the other direction.
    • Here's how I check if the ball hits the wall:
C#
public Boolean Collision_Left(PictureBox obj)
{
    if (obj.Location.X <= 0)
    {
        return true;
    }
    return false;
}

public Boolean Collision_Right(PictureBox obj)
{
    if (obj.Location.X + obj.Width >= WorldFrame.Width)
    {
        return true;
    }
    return false;
}

Within the tick event, where the check for which direction the ball is going, I use this to check if the ball hits the outer wall. If it's true, just change the Boolean value.

  • After this, I added 2 Pictureboxes representing the player, and the enemy
  • Made the player able to go up and down with 2 events, KeyPress Up/Down
C#
private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)      
            {
                case Keys.W:
                case Keys.Up:
                    Player_Down = false;
                    Player_Up = true;
                    break;
                case Keys.S:
                case Keys.Down:
                    Player_Up = false;
                    Player_Down = true;
                    break;
            }
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.W:
                case Keys.Up:
                    Player_Up = false;
                    break;
                case Keys.S:
                case Keys.Down:
                    Player_Down = false;
                    break;
            }
        }

I use 2 Booleans to check if the player is going Up or Down, and then in the Movement timer, I check if any of the booleans is true. Then the player moves.

C#
if (Player_Up && !Collision_Up(pb_Player))
                {               
                    pb_Player.Top -= Speed_Player;    
                }
if (Player_Down && !Collision_Down(pb_Player))
                {               
                    pb_Player.Top += Speed_Player;
                }

The extra functions like Collision_Up can be found in the well documented source code.

  • When this was done, I made the same thing for the collision on the walls, but on the player instead.
    • This was a bit tricky, at the same time I did this I made it so it checks where it lands on the player and from there changes the balls "force" how fast it goes up/down
    • I did this by creating 5 small rectangles in front of the player, invisible and checks if the ball interacts with the player and these rectangles. If it does, then boom it goes away to the other direction.
    • Sample code (See full source files for everything):
    C#
    public Boolean Collision_Player(PictureBox tar)
            {
                if (tar.Bounds.IntersectsWith(pb_Player.Bounds))
                {
                    PictureBox temp1 = new PictureBox();
                    temp1.Bounds = pb_Player.Bounds;
                    temp1.SetBounds(temp1.Location.X + temp1.Width, temp1.Location.Y, 1, 10);
                    if (tar.Bounds.IntersectsWith(temp1.Bounds)) 
                    {
                        BallForce = 3;
                        return true;
                    }
                    temp1.SetBounds(temp1.Location.X, temp1.Location.Y + 5, 1, 10);
                    if (tar.Bounds.IntersectsWith(temp1.Bounds))
                    {
                        BallForce = 2;
                        return true;
                    }
                    temp1.SetBounds(temp1.Location.X, temp1.Location.Y + 10, 1, 10);
                    if (tar.Bounds.IntersectsWith(temp1.Bounds))
                    {
                        BallForce = 1;
                        return true;
                    }
    ...
  • With this, I created within the Movement timer event a check for if the Integer "BallForce" has any value below or above 0. If it's below 0, the ball goes down, above it goes up.
    • At the same time, as the ball goes left-right, it also goes up/down depending on the BallForce value.
    • Example, if I hit the ball at the top of the player. BallForce goes to 3 - Then the ball goes 1 pixel to the side and 3 pixels up every ms.
    C#
    if (BallForce > 0)
     {
         pb_Ball.Top -= BallForce;
     }
     if (BallForce < 0)
     {
         pb_Ball.Top -= BallForce;
     }
    
  • Along with this, I had to make sure that the ball didn't go flying up in space or down to hell. So with every movement up, it checks if the ball goes Above/Below the WorldFrame. And if it does, it reverses the BallForce.

    Inside timer_Movement tick event:

    C#
    if (pb_Ball.Location.Y <= 1)
    {
        BallForce = ReverseInt(BallForce, true, true);
    }
    if (pb_Ball.Location.Y + pb_Ball.Height >= WorldFrame.Height - 1)
    {
        BallForce = ReverseInt(BallForce, true, false);
    }
    
    C#
    public int ReverseInt(int x, Boolean Force = false, Boolean Negative = false)
            {
                if (Force) 
                {
                    if (Negative)  
                    {
                        if (x > 0) 
                        {
                            x = ~x + 1;
                        }         
                    }
                    else
                    {  
                        x = x - (x * 2);
                    }
                }
                else
                {
                    if (x > 0)
                    {
                        x = x - (x * 2);
                    }
                    else
                    {          
                        x = ~x + 1;
                    }
                }
                return x;
            }
  • How the Enemy moves is very simple
    • It checks whether the ball is above or below its central point. Then, it moves depending on its location.
    C#
    if (pb_Enemy.Location.Y + 28 < pb_Ball.Location.Y)
                    {   //Which is around 28 pixels below its Y coordinate
                        pb_Enemy.Top += Speed_Enemy;
                    }
                    else
                    {
                        pb_Enemy.Top -= Speed_Enemy;
                    }
  • I added this to a new timer called timer_Enemy, not sure why but it's there now.
  • I also added ex the same as the "if ball hits player on the top it bounces back" to the enemy with this.
  • After this, I added every customizable option, like change of colors/timers/speeds with a new form called SettingsForm.cs.
    • In this, I use a global setting in the file to change, and then in Form1, I just apply these every ms together with the movement. See source file for more information.

    There are score images also, not visible on the image above but they're there.

  • I made these by adding 5 pictureboxes on each side of the "Press space to start" label.
    • Then, I changed the original code that the ball bounces when it hits each side by changing the pictureboxes color to a black dot if the player/enemy messes up.
    • If 5 of these boxes turn black, the game is over.
    C#
    public void AddScore(PictureBox[] Arr)
    {
        for (int i = 0; i < Arr.Length; i++)
        {
            if (Arr[i].BackColor == ScoreColor)
            {   //And then changes it to black
                Arr[i].BackColor = Color.Black;
                break;
            }
        }
    
        if (Arr[4].BackColor == Color.Black)
        {
            GameOn = false;
            label_Start.Visible = true;
            RestoreScore();
            pb_Ball.Location = new Point(208, rng.Next(10, 190));
            pb_Player.Location = new Point(3, 67);
            pb_Enemy.Location = new Point(409, 67);
            Round = 0;
            label_Time.Visible = false;
        }
    }
    

This is the basic idea, basis of the code.

Points of Interest

I learned a lot, had fun creating this. Making it while at work so had ~10 minutes of time each day so it took me a few days to complete.

I learned a lot from this, I have made games before so some of the code is what I reuse/improve from my other games.

I'm not a pro, I just like programming and I like to share my idéas and my code with others to play with.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Help desk / Support
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionhow do I use settings? Pin
Ionuţ Alex7-May-16 4:46
Ionuţ Alex7-May-16 4:46 
QuestionThe code Pin
Member 122760712-Feb-16 0:10
Member 122760712-Feb-16 0:10 
GeneralFull screen Pin
Axel Steiner28-Aug-15 7:56
Axel Steiner28-Aug-15 7:56 
Would be nice Smile | :)

Pause function is not a problem Wink | ;)

modified 28-Aug-15 14:04pm.

QuestionGood job, but only one advice Pin
Octanic10-May-15 7:04
Octanic10-May-15 7:04 
QuestionInvalid .zip archive? Pin
Ravi Bhavnani28-Apr-15 7:23
professionalRavi Bhavnani28-Apr-15 7:23 
AnswerRe: Invalid .zip archive? Pin
Hydeen28-Apr-15 21:32
Hydeen28-Apr-15 21:32 
GeneralRe: Invalid .zip archive? Pin
Ravi Bhavnani29-Apr-15 5:01
professionalRavi Bhavnani29-Apr-15 5:01 
QuestionCouple of suggestions Pin
Bjarne Nielsen28-Apr-15 2:24
Bjarne Nielsen28-Apr-15 2:24 
AnswerRe: Bad code Pin
_Vitor Garcia_28-Apr-15 3:03
_Vitor Garcia_28-Apr-15 3:03 
AnswerRe: Bad code Pin
Hydeen28-Apr-15 3:24
Hydeen28-Apr-15 3:24 
GeneralRe: Bad code Pin
Bjarne Nielsen28-Apr-15 4:21
Bjarne Nielsen28-Apr-15 4:21 
GeneralRe: Bad code Pin
George200628-Apr-15 10:24
George200628-Apr-15 10:24 
GeneralRe: Bad code Pin
Jacob Himes28-Apr-15 12:32
professionalJacob Himes28-Apr-15 12:32 
AnswerRe: Bad code Pin
PeejayAdams28-Apr-15 3:40
PeejayAdams28-Apr-15 3:40 
GeneralRe: Bad code Pin
Octanic10-May-15 7:08
Octanic10-May-15 7:08 
AnswerRe: Couple of suggestions Pin
Bjarne Nielsen28-Apr-15 21:52
Bjarne Nielsen28-Apr-15 21:52 
QuestionBrilliant, why didn't I think of that ... Pin
peterkmx28-Apr-15 1:29
professionalpeterkmx28-Apr-15 1:29 
GeneralMy vote of 5 Pin
Sachin Mahandule27-Apr-15 22:16
professionalSachin Mahandule27-Apr-15 22:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.