Click here to Skip to main content
16,017,608 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 190.4K   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 
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 
OK, I guess it's only fair to be more specific.

I'm not trying to be harsh or too nit picky, so please don't be offended, it's not meant to be offensive in any way. The code is not terrible, just some things I don't like.

You should get out of the habit of using variable names like "i" and parameter names called "Arr", use descriptive names. For very small loops maybe it's OK, but I certainly don't like it and never use it. Also, I don't use Hungarian notation for parameters, which I think is what most people prefer, but I guess it's a matter of taste.

Prefixing variables with like "pb" for PictureBoxes is also a bad idea, since at some point, you might change the control for something else.

The worst part is probably the AddScore function. I didn't download the source, so I have only seen the posted code. Doing a comparison on UI elements for business logic like this is bad. For example, it will likely break the code, if at some point you decide to change the color of score boxes from black to blue, unless you remember to change it everywhere. Hard coding positions like you did also seems like a rather bad idea.

While writing this, I read PeejayAdams' comment. I must admit, I missed the part of you not being a professional, so I will agree with his comments.

Don't let this discourage you, programming is fun and with experience comes better code.

Keep it up!

Sincerely
Bjarne Nielsen
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.