🎯 My First GameMaker Game · Episode 1 of 5 · See All Episodes
🏓 Episode 1 · Beginner · No Experience Needed

GameMaker Go!
Pong in GML

Learn GameMaker Studio the right way: objects, events and GML code. Build Pong with two paddles, a bouncing ball, scoring and an AI, the engine that shipped Undertale, in your hands.

👶 Ages 10+ ⏱️ ~1.5 Hours 🎯 GameMaker ✓ Free
🧩 Objects & instances Events 📜 GML basics 🏓 Movement 💥 Collisions 🤖 AI paddle
0 XP
Level 1
🔥0
Your Progress 0 / 6 steps
1
🧩
Project, Room & First Object
GameMaker’s building blocks: sprites, objects, rooms
Active
🎯
Goal for this step

Create the project and understand GameMaker’s core concepts.

  • 1Install GameMaker (gamemaker.io), the free tier covers this whole series. New Blank project, name it Pong.
  • 2The three building blocks: Sprites (images), Objects (things with behaviour), Rooms (levels containing instances of objects).
  • 3Make a sprite: spr_paddle, 16×96, filled white (the built-in editor is fine).
  • 4Make an object: obj_paddle, assign spr_paddle.
  • 5Open Room1, set it 800×500 with a dark background, drag obj_paddle in near the left edge. Run (F5), your paddle exists in a window!
👨‍👧
Parent note: GameMaker’s free licence is enough for the entire series; it only limits some export platforms. GML is a friendly first "real" language, Undertale and Chicory shipped with it.
✏️
Fill in the Blanks
+15 XP
GameMaker’s three core assets are sprites, and rooms. A copy of an object placed in a room is called an . The run key is .
🧠
Knowledge Check
+15 XP
The difference between an object and an instance is…
ASpelling
BThe object is the blueprint; instances are copies living in the room, one obj_paddle, two paddles
CObjects are bigger
2
Events & Your First GML
Step events and keyboard_check
Locked
🎯
Goal for this step

Move the paddle with GML code in the Step event.

  • 1Objects respond to Events: Create (born), Step (every frame, 60/s), Draw, collisions and more.
  • 2In obj_paddle: Add Event → Step, and write the movement code below.
  • 3keyboard_check is true while held; y is the built-in vertical position; clamp keeps it on screen in one call!
  • 4GML reads like simple English-maths. Run it and slide the paddle.
obj_paddle · Step Event
// move with W and S
if (keyboard_check(ord("W"))) y -= 6;
if (keyboard_check(ord("S"))) y += 6;

// stay on screen (48 = half the paddle height)
y = clamp(y, 48, room_height - 48);
⌨️
Code Challenge
+20 XP
Complete the paddle movement and clamp:
obj_paddle · Step
if (keyboard_check(ord("W"))) y  6;
if (keyboard_check(ord("S"))) y += 6;
y = (y, 48, room_height - );
💡 Hint: W moves up (y shrinks). GML has a one-call min/max limiter. The margins are half the paddle height at each end.
🧠
Knowledge Check
+15 XP
The Step event runs…
AOnce when the game starts
BEvery frame, ~60 times per second, it IS the game loop, per object
COnly when a key is pressed
3
The Ball: hspeed & vspeed
Built-in motion and wall bouncing
Locked
🎯
Goal for this step

Launch a ball with built-in speed variables and bounce it.

  • 1Make spr_ball (16×16 white square) and obj_ball.
  • 2GameMaker objects have motion BUILT IN: set hspeed and vspeed in the Create event and the instance moves itself, no position code needed!
  • 3Bounce off top/bottom in Step: if the ball is past an edge, flip vspeed.
  • 4choose(-4, 4) is GML’s coin flip, a random serve direction each run.
  • 5Drop obj_ball in the room centre and run: it flies and bounces.
obj_ball
/// Create Event
hspeed = choose(-4, 4);
vspeed = choose(-3, 3);

/// Step Event
if (y < 8 || y > room_height - 8) {
    vspeed = -vspeed;
}
✏️
Fill in the Blanks
+15 XP
GameMaker instances move themselves when and vspeed are set. A random pick between listed values uses (-4, 4).
🧠
Knowledge Check
+15 XP
Why does obj_ball move with NO movement code in Step?
AA bug
Bhspeed/vspeed are engine-integrated: GameMaker applies them to x/y automatically every frame
CThe room moves instead
4
💥
Collision Events & Spin
The visual event system meets rebound maths
Locked
🎯
Goal for this step

