← Arcade Foundations

Space dodger

Build a complete game that uses everything so far. Steer a ship through rocks, keep your lives, and beat your high score.

Asteroids, Flappy Bird and every endless runner are the same game underneath: things come at you, you dodge, and the longer you last the better you score.

Your ship sits on the left and moves up and down. Rocks fly in from the right. Touch one and you lose a life; survive and your score climbs. You will build it in three milestones, with less help each time.

You already know every idea it needs. Two blocks are new, and each comes with a Behind the code note when you need it.

PredictRead the code and say what it will do before you run anything. A wrong guess is fine: it shows you what to look for.

Predict

The program as blocks
Show as code
lesson.ts
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, 60)
    rock.vx = -50
})

The ship can only move up and down: moveSprite(ship, 0, 100) gives it no speed across.

Where do the rocks fly across the screen?

RunRun it and compare the result with your prediction.

Run

Move with the up and down arrows (or W and S). Is it hard to dodge rocks that always come the same way?

The program as blocks
Show as code
lesson.ts
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, 60)
    rock.vx = -50
})
Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.

InvestigateTrace how each line of code connects to what you see.

Investigate

This is the working start of the game. Read it, and change numbers in the playground to test your answers.

The program as blocks
Show as code
lesson.ts
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, 60)
    rock.vx = -50
})

Match each block with its job.

The timer in Python:

def on_update_interval():
    global rock
    rock = sprites.create(img("""..."""), SpriteKind.enemy)
    rock.set_position(160, 60)
    rock.vx = -50
game.on_update_interval(1000, on_update_interval)

The timer becomes a def: a named job handed to the game, which runs it every second. Blocks write this for you. (Functions are the first lesson of Arcade advanced skills.)

Work it out from the numbers.

Watch a rock that misses the ship.

The program as blocks
Show as code
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
    info.changeLifeBy(-1)
})
Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.

Match each block with its job in the game.

on game update every 1000 ms
set rock position to (160, 60)
set rock vx to -50
move ship with buttons, vx 0, vy 100

A rock starts at x 160 and moves 50 pixels left every second. The ship is at x 20. How many seconds does the rock take to reach the ship?

Ava plays for a minute. A rock goes past the ship and off the left edge. What happens to it?

Leo adds an overlap event for Player and Enemy that takes away a life, but forgets to destroy the rock. He starts with 3 lives. A rock touches his ship. What happens?

ModifyChange the code on purpose and check the result.

Milestone 1: rocks from anywhere

Behind the code: set rock auto destroy on (Sprites, the set flag block) tells the engine to remove the sprite as soon as it leaves the screen. Without it, every rock that missed the ship keeps flying forever.

  1. Start each rock at a random height, from 10 to 110.
  2. Set each rock to auto destroy.
Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.
Need a hint?

In the timer, replace the 60 in set rock position with pick random 10 to 110 (from Math).

Another hint

Drag set rock auto destroy (Sprites, set flag) into the timer, under set rock vx.

Each rock starts at a random height and is removed once it leaves the screen.

This ticks by itself when your blocks do what is asked.

ModifyChange the code on purpose and check the result.

Milestone 2: lives and a hit

Give the player 3 lives, and make a hit count:

Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.
Need a hint?

Set life to 3 in on start. Then drag in on sprite of kind Player overlaps otherSprite of kind Enemy.

Another hint

Inside the overlap: destroy otherSprite, then change life by -1.

Start with 3 lives; a rock that hits the ship is destroyed and takes one life.

This ticks by itself when your blocks do what is asked.

MakeBuild something new using what you have learned. Expect a few tries; that is normal.

Milestone 3: score and high score

Behind the code: high score (in Info) is the best score so far in this browser. The game over screen shows it by itself; you can also use it in your blocks.

Finish the game:

Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.
Need a hint?

Add a second on game update every 1000 ms. Inside it: change score by 1.

Another hint

high score is in Info. Try: if score > high score, set the background to a new colour, so the player sees they are beating their best.

Score one point for every second survived, and use the high score in your game.

This ticks by itself when your blocks do what is asked.

ModifyChange the code on purpose and check the result.

Change a road crossing

The same game turned on its side: cars drive across, and the chick scores by reaching the top. Make it yours. Ideas: faster cars as the score goes up, cars from both sides, a second lane of logs, or a short effect when a car hits (Sprites › Effects).

The program as blocks
Show as code
lesson.ts
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
    otherSprite.destroy()
    info.changeLifeBy(-1)
})
let car: Sprite = null
scene.setBackgroundColor(7)
let chick = sprites.create(img`
    . 5 5 .
    5 f 5 4
    5 5 5 .
    . 4 4 .
    `, SpriteKind.Player)
chick.setPosition(80, 112)
controller.moveSprite(chick, 60, 60)
chick.setStayInScreen(true)
info.setLife(3)
game.onUpdateInterval(800, function () {
    car = sprites.create(img`
        2 2 2 2 2 .
        2 9 2 2 9 2
        2 2 2 2 2 2
        . f . . f .
        `, SpriteKind.Enemy)
    car.setPosition(0, randint(25, 95))
    car.vx = 60
    car.setFlag(SpriteFlag.AutoDestroy, true)
})
game.onUpdate(function () {
    if (chick.y < 10) {
        info.changeScoreBy(1)
        chick.setPosition(80, 112)
    }
})
Try it yourselfYour edits are saved in this browser.
It takes a few seconds to load. Your work in this step is kept.
For teachers

Students build a complete dodging game in three milestones, using a timer, random positions, velocity, overlaps, lives, score and the high score. About 60 minutes.

Open the teacher guide: answers, solutions, slides and a worksheet.

Students will be able to

Before class

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.

Running the lesson

  1. Predict and Run: every rock comes down the middle, so the game is easy (or impossible if you sit still). Ask what one change would make it a real game.
  2. Investigate: the match is the whole game in four blocks. The reaction-time sum shows why speed matters. The 'where do rocks go' question sets up auto destroy.
  3. Leo's game revisits the Score and lives lesson: an overlap runs every frame while the sprites touch, so a rock that is not destroyed eats every life at once.
  4. Milestone 1: two blocks. Auto destroy changes nothing you can see, so explain it as tidying up: the console only has so much memory.
  5. Milestone 2: read the overlap aloud: 'when the ship touches a rock, remove that rock and lose a life'. otherSprite is the rock.
  6. Milestone 3: goals only. A second timer is fine; several timers can run at once. The high score lives in the browser, so it survives the restart button.
  7. Road crossing: the same building blocks on their side. Good for students who finish early, or as a homework remix.

The hard part (on purpose)

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.

When students get stuck

Stretch and support

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.

Where it leads

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.

What each step is for

Now you can
You reached the endBack to Arcade Foundations