Flash Tutorial Links:
Play Games: HTML5 Tutorials:

How To Make Pong

You are not considered a game developer until you've made your own Pong game!

gaminglogy logo

HTML5 Version

Learn how to make the same game in HTML5 instead. Head over to Gaminglogy now!

History of Pong

The story of Pong goes back a long way. It is commonly hailed as the first video game, but that's historically untrue. The idea of what constitutes a video game is somewhat debatable, so it's not easy to claim accurately which video game is the true first. But there are definitely several other games that came out before Pong, like Spacewars, which was created by MIT students Martin Graetz, Steve Russell and Wayne Wiitanen. It was a 2 player spaceship battle that takes place around a strong gravity field.

Even so, Pong is still one of the earliest arcade video game originally manufactured by Atari in 1972 to achieve huge commercial success. The success of Pong pushed the video games industry forward, so we really have to thank it for all the great games we're playing today!

But, if you think about the game design of Pong, it's actually quite simple. It basically involves 2 players (or single player versus a computer) whacking a ball to and fro the screen hoping to score a goal.

Regardless, this game will be a good starting point to explore a few elements in game creation. Let's take a look at how we can recreate this iconic game.

Game Scenario

The game involves two players controlling a wooden block to hit a wooden ball to the opponent. The objective is to get it past the opponent's wooden block.

Game Details

  1. Control your wooden block with the W (to go up) and S (to go down) keys.
  2. Hit the ball when it comes near you,
  3. 1 point is scored for each ball that you get past your opponent and vice versa.

Download the Game Files

The files you need to create this game can be downloaded from here.

Step 1 - Managing your FLA file

If you open up the FLA file provided, you will see that it is not much different from the one you did in Tutorial 1. This is very much the intention of this series of tutorials. I hope that you can learn through a very consistent framework to get most of these games done.

In the library, we have images of the player and computer wood blocks, the walls, etc.

tut2library

Open up each of the movieclips and observe the slight differences in the positioning of the png files within it. For example, in the Ball movieclip, we position the ball to be in the exact centre. For the Player movieclip, the centre is towards the right, whereas the Computer movieclip is the exact opposite. These subtle differences in the positioning just lead to more natural coding as you'll see later on.

Although we have several MovieClips this time round, we will still not be writing any classes for each of them. It is because the classes are really not complex enough to warrant that. As usual, we rely on Flash's default classes for them. Do remember to set it up through the Linkage option.

Since this game needs to track the scores of both the player and the computer, we need to add more elements to the UI.

stage

You can easily drag these onto the stage using the TextField tool. Make sure you set the instance name of the dynamic text fields correctly.

set text field name

Likewise, do the same for txtScorePlayer. Take note that since GameController.as now controls the FLA file, these text fields can be accessed just like any regular variables.

Step 2 - Starting up the game in your GameController.as

Let's tackle the initial values that we have to set before the game begins. If you do a mental inspection of how this game works, you should be able to start typing out some of these initialization codes. In fact, you should find most of the codes familiar and natural. Let's take a look at what goes on in the startGame function.

50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100
101
102
103
104
105
public function startGame()
{
    //Create ball
    ball = new Ball();
    ball.x = C.BALL_START_X;
    ball.y = C.BALL_START_Y;
    mcGameStage.addChild(ball);
    
    //Create player
    player = new Player();
    player.x = C.PLAYER_START_X;
    player.y = C.PLAYER_START_Y;
    mcGameStage.addChild(player);
    
    //Create computer
    computer = new Computer();
    computer.x = C.COMPUTER_START_X;
    computer.y = C.COMPUTER_START_Y;
    mcGameStage.addChild(computer);
    
    //Create top and bottom walls
    topWall = new Wall();
    topWall.x = C.TOP_WALL_X;
    topWall.y = C.TOP_WALL_Y;
    bottomWall = new Wall();
    bottomWall.x = C.BOTTOM_WALL_X;
    bottomWall.y = C.BOTTOM_WALL_Y;			
    mcGameStage.addChild(topWall);
    mcGameStage.addChild(bottomWall);
    
    playerScore = C.PLAYER_START_SCORE;
    computerScore = C.COMPUTER_START_SCORE;
    
    moveY = 0;
    moveY2 = 0;
    ballVelX = -1;
    ballVelY = 1;
    
    mcGameStage.addEventListener(Event.ENTER_FRAME,update);
			
    //Handle event when this game is being preloaded
    addEventListener(Event.ADDED_TO_STAGE, gameAddedToStage );
    
    //Handle situations when this game is being run directly
    if (stage != null)
    {
        stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
        stage.addEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
    }
}
		