Bounce the ball off paddles with position-based spin.

  • 1GameMaker’s superpower: add a Collision event to obj_ball targeting obj_paddle, the code runs exactly when they touch. No manual overlap tests!
  • 2In it: reverse and slightly grow hspeed, and set vspeed from WHERE the ball hit (distance from paddle centre, the spin trick works in every engine).
  • 3other refers to the paddle instance in the collision, other.y is ITS position.
  • 4Make the second paddle: a child object or a duplicate with Up/Down keys.
obj_ball · Collision with obj_paddle
// reverse and speed up slightly
hspeed = -hspeed * 1.05;

// spin: hit position steers the rebound
vspeed = (y - other.y) / 12;

// never fully flat
if (vspeed == 0) vspeed = 1;
⌨️
Code Challenge
+20 XP
Add spin from the hit position:
Collision event
hspeed = -hspeed * ;
vspeed = (y - .y) / 12;
💡 Hint: The rally grows 5% per hit; the special keyword referring to the touched instance provides its y.
🧠
Knowledge Check
+15 XP
In a collision event, other means…
AAny random object
BThe specific instance you collided with, here, exactly which paddle got hit
CThe previous ball
5
🔢
Scoring & the Controller Object
Global variables and an invisible manager
Locked
🎯
Goal for this step

Track score with a controller object and serve after points.

  • 1Create obj_game, no sprite! Invisible manager objects are a core GameMaker pattern.
  • 2Its Create event: global.score_l = 0; global.score_r = 0;, global variables reachable from any object.
  • 3In obj_ball’s Step: ball past the left edge → global.score_r++, reset ball to centre and re-serve; mirror for the right.
  • 4obj_game gets a Draw GUI event drawing both scores big and centred.
  • 5Drop obj_game in the room. Score away!
obj_game
/// Create Event
global.score_l = 0;
global.score_r = 0;

/// Draw GUI Event
draw_set_halign(fa_center);
draw_text_transformed(340, 30, string(global.score_l), 3, 3, 0);
draw_text_transformed(460, 30, string(global.score_r), 3, 3, 0);
✏️
Fill in the Blanks
+15 XP
Variables reachable from every object are prefixed . An invisible manager object like obj_game is a classic GameMaker pattern.
🧠
Knowledge Check
+15 XP
Why put score in a controller object instead of inside the ball?
ABalls cannot count
BThe ball resets/respawns, data that must OUTLIVE gameplay objects belongs in a persistent manager
CGUI events need it
6
🤖
AI & Game Over
A beatable computer and first-to-7
Locked
🎯
Goal for this step

Finish with an AI opponent and a win screen.

  • 1obj_paddle_ai Step: chase the ball with a dead zone and a capped speed (slower than yours, flaws make fun, the universal AI lesson).
  • 2instance_exists guards against the serve gap.
  • 3obj_game Step: first to 7 → set global.winner and go to a game-over state (a room_goto to rm_gameover is the easiest GameMaker way!).
  • 4rm_gameover: an object drawing the winner + "press R" (keyboard_check_pressed(ord("R")) → room_goto(rm_game), reset scores).
  • 5Ship it. GameMaker made all the boring parts easy, that is why devs love it.
obj_paddle_ai · Step
if (instance_exists(obj_ball)) {
    var gap = obj_ball.y - y;
    if (abs(gap) > 12) {
        y += sign(gap) * 5;     // capped chase speed
    }
    y = clamp(y, 48, room_height - 48);
}
⌨️
Code Challenge
+20 XP
Write the dead-zoned AI chase:
obj_paddle_ai · Step
var gap = obj_ball.y - y;
if ((gap) > 12) {
    y += (gap) * 5;
}
💡 Hint: One function gives the distance size, the other gives just its direction (-1 or 1).
🧠
Knowledge Check
+15 XP
sign(gap) returns…
AThe gap squared
B-1, 0 or 1, pure direction, letting you cap chase speed at exactly 5
CThe paddle sprite
🎉🏆🎮✨🎉
Workshop Complete!
Objects, events and GML, the GameMaker way of thinking, learned on the perfect first game. Episode 2: gravity and platforms!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
▶ Episode 2: Simple Platformer →
⭐ View My Progress & Certificates

This workshop was free and took many hours to build. If it helped you learn something new, consider supporting the project.

☕ Support on Ko-fi