Read a whole game, find the blocks that do each job, and change just the part you need.
Game makers spend more time reading code than writing it: to fix a bug or add a feature, you first find the blocks that do that job.
This is a whole game: Garden defender. Bugs fall on the garden; you move the gardener along the bottom and spray them with water. Every block in it is something you have already learned. Today you read it, find the blocks that do each job, and change the game without breaking it.
Make your prediction first. Help opens once you've locked it in.

let bug: Sprite = null
scene.setBackgroundColor(13)
info.setLife(3)
let gardener = sprites.create(img`
. 4 4 .
4 4 4 4
. 8 8 .
. 8 8 .
`, SpriteKind.Player)
gardener.setPosition(80, 110)
controller.moveSprite(gardener, 100, 0)
gardener.setStayInScreen(true)
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
let water = sprites.createProjectileFromSprite(img`
. 9 .
9 9 9
. 9 .
`, gardener, 0, -100)
})
game.onUpdateInterval(800, function () {
bug = sprites.create(img`
. 7 7 .
7 f f 7
7 7 7 7
. 7 7 .
`, SpriteKind.Enemy)
bug.setPosition(randint(10, 150), 0)
bug.vy = 30
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
sprite.destroy()
otherSprite.destroy()
info.changeScoreBy(1)
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
info.changeLifeBy(-1)
})
game.onUpdate(function () {
if (info.score() >= 10) {
scene.setBackgroundColor(7)
}
})
Read the blocks before you play.
Move with the left and right arrows. Fire with A (space).

let bug: Sprite = null
scene.setBackgroundColor(13)
info.setLife(3)
let gardener = sprites.create(img`
. 4 4 .
4 4 4 4
. 8 8 .
. 8 8 .
`, SpriteKind.Player)
gardener.setPosition(80, 110)
controller.moveSprite(gardener, 100, 0)
gardener.setStayInScreen(true)
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
let water = sprites.createProjectileFromSprite(img`
. 9 .
9 9 9
. 9 .
`, gardener, 0, -100)
})
game.onUpdateInterval(800, function () {
bug = sprites.create(img`
. 7 7 .
7 f f 7
7 7 7 7
. 7 7 .
`, SpriteKind.Enemy)
bug.setPosition(randint(10, 150), 0)
bug.vy = 30
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
sprite.destroy()
otherSprite.destroy()
info.changeScoreBy(1)
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
info.changeLifeBy(-1)
})
game.onUpdate(function () {
if (info.score() >= 10) {
scene.setBackgroundColor(7)
}
})

let bug: Sprite = null
scene.setBackgroundColor(13)
info.setLife(3)
let gardener = sprites.create(img`
. 4 4 .
4 4 4 4
. 8 8 .
. 8 8 .
`, SpriteKind.Player)
gardener.setPosition(80, 110)
controller.moveSprite(gardener, 100, 0)
gardener.setStayInScreen(true)
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
let water = sprites.createProjectileFromSprite(img`
. 9 .
9 9 9
. 9 .
`, gardener, 0, -100)
})
game.onUpdateInterval(800, function () {
bug = sprites.create(img`
. 7 7 .
7 f f 7
7 7 7 7
. 7 7 .
`, SpriteKind.Enemy)
bug.setPosition(randint(10, 150), 0)
bug.vy = 30
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
sprite.destroy()
otherSprite.destroy()
info.changeScoreBy(1)
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
info.changeLifeBy(-1)
})
game.onUpdate(function () {
if (info.score() >= 10) {
scene.setBackgroundColor(7)
}
})
Match each job with the blocks that do it.
The game starts with 3 lives and a score of 0. Fill in the score and lives after each thing happens.
| what happens | score | lives |
|---|---|---|
| (start) | 0 | 3 |
| water hits a bug | ||
| a bug lands on the gardener | ||
| a bug falls past, off the bottom |
Make the bugs come twice as often.
The timer's number sets how often. Half of 800 is 400.
Make a bug that lands on the gardener cost 2 lives.
Find the event for a bug landing on the gardener. Change the -1.
Make the bugs come twice as often.
This ticks by itself when your blocks do what is asked.
Make a bug that lands on the gardener cost 2 lives.
This ticks by itself when your blocks do what is asked.
Add one new job to the game: an apple falls every few seconds, and catching it gives the gardener a life. Find where each part belongs: making it, moving it, and what a catch means.
A second timer, on game update every 3000 ms: an apple of kind Food at a random x at the top, falling with vy.
A new overlap: Player and Food. Inside: change life by 1, destroy otherSprite.
Add a new job: an apple falls every few seconds, and catching it gives a life.
This ticks by itself when your blocks do what is asked.
Students read a whole game, match each job to its blocks, and change rules without breaking the game: a review of the course before the final challenge. About 40 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
This lesson adds nothing new. Garden defender uses every idea in the course: sprites and positions, the controller, velocity, kinds and overlaps, lives, a timer with pick random, an if in on game update, and projectiles. The skill is reading: find the blocks that do one job, then change only those. It prepares students for Space dodger, where they build a game in milestones.
Finding the right block in a longer program. Ask them to name the job first, then point to its block.
Stretch: Add a second timer that sends a fast bug every 5 seconds. Where does each part of it go?
Support: Give students the apple's timer already made, and ask them only to add the Player–Food overlap.
Next: Space dodger, the final challenge, built in milestones with less help each time.