private function gameAddedToStage(evt: Event):void
{
    stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
    stage.addEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
}

I don't really want to spend too much time talking about lines 50 to 81. You can see that they are pretty standard code you saw earlier on in Tutorial 1 as well. Just remember to instantiate the object that we want and set its x and y coordinates. Do not forget to add it onto the stage by using addChild. Remember that mcGameStage here refers to the MovieClip which the entire game takes place.

Line 83 initializes moveY to 0. Like before, moveY is a variable which indicates whether the player's block is moving up or down. When moveY is positive, it is moving in the positive Y-direction, which in computer terms, is downwards. The opposite holds true.

moveY2 is the corresponding indicator for the computer's block.

In lines 85 and 86, ballVelX will store the velocity of the ball. In a similar fashion, a positive ballVelX will mean that the ball is moving in a positive X-direction, i.e. moving right. Since the ball can move in a variety of directions, we need to use ballVelY to keep track of the movement in the Y-direction as well. The combination of these two variables will easily allow you to data crunch where the ball should be in the next game tick.

Line 88 starts the game loop.

Lines 90 to 98 deserve a more detailed explanation. Earlier on in Tutorial 1, we learnt about using the mouse cursor as the main source of input. In this tutorial, we're going to learn about getting user input via the keyboard. A more detailed explanation of the KeyboardEvent is presented here in the Resources section. If you find difficulties understanding Keyboard events, please head over there first.

In line 91, we see a new kind of event used here, ADDED_TO_STAGE. This line of code is written explicitly to cater for cases where this game will be preloaded by another swf file, which is quite likely. When your game is preloaded, it becomes a child of another movie clip. The ADDED_TO_STAGE event will be triggered by the preloader when it calls addChild to add this game once it is preloaded. When it triggers, you can see that it calls the function gameAddedToStage.

The code that gets executed in this function is essentially the same as line 96 and 97, so let's discuss them together. The KeyboardEvent.KEY_DOWN event is triggered whenever any keys are pressed by the player. Similarly, we listen to when the key is released with the KEY_UP event. keyUpHandler and keyDownHandler are the functions used to handle these two events.

But notice that we didn't add it to mcGameStage like we usually did. Instead, we added it to stage. This is because keyboard events are issued to the stage in AS3. This is a common problem that always trips new programmers in AS3, so you need to remember to add keyboard listeners to the stage, not movie clips.

The confusion may arise when you question why there is a need to have two chunks of code to listen to the same keyboard events, line 91 versus lines 94 to 98. Actually lines 94 to 98 would suffice if your game is being tested (CTRL+ENTER) or loaded directly. But it fails to work when your game is preloaded, because remember that the stage reference will change when it is preloaded and added as a child to another movieclip.

**To reinforce this point, try commenting away line 91. You will realise that the keyboard input fails when this game is preloaded.**

Problems of KEY_DOWN events

There is another inherent problem listening to Key down events; the function keyDownHandler is only triggered once when a key is hit. The player's block will not keep moving up even if the player is holding down the W key. Instead, the player will have to continuously hit the W or S keys to move the block up or down. This kind of interaction with the game is pretty unnatural and you can trust me 100% that your players are going to get extremely frustrated.

Note that I avoided using the Up and Down key in this game because some browsers don't trap the keys well, and you end up scrolling the entire webpage instead when you're trying to play the game. But if you're using CTRL+ENTER to test out your game, the S key gets "eaten" up by Flash default keyboard shortcuts as well. For testing purposes, you can use CTRL+SHIFT+ENTER instead. Another way would be to go to Control > Disable Keyboard Shortcuts (during runtime after you hit CTRL + ENTER, not during the design time).

