1. Lesson Overview
| Lesson Title |
Pac-Man-Style Maze Game |
| Course |
Video Game Design / Game Programming |
| Game Engine |
GameMaker |
| Language |
GameMaker Language (GML) |
| Difficulty |
Intermediate |
| Estimated Time |
5–7 class periods (45–55 minutes each) |
| Project Name |
PX_lastname_PacMan |
| Total Points |
100 |
Design and develop an original maze game. Navigate corridors, collect pellets for points, avoid moving enemies, and collect special power-ups that temporarily make enemies vulnerable. Include a start screen, lives, score, and win/loss conditions.
Originality: Create your own maze, characters, colors, and other artwork rather than copying an existing commercial game's assets.
4. Step-by-Step Activities
Activity 1: Create the Project Very Easy
- Open GameMaker and create a new GML Code project.
- Name it
PX_lastname_PacMan (replace PX and lastname with your own information).
- Create
rm_game and set the room to 640 × 480 pixels.
- Set the Room Editor grid to 32 × 32 pixels.
- Create
spr_player, obj_player, and assign the sprite to the object.
- Place one player instance in the room.
Checkpoint 1: Show your teacher your project with the player visible in the game room.
Activity 2: Design the Maze Easy
- Create
spr_wall and obj_wall; assign the sprite.
- Place wall objects in the Room Editor to form outer boundaries and internal corridors.
- Include at least four intersections and two dead ends.
- Leave room for pellets, power-ups, and at least three enemy spawn locations.
- Keep paths wide enough for the player and enemies.
Checkpoint 2: Show your teacher a complete maze with corridors, walls, and a player starting location.
Activity 3: Player Movement Easy–Intermediate
The arrow keys move the player in four directions. Before changing position, check whether a wall blocks the move.
obj_player — Create Event
move_speed = 4;
start_x = x;
start_y = y;
obj_player — Step Event
var h = 0;
var v = 0;
// Horizontal movement
if (keyboard_check(vk_right)) {
h = move_speed;
} else if (keyboard_check(vk_left)) {
h = -move_speed;
}
// Vertical movement
if (keyboard_check(vk_down)) {
v = move_speed;
} else if (keyboard_check(vk_up)) {
v = -move_speed;
}
// Only move if the path is clear
if (!place_meeting(x + h, y, obj_wall)) {
x += h;
}
if (!place_meeting(x, y + v, obj_wall)) {
y += v;
}
Testing: Try moving toward walls, around corners, and through intersections. Use properly aligned sprites and collision masks.
Checkpoint 3: Demonstrate four-directional movement without passing through walls.
Activity 4: Collectible Pellets Easy–Intermediate
Create regular pellets that award 10 points each. Place one obj_game instance in rm_game.
obj_game — Create Event
global.score = 0;
global.lives = 3;
global.power_active = false;
global.power_timer = 0;
global.game_finished = false;
global.invulnerable_timer = 0;
obj_pellet — Collision Event with obj_player
global.score += 10;
instance_destroy();
Place at least 20 instances of obj_pellet throughout the maze.
Checkpoint 4: Demonstrate that pellets disappear when collected and the score increases by 10.
Activity 5: Moving Enemies Intermediate
Place at least three obj_enemy instances in the maze. Start with simple random-direction movement.
obj_enemy — Create Event
move_speed = 2;
move_dir = irandom(3);
start_x = x;
start_y = y;
obj_enemy — Step Event
var dx = 0;
var dy = 0;
switch (move_dir) {
case 0: dx = move_speed; break;
case 1: dx = -move_speed; break;
case 2: dy = move_speed; break;
case 3: dy = -move_speed; break;
}
if (place_meeting(x + dx, y + dy, obj_wall)) {
// Choose a new direction when a wall blocks movement
move_dir = irandom(3);
} else {
x += dx;
y += dy;
}
Required improvement: The starter code can make enemies repeatedly attempt blocked directions or fail to turn at intersections. Test it and extend it so enemies select legal directions at intersections and do not become trapped. Advanced students can program an enemy that follows the player.
Checkpoint 5: Show three enemies moving automatically through the maze without passing through walls.
Activity 6: Power-Ups Intermediate
Special pellets award 50 points and temporarily make enemies vulnerable.
obj_powerup — Collision Event with obj_player
global.score += 50;
global.power_active = true;
global.power_timer = room_speed * 8;
instance_destroy();
obj_game — Step Event (add to this event)
if (global.power_timer > 0) {
global.power_timer -= 1;
if (global.power_timer <= 0) {
global.power_timer = 0;
global.power_active = false;
}
}
if (global.invulnerable_timer > 0) {
global.invulnerable_timer -= 1;
}
obj_enemy — Step Event (add to existing movement code)
if (global.power_active) {
image_blend = c_blue;
} else {
image_blend = c_white;
}
Checkpoint 6: Demonstrate a power-up activating, changing enemy appearance, and expiring after about eight seconds.
Activity 7: Enemy Collisions and Lives Intermediate
Touching an enemy while powered up defeats that enemy for 200 points. Otherwise, the player loses one life and receives temporary immunity to prevent immediate repeat damage.
obj_enemy — Collision Event with obj_player
if (global.game_finished) {
exit;
}
if (global.power_active) {
global.score += 200;
x = start_x;
y = start_y;
} else if (global.invulnerable_timer <= 0) {
global.lives -= 1;
global.invulnerable_timer = room_speed * 2;
if (global.lives <= 0) {
global.game_finished = true;
room_goto(rm_gameover);
} else {
other.x = other.start_x;
other.y = other.start_y;
}
}
Important: Keep the start_x and start_y assignments in each character's Create Event. Consider temporary enemy immunity after being defeated so an overlapping enemy cannot award the same points every step.
Checkpoint 7: Demonstrate losing a life from a normal enemy and defeating an enemy while powered up.
Activity 8: Score and Lives Display Easy
obj_game — Draw GUI Event
draw_set_color(c_white);
draw_text(16, 16, "Score: " + string(global.score));
draw_text(16, 40, "Lives: " + string(global.lives));
if (global.power_active) {
draw_text(16, 64, "POWER-UP ACTIVE!");
}
Make the on-screen display readable without blocking gameplay.
Checkpoint 8: Show the score, lives, and power-up indicator updating during play.
Activity 9: Win, Game Over, and Restart Intermediate
Add the following logic to the existing obj_game Step Event after the timer code.
if (!global.game_finished) {
if (instance_number(obj_pellet) == 0) {
global.game_finished = true;
room_goto(rm_win);
}
}
Create rm_win and rm_gameover. Display a message and final score in each room. Provide a restart object or button that calls game_restart(); from a keyboard or mouse event when the player requests it.
Menu: Create rm_menu with game title and start instructions; use a key or button to enter rm_game. Keep room order and object initialization consistent when restarting.
Checkpoint 9: Demonstrate victory, game over, and restarting from both ending screens.
Have students demonstrate each checkpoint before moving to the next activity. The sample code is a starting point, not a complete preassembled game. Students must create and assign sprites, place object instances, configure collision masks and events, and build the menu and end screens.
Implementation considerations: Keep the game controller in the gameplay room; add timer logic and victory logic to the same Step Event rather than replacing one with the other. Test enemy behavior in narrow corridors and at intersections. If using one global score across rooms, ensure the ending screens read it before starting a new game. Have students verify that repeated enemy overlaps do not generate accidental repeated points.