Students limit a blaster with a number that counts down, check it first so it never goes below zero, refill it with a star, and make a shield run out after 5 seconds.
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 and Run 7 min · Investigate 10 min · Modify 8 min · Mix it up 3 min · Make 12 min · Sprint 5 min
A power-up that runs out is a number counting down. For ammo, the A event asks if ammo > 0 first, then fires and changes ammo by -1. Without the check, ammo goes below zero and the shots never stop (the misconception). With ≥ 0 there is one shot too many.
For time, a timer every 1000 ms counts shieldTime down while the shield is on, and at 0 sets the shield back to false: an if inside an if. Set (refill to 5) and change (add 3) are different, which Modify brings out.
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.
A student has three counters. Each "fire" hands one over, but only if they still have one.
Nobody can hand over a counter they do not have. The game can, unless it checks.
Play the next pair's sprint boost. Is three boosts fair?
Checking before using. When the count goes below zero, ask what the event asks first.
| What you will see | A question to ask | The fix |
|---|---|---|
| Shots never run out. | Is the shot inside the if? | Put both the shot and change ammo by -1 inside if ammo > 0. |
| The shield switches off straight away, or never. | Where is the countdown, and when does that block run? | In the 1000 ms timer, inside if shield; set it to false only inside if shieldTime = 0. |
| The countdown goes 5, 3, 1, -1. | How many timers count it down? | One: remove the second change. |
One possible solution for each task. Other correct programs are fine.

let star: Sprite = null
let shot: Sprite = null
let rock: Sprite = null
let ammo = 3
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)
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
if (ammo > 0) {
shot = sprites.createProjectileFromSprite(img`
4 4 4
`, ship, 100, 0)
ammo += -1
}
ship.sayText(ammo)
})
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
})
game.onUpdateInterval(5000, function () {
star = sprites.create(img`
. . 5 . .
5 5 5 5 5
. 5 5 5 .
. 5 . 5 .
`, SpriteKind.Food)
star.setPosition(160, randint(10, 110))
star.vx = -30
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
sprite.destroy()
otherSprite.destroy()
info.changeScoreBy(1)
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) {
otherSprite.destroy()
ammo = 5
})

let star: Sprite = null
let shot: Sprite = null
let rock: Sprite = null
let ammo = 3
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)
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
if (ammo > 0) {
shot = sprites.createProjectileFromSprite(img`
4 4 4
`, ship, 100, 0)
ammo += -1
}
ship.sayText(ammo)
})
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
})
game.onUpdateInterval(5000, function () {
star = sprites.create(img`
. . 5 . .
5 5 5 5 5
. 5 5 5 .
. 5 . 5 .
`, SpriteKind.Food)
star.setPosition(160, randint(10, 110))
star.vx = -30
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
sprite.destroy()
otherSprite.destroy()
info.changeScoreBy(1)
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) {
otherSprite.destroy()
ammo += 3
})

let rock: Sprite = null
let star: Sprite = null
let shield = false
let shieldTime = 0
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
if (shield) {
info.changeScoreBy(5)
} else {
info.changeLifeBy(-1)
}
})
sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) {
otherSprite.destroy()
shield = true
shieldTime = 5
scene.setBackgroundColor(8)
})
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
info.changeScoreBy(1)
if (shield) {
shieldTime += -1
if (shieldTime == 0) {
shield = false
scene.setBackgroundColor(15)
}
}
})
game.onUpdateInterval(5000, function () {
star = sprites.create(img`
. . 5 . .
5 5 5 5 5
. 5 5 5 .
. 5 . 5 .
`, SpriteKind.Food)
star.setPosition(160, randint(10, 110))
star.vx = -30
})
Open task: any program that does what the step asks.
Stretch: Show the shield time with the ship's say block, every second.
Support: Give students the if shield in the timer, so they add only the countdown and the switch-off.
Why does the A event ask ammo > 0 before it fires?
So it only fires while there are shots left. Without the check, ammo goes below zero and the shots never run out.
Next: the Power-ups challenge, with less help. Skillmap: Save the Galaxy (arcade.makecode.com/skillmaps).