disable keyboard shortcuts

In AS2, we were able to continuously check if a key is depressed by using Key.isDown(...). But that doesn't work in AS3 anymore. There are some web tutorials online which describe writing a Key class to simulate this behaviour, but I'm going to introduce a simpler "cheat" to get around it. We just need to assume that the W or S key is always down until the KeyboardEvent.KEY_UP event is called. When that happens, the function keyUpHandler will trigger to clear the moveY variable and set it to 0. Simple isn't it? :)

Step 3 - Key Handlers

We need to define the two key handler functions.

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
private function keyDownHandler(evt:KeyboardEvent):void
{
    if (evt.keyCode == 87) 
    {
        //Move player up
        moveY = -1;
    }
    else if (evt.keyCode == 83)
    {
        //Move player down
        moveY = 1;
    }
}
 
private function keyUpHandler(evt:KeyboardEvent):void
{
    moveY = 0;
}

A keycode of 87 refers to the 'W' key, whereas the keycode of 83 refers to the 'S' key in Flash (For the full list, you can either refer to Adobe livedocs or head over to the resource on keycodes here). What happens here is just setting the direction of movement for the player block when the respective keys are pressed.

They keyUpHandler, as explained earlier, is used to detect when the player releases the W or S key. Releasing any of these keys will cause the block to stop moving, hence the setting of moveY to 0.

