Students build a complete dodging game in three milestones, using a timer, random positions, velocity, overlaps, lives, score and the high score.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict, Run, Investigate 12 min · Milestone 1 10 min · Milestone 2 12 min · Milestone 3 15 min · Road crossing 10 min
This lesson uses everything from the course, with only two new blocks: auto destroy (the set flag block in Sprites removes a sprite once it leaves the screen) and high score (in Info: the best score so far in this browser, shown on the game over screen by itself). The game: a timer (on game update every 1000 ms) makes a rock at the right edge, and a negative vx carries it left; an overlap event between Player and Enemy destroys the rock and takes a life; a second timer adds 1 to the score every second. The milestones fade the help: Milestone 1 gives nearly all the code, Milestone 2 an outline, Milestone 3 only goals. Play it yourself first. The core is Milestones 1 and 2; Milestone 3 and the road crossing finish the lesson for most students.
On the slides at these points. Students can do the whole lesson on their own; these are for the room. In the deck, the Run, Modify and Make slides have the live playground in them (the tutorial link is the backup), and the notes above are in each slide's speaker notes.
On the board, list what the finished game needs: random rocks, lives, a hit, a score, a high score. Next to each, write the block or event that does it.
This list is the plan for the three milestones.
Write your high score on the board. Swap games and suggest one change that makes the next pair's game fairer or harder.
Combining a timer, velocity and overlaps in one game. Point them to the milestone they're on and ask them to get that part playing first.
| What you will see | A question to ask | The fix |
|---|---|---|
| All lives vanish at the first hit. | What happens to the rock after it touches the ship? | Destroy otherSprite inside the overlap event, so it touches only once. |
| Rocks pass through the ship and nothing happens. | Which kinds does the overlap event name, and which kinds are the ship and the rock? | The ship must be a Player and the rock an Enemy, matching the event. |
| All rocks still come along one line. | Where is pick random? | It must be in the y of set position, inside the timer, so each rock gets a new number. |
| The score goes up very fast. | Which block is the score in? | Use on game update every 1000 ms, not on game update (which runs every frame). |
One possible solution for each task. Other correct programs are fine.

let rock: Sprite = null
scene.setBackgroundColor(15)
let ship = sprites.create(img`
8 8 . . . . . .
8 9 9 9 9 . . .
8 9 1 1 9 9 9 9
8 9 9 9 9 . . .
8 8 . . . . . .
`, SpriteKind.Player)
ship.setPosition(20, 60)
controller.moveSprite(ship, 0, 100)
ship.setStayInScreen(true)
game.onUpdateInterval(1000, function () {
rock = sprites.create(img`
. e e e .
e e d e e
e d e e e
. e e e .
`, SpriteKind.Enemy)
rock.setPosition(160, randint(10, 110))
rock.vx = -50
rock.setFlag(SpriteFlag.AutoDestroy, true)
})

sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
info.changeLifeBy(-1)
})
let rock: Sprite = null
scene.setBackgroundColor(15)
let ship = sprites.create(img`
8 8 . . . . . .
8 9 9 9 9 . . .
8 9 1 1 9 9 9 9
8 9 9 9 9 . . .
8 8 . . . . . .
`, SpriteKind.Player)
ship.setPosition(20, 60)
controller.moveSprite(ship, 0, 100)
ship.setStayInScreen(true)
info.setLife(3)
game.onUpdateInterval(1000, function () {
rock = sprites.create(img`
. e e e .
e e d e e
e d e e e
. e e e .
`, SpriteKind.Enemy)
rock.setPosition(160, randint(10, 110))
rock.vx = -50
rock.setFlag(SpriteFlag.AutoDestroy, true)
})

sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
info.changeLifeBy(-1)
})
let rock: Sprite = null
scene.setBackgroundColor(15)
let ship = sprites.create(img`
8 8 . . . . . .
8 9 9 9 9 . . .
8 9 1 1 9 9 9 9
8 9 9 9 9 . . .
8 8 . . . . . .
`, SpriteKind.Player)
ship.setPosition(20, 60)
controller.moveSprite(ship, 0, 100)
ship.setStayInScreen(true)
info.setLife(3)
game.onUpdateInterval(1000, function () {
rock = sprites.create(img`
. e e e .
e e d e e
e d e e e
. e e e .
`, SpriteKind.Enemy)
rock.setPosition(160, randint(10, 110))
rock.vx = -50
rock.setFlag(SpriteFlag.AutoDestroy, true)
})
game.onUpdateInterval(1000, function () {
info.changeScoreBy(1)
if (info.score() > info.highScore()) {
scene.setBackgroundColor(8)
}
})
Open task: any program that does what the step asks.
Stretch: Make the rocks faster as the score grows: set rock vx to 0 - (50 + score), so a long game gets harder by itself.
Support: Pair students for Milestone 3: one reads the goals aloud while the other builds. A student who finishes Milestone 2 has a complete, playable game.
Why must the rock be destroyed inside the overlap event?
The overlap event runs every frame the two sprites touch. Destroying the rock makes it touch once, so a hit costs one life, not all of them.
Course complete. Next: Arcade advanced skills (functions, gravity, levels and power-ups). For more practice building whole games, MakeCode's Beginner Skillmap (arcade.makecode.com/skillmaps) uses the same blocks. Class ideas: a class high-score board on the whiteboard; swap games with a partner and suggest one change that makes it fairer or harder.