Baroody's Game Development Site

A Website to help you program computer games

Step 3: Collisions

This is where we really make Pong come to life.  Before we do that, however, we need to activate the appropriate keys on the keyboard.  In order to do that, enter the following code into your program:

Form_KeyDown sub routine

The first thing to note here is when this code will be run.  Basically, it runs any time a key is pressed down on the keyboard (that's why it's called Form_KeyDown)!  What we're doing is performing some actions when certain keys are depressed.  We don't do anything if, for example, the "R" key is pressed, but we do some important things if the left or right arrow is pressed!  Let's see how it works:

  • If the left arrow key is depressed, we want the paddle to move to the left, so we set the paddle speed to be -150.  This will move the paddle to the left 150 twips (a "twip" is defined as 1/1440 of a inch).
  • If the right arrow key is depressed, we want the paddle to move to the right, so we set the paddle speed to be 150.  This will move the paddle to the right 150 twips.

Pretty straight forward, right?

Now, we just have to take care of the situation when we let up on the arrow keys.  What do we want the paddle to do then?  Stop, right?  Let's see how it works:

Form_KeyUp sub routine


OK, now for the really fun stuff...moving the ball and dealing with collisions (the ball hitting a wall or the paddle).  Remember that we set the timer interval to 1 millisecond.  That means we'll run the tmrMain_Timer() sub routine every millisecond.  Pretty quick, huh?  Let's start by getting the ball to move:

tmrMain_Timer sub routine - Step 1

Here's what we've done:

  • We start by declaring a temporary variable, which we'll use later (don't worry about it for now).
  • Next, we move the ball.  To do this, we change the location of the top of the ball (shpBall.Top) by adding the vertical speed to it's current value.  Now, remember that we originally started with a vertical speed of 50, so basically, we're moving the ball 50 twips down from where it is currently.  Then we move the left side of the ball (shpBall.Left) in the same way.  In the beginning of the game, we selected a random number between -250 and 1 for our horizontal speed, right?  Let's say we picked -100.  Now, we use that value to move the left side of the ball 100 twips to the left.  Rember that we do this every 1 millisecond, so the movement actually looks very smooth on the screen.
  • Finally, we move the paddle.  Assuming that the paddle speed is not = 0 (in other words, the player is holding down the right or left arrow key), we add the paddle speed to the left side of the paddle.  If the right arrow is held down, the paddle speed is 150, so we move the left side of the paddle 150 twips to the right.  If the left arrow key is held down, the paddle speed is -150, so we move the left side of the paddle 150 twips to the left.

Try running your program now.  Click on the "Play" button.  After a 2 second delay, the ball should move down and to the left  It will keep moving right through the wall on the left!  While this is happening, try moving the paddle with the right and left arrow keys.  It should following your commands.


Now we've got to put some parameters around the movement of the ball and the paddle.  Let's focus on the ball at first.  When it hits the left side wall, we want it to rebound to the right, don't we?  Here's how to do it:

tmrMain_Timer sub routine - Step 2

The new code here works like this:

  • First, we check to see if the left most part of the ball is to the left of (<=) the right most part of the left wall.  If it is, then the ball has moved beyond the wall, right?  If that's the case, we first make the left most part of the ball equal to the value of the right most part of the left wall.
  • Then, we make the horizontal speed  be the opposite of it's existing value.  In our case, we're going to make the speed be 100 (it was -100, remember?).  That means that the ball will start moving to the right.
  • We also make a noise...that's what the "Beep" is for.

Try out your program again.  The ball should "hit" the left wall, beep, and start moving to the right.  However, it will still go through either the bottom wall or the right wall.  Our next step will be to handle a collision with the right wall:

tmrMain_Timer sub routine - Step 3

Assuming that we haven't "hit" the left side wall, we need to check for a collision with the right side wall.  This is done with the code highlighted above.  It's pretty similar to the code for the left side wall, but make sure that you really understand it before moving on.  After adding this code, run your program.  The ball should bounce off both the left and right side walls, but go through the bottom wall.  In fact, at this point, the ball will continually move down and just keep bouncing off the left and right walls (even though you can only see it for a little while!).


Next, we need to modify our paddle movement a little.  When moving it left or right, do we really want it to go through the left and right walls?  Not really...we want it to stop when it hits them, right?  Try adding the following code:

tmrMain_Timer sub routine - Step 4

Basically, what we do here is to first compare the left hand side of the paddle to the right most part of the left side wall.  If the left most part of the paddle is to the left of the right most part of the wall (shpPaddle.Left <= shpWallLeft.Left + shpWallLeft.Width), then we set it to be equal to that position.  Similarly, if the right most part of the paddle is to the right of the left most part of the right wall, we set the paddle position to be just touching the right wall.

After adding this code, try running the program.  The ball will keep bouncing, but now the paddle should only move as far as the left and right walls...it shouldn't go through them.


Now we need to handle the situation where the ball hits the paddle.  This is a little more complicated.  The basic idea is this:  if the bottom of the ball is below the top of the paddle and the ball is within the left and right boundaries of the paddle, then the ball has "hit" the paddle and should be reflected up.

Take a look at the following code:

tmrMain_Timer sub routine - Step 5

Note that a number of things happen here:

  • First, we check to see if the bottom of the ball (shpBall.Top + shpBall.Height) is below the top of the paddle (>= shpPaddle.Top).
  • If that condition is met, we check to see if the ball is within the right and left boundaries of the paddle (shpBall.Left + shpBall.Width >= shpPaddle.Left and shpBall.Left <= shpPaddle.Left + shpPaddle.Width).
  • Assuming both conditions are met, we update the player's score, make a sound, position the ball to be just touching the top of the paddle, and change the vertical speed to move the ball up.

Try adding this code and then running your program again.  You should be able to "hit" the ball with the paddle and change it's direction.  The only issue now is that it will keep going up forever since we haven't taken care of the collision with the top wall!

Here's the code for making the ball bounce off the top wall:

tmrMain_Timer sub routine - Step 6

You should be able to understand this code at this point.  Now, your game is really moving along...you can play the basics!  If you play it for a little while, though, you'll notice that it's really hard to lose...when the ball goes past the paddle, it always ends up on top of it again...we'll cover how to deal with this problem in the next step.


If you're ready to move on, click here or select Step 4: End the Game on the navigation bar.