Step 4 - Game Loop, Computer "AI"

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
private function update(evt:Event)
{
    //******************			
    //Handle User Input
    //******************
    //Handle Player 1 User Input
        //Handled with keyDownHandler
    //Handle Player 2 User Input
        //Handled with Computer AI
    moveY2 = 0;
    if (Math.random() < C.COMPUTER_INTELLIGENCE)
    {
        //Computer reacts and move towards ball position
        if (ballVelY < 0)
            moveY2 = -1;
        else if (ballVelY > 0)
            moveY2 = 1;
    }

Now, let's talk about the game loop that happens in your update function. At this time, do a quick check to see that you have set your fps to 30. This will cause this update function, your game loop, to execute 30 times a second (theoretical maximum).

The code presented above handles the "brain" of the computer, or more commonly known as the Artificial Intelligence (AI) of the computer. Here, you can see that it isn't entirely smart, but I coded it in a way such that you can tweak the numbers to see improvements to the AI, rather than having to change the entire code to make it smarter.

So what happens is, we set it to stop moving first in line 135, somewhat like a pause and think state of mind for the computer. Line 136 is where the magic takes place. If you look into the constants file, C.as for this game, you will see that in line 39, we set COMPUTER_INTELLIGENCE to a value of 0.4. Back in Line 136, we asked Flash to generate a random number, x, where 0 <= x < 1. The nett effect of this means that the computer is "smart" 40% of the time whenever this code is executed. In lines 138 to 142, what the computer does after it acts, is to detect whether the ball is moving up or down (by checking ballVelY). If the ball is moving up, the computer will react and move up as well (by setting its moveY2 to be -1). If the ball is moving down, the computer reacts as well.

Take an extreme case, and comment away Line 136 or set the COMPUTER_INTELLIGENCE in the C.as to be a value of 1. If you run the game, you will see that the computer almost always manages to catch the ball. Because by doing that, you're making the computer AI extremely smart by reacting with Line 138 to 142 during each tick of the game loop to track the movement of the ball. Hence, naturally, as you slowly tweak the value of COMPUTER_INTELLIGENCE from 0.4 to 0.5 to 0.6, and so on, you should be able to see the AI of the computer improving gradually. All these, with VERY minimal code changes!

Step 5 - Handle Player, Computer, Ball Movements & Positions

The next few lines of code handles the movement of the player, computer and the ball. Lines 149 to 158 handles the movement of the player's block. Take note of line 151, which takes into account the upper ceiling which the player's block cannot move into. Hence, movement is only allowed when the player's vertical position is lower than the PLAYER_UPPER_BOUND constant, which we can set in the constants file. Likewise, line 156 handles the check to make sure that the player's block doesn't move into the floor.

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//******************
//Handle Game Logic
//******************
//Handle new Player Position
if (moveY > 0)
{
    if (player.y + C.PLAYER_SPEED <= C.PLAYER_UPPER_BOUND)
        player.y += C.PLAYER_SPEED;
}
else if (moveY < 0)
{
    if (player.y - C.PLAYER_SPEED > C.PLAYER_LOWER_BOUND)
        player.y -= C.PLAYER_SPEED;	
}
 
//Handle new Player 2 Position
if (moveY2 > 0)
{
    if (computer.y + C.COMPUTER_SPEED <= C.PLAYER_UPPER_BOUND)
        computer.y += C.COMPUTER_SPEED;
}
else if (moveY2 < 0)
{
    if (computer.y - C.COMPUTER_SPEED > C.PLAYER_LOWER_BOUND)
        computer.y -= C.COMPUTER_SPEED;	
}
 
//Handle new Ball Position
if (ballVelX < 0)
{
    ball.x -= C.BALL_SPEED +  Math.floor(Math.random()*C.SPEED_MOD);
}
else if (ballVelX > 0)
{
    ball.x += C.BALL_SPEED +  Math.floor(Math.random()*C.SPEED_MOD);
}
 
if (ballVelY < 0)
{
    ball.y -= C.BALL_SPEED +  Math.floor(Math.random()*C.SPEED_MOD);
}
else if (ballVelY > 0)
{
    ball.y += C.BALL_SPEED +  Math.floor(Math.random()*C.SPEED_MOD);
}

In lines 172 to 189, you see that I move the ball according to the values of ballVelX and ballVelY. There is a little inaccuracy here that I introduced for the ease of coding. In a nutshell, when a ball is moving in the diagonal direction, it ends up moving faster than it would be moving in just the horizontal or vertical directions. This is because we do a check for horizontal movement, and advance it by BALL_SPEED. Then we check for vertical movement, and then advance it by BALL_SPEED again. A more accurate way would be to check for diagonal movement, and then advance it by cos(45 degrees), which gives us 0.707 thereabout.

If you're confused, that's the reason why I didn't want to introduce this yet. =D In any case, we don't aim for perfect physics in games; that's better left for simulation programs. We just need efficient and believable physics here.

Another random element that is added here is Math.floor(Math.random() * C.SPEED_MOD); What it does is to add a random factor into the movement so that the ball does not end up at the same spot each time. Math.floor does a round down regardless of the value, so since we set SPEED_MOD to be 5, we add in a random value of 0 to 4 each time.

Step 6 - Checking for Collisions

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//Check for collision
//---------------------
//Top and bottom walls
if (ball.y <= topWall.y + topWall.height)
{
    ballVelY = 1;
}
else if (ball.y >= bottomWall.y)
{
    ballVelY = -1;
}
 
//Player and Computer collisions
if (ball.x <= player.x)
{
    if (Math.abs(ball.y - player.y) <= player.height/2)
    {
        ballVelX = 1;
    }
}
else if (ball.x >= computer.x)
{
    if (Math.abs(ball.y - computer.y) <= computer.height/2)
    {
        ballVelX = -1;
    }
}

The codes above do the checking for the collisions that go on in the game. If you look at line 194 shown above, the ball's y position is checked against the lower part of the ceiling wall. The figure below should give you a better idea.

wallpoints

Open up the Wall movieclip in the flash file if you need a closer look. To not let the ball fly away from the stage, we should turn the ball around (by swapping its ballVelY from -1 to 1) once it reaches the bottom of the top wall. That is what line 194 is checking for.

In line 198, we do not need to add the height of the wall to it because the registration point is already at the top of the bottom wall.

Lines 203 to 210 handle the collision between the ball and the player's block. We first check if the horizontal position of the ball is less than or equal to the horiztonal position of the player's block. Line 206 then goes on to check if the ball is inside the player block's upper and lower y positions. If both conditions are fulfilled, it can only mean that the ball has collided with the player's block, and we should send the ball flying back to the right, by setting ballVelX to be a positive 1.

Lines 211 to 217 does the same with the computer's block.

Step 7 - Taking Score

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
            //Check for Winning
            //---------------------
            if (ball.x < C.PLAYER_LOSE)
            {
                resetGame();
                computerScore += 1;
            }
            else if (ball.x > C.COMPUTER_LOSE)
            {
                resetGame();
                playerScore += 1;				
            }
            
            //******************
            //Handle Display
            //******************
            //Display new Score
            txtScorePlayer.text = String(playerScore);
            txtScoreComputer.text = String(computerScore);
        }	
         
        private function resetGame():void
        {
            ball.x = C.BALL_START_X;
            ball.y = C.BALL_START_Y;
            player.x = C.PLAYER_START_X;
            player.y = C.PLAYER_START_Y;        
            moveY = 0;
            moveY2 = 0;
            ballVelX = -1;
            ballVelY = 1;
        }
     }
}

