In this lesson, you will build a simple version of the classic Pong video game using GameMaker.
You will create two paddles, a moving ball, collision detection, scoring, and a system that resets the ball after a player scores.
By the end of this lesson, you should be able to:
| Requirement | Description |
|---|---|
| Left Paddle | Controlled by Player 1. |
| Right Paddle | Controlled by Player 2. |
| Ball | Moves continuously across the screen. |
| Paddle Movement | Paddles move up and down. |
| Wall Bounce | The ball bounces off the top and bottom walls. |
| Paddle Bounce | The ball changes direction when it hits a paddle. |
| Scoring | A player earns a point when the opponent misses. |
| Score Display | The score for both players appears on screen. |
| Reset | The ball returns to the center after a point. |
Create a new GameMaker project named:
Name the project:
PX_lastname_PongGame
Create these assets:
spr_paddle
spr_ball
obj_paddle_left
obj_paddle_right
obj_ball
obj_wall_top
obj_wall_bottom
obj_game
rm_pong
Create a sprite named:
spr_paddle
Make it a simple vertical rectangle.
Example size:
Width: 20
Height: 100
Set the origin to:
Middle Center
Create a sprite named:
spr_ball
Make it a small square or circle.
Example size:
Width: 24
Height: 24
Set the origin to:
Middle Center
Create:
obj_paddle_left
Assign:
spr_paddle
Add a Create Event:
move_speed = 6;
Add a Step Event:
if (keyboard_check(ord("W")))
{
y -= move_speed;
}
if (keyboard_check(ord("S")))
{
y += move_speed;
}
Add this code to the bottom of the left paddle's Step Event:
y = clamp(
y,
sprite_height / 2,
room_height - sprite_height / 2
);
The clamp() function prevents the paddle from
moving outside the room.
Create:
obj_paddle_right
Assign:
spr_paddle
Add a Create Event:
move_speed = 6;
Add a Step Event:
if (keyboard_check(vk_up))
{
y -= move_speed;
}
if (keyboard_check(vk_down))
{
y += move_speed;
}
y = clamp(
y,
sprite_height / 2,
room_height - sprite_height / 2
);
Create:
obj_ball
Assign:
spr_ball
Add a Create Event:
ball_speed = 6;
direction = choose(30, 150, 210, 330);
speed = ball_speed;
The choose() function randomly selects one of
several starting directions.
Create:
obj_wall_top
obj_wall_bottom
Create simple rectangle sprites for the walls or use another collision method.
Place one wall across the top of the room and one across the bottom.
In obj_ball, add a Collision Event with:
obj_wall_top
Enter:
vspeed = abs(vspeed);
Add another Collision Event with:
obj_wall_bottom
Enter:
vspeed = -abs(vspeed);
In obj_ball, add a Collision Event with:
obj_paddle_left
Enter:
hspeed = abs(hspeed);
This makes the ball move to the right after hitting the left paddle.
Add a Collision Event with:
obj_paddle_right
Enter:
hspeed = -abs(hspeed);
This makes the ball move to the left after hitting the right paddle.
You can make Pong more interesting by changing the ball's vertical speed depending on where it hits the paddle.
var difference = y - other.y;
hspeed = abs(hspeed);
vspeed += difference * 0.05;
var difference = y - other.y;
hspeed = -abs(hspeed);
vspeed += difference * 0.05;
Hitting near the top or bottom of a paddle changes the angle of the ball.
Create an object named:
obj_game
Add a Create Event:
global.left_score = 0;
global.right_score = 0;
Place one instance of obj_game inside the room.
Add a Step Event to obj_ball.
if (x < 0)
{
global.right_score += 1;
x = room_width / 2;
y = room_height / 2;
direction = choose(30, 150, 210, 330);
speed = ball_speed;
}
if (x > room_width)
{
global.left_score += 1;
x = room_width / 2;
y = room_height / 2;
direction = choose(30, 150, 210, 330);
speed = ball_speed;
}
If the left player misses, the right player receives a point.
If the right player misses, the left player receives a point.
Add a Draw GUI Event to obj_game.
draw_set_halign(fa_center);
draw_text(
display_get_gui_width() / 4,
30,
string(global.left_score)
);
draw_text(
display_get_gui_width() * 3 / 4,
30,
string(global.right_score)
);
The score for both players should now appear near the top of the screen.
Open:
rm_pong
Place the following objects:
obj_paddle_left
obj_paddle_right
obj_ball
obj_wall_top
obj_wall_bottom
obj_game
Arrange them approximately like this:
+------------------------------------------+
| |
| | | |
| | BALL | |
| | | |
| |
+------------------------------------------+
Player 1 Player 2
Run the game and test the controls.
Demonstrate that:
Allow one player to intentionally miss the ball.
Verify that:
Demonstrate that both Player 1 and Player 2 can score.
Make the ball move slightly faster every time it hits a paddle.
speed += 0.25;
Limit the maximum speed:
speed = min(speed, 12);
Create:
winning_score = 10;
Then check the scores:
if (global.left_score >= winning_score)
{
show_message("Player 1 Wins!");
game_restart();
}
if (global.right_score >= winning_score)
{
show_message("Player 2 Wins!");
game_restart();
}
Add this code to the Draw GUI Event of obj_game:
draw_line(
display_get_gui_width() / 2,
0,
display_get_gui_width() / 2,
display_get_gui_height()
);
Add sound effects for:
Possible sound asset names:
snd_paddle
snd_wall
snd_score
Play a sound using:
audio_play_sound(snd_paddle, 1, false);
Replace the Player 2 controls with simple computer movement.
if (obj_ball.y < y)
{
y -= move_speed;
}
if (obj_ball.y > y)
{
y += move_speed;
}
The computer-controlled paddle will attempt to follow the ball.
hspeed and vspeed?
After completing the basic Pong game, try adding one or more advanced features:
Play the completed game and demonstrate paddle movement, bouncing, collision detection, scoring, and ball reset.