To check who should get a score, we simply check if the ball has passed the screen on the left (check done on line 221). If so, the computer would get a point. If the ball passed the screen on the right (check done on line 226), the player would get a point.

The resetGame function is called upon to reset the entire game state to its original. Whenever a score is made, this function will be called.

The Game

And here you have it ... the working game! Hope you enjoyed learning how to make Pong. You have earned the right to call yourself a game developer now! =)

Download the Game Files

The files you need to create this game can be downloaded from here.

How To Play

Objective: Hit the ball past the computer's paddle.

Controls: Press W key to move Up and S key to move Down.


Content on this page requires a newer version of Adobe Flash Player.

Get Adobe Flash player


Flash Resources
Preloader FPS Display Sounds & Music
Keycodes Name Generator
Game Development Resources
Sprite Sheets


Posted by Joseph

on 2014-12-04 23:15:05

Phone is a totally different ball game. :/


Posted by lona

on 2014-09-16 06:45:29

I made this available for my android device. How should i change the code of the bullet and the movements of the player...because with the keyboard event they dont move on my phone :/. pls help


Posted by Gabby

on 2014-04-17 01:43:15

I'm getting an error 1120 in reference to c.
Can any one help


Posted by Spencer

on 2013-05-18 08:29:50

Hi
I am a student in highschool and I am creating a game for class and I am confused with this. I have CS6 and need help. I would really be grateful for some help.


Posted by Joseph

on 2013-01-29 21:40:09

Hi Max,

If you are compiling the files in CS5 or later, you need to embed the fonts to make it show up if you are using anything other than Static Text Field.

One quick workaround is to set the text field as "Use Device Fonts"


Posted by Max Miles

on 2012-12-27 08:09:59

The score not showing up is, I think, a problem of compatibility with Flash 9. If you open up a newer version of flash you can try this:

1-Go to "Publish Seettings..." in the File dropdown menu (shortcut is Ctrl + Shift + F12)
2-Change the "Player" field from "Flash Player 9" to a higher version. "Flash Player 10 & 10.1" works fine
3-Select each text field and right below the instance name change from "Classic Text" to "TLF Text"

This worked for me. Mind you, I'm no flash expert (or I wouldn't be browsing this website) so I'm not sure if my solution is airtight. So far I did not have any problems with it.

Also, nice tutorials! They're really helping me learn how to use flash, and I'm a complete newbie, so good job on making simple and accessible tutorials.


Posted by Joseph

on 2012-12-19 23:42:07

Just make sure when you open it up in CS5 and later, there may be an issue with font embedding. Just use the "Use Device Fonts" for the textfield and it should show up.


Posted by sahil

on 2012-10-23 17:20:43

please tell me how you make these games in flash cs4/cs5 it's awesome.I have some knowledge about flash basic not in coding


Posted by ATF

on 2011-09-11 22:48:32

The score doesn't work in the download FLA


Posted by Joseph

on 2010-12-31 23:28:57

Hi, can let me know what's the problem that you faced?


Posted by Jj

on 2010-12-28 12:46:55

The FLA doesn't seem to work. Just to let you know.


Flash Tutorial Links:
Play Games: HTML5 Tutorials:
gaming tools download on app store now!
Home | About Us | Contact Us
Powered by Make Flash Games. All Rights Reserved.
By Joseph Tan