← Python functions and events

Power-ups

Add lives, a status bar, a gold turtle and an upgrade you buy with points.

Games and apps are built from the same parts: buttons that change state, and rules about what each change means.

Your game works. Now make it richer: lives instead of misses, a proper status bar, a gold turtle worth more, and an upgrade that costs points. Each one is a small change to the program you already have.

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

powerups.py
from turtle import *
from ui import inside, draw_button

speed(0)
penup()
hideturtle()

xs = [-120, 0, 120, 120, 0, -120]
ys = [60, 110, 60, -50, -100, -50]
place = 0
tx = 0
ty = 0
score = 0
lives = 3
showing = False
time_left = 30
playing = False


def draw_scene():
    clear()
    goto(-190, 160)
    write(score, False, "left", ("Arial", 20, "normal"))
    goto(-20, 160)
    write(lives, False, "left", ("Arial", 20, "normal"))
    goto(150, 160)
    write(time_left, False, "left", ("Arial", 20, "normal"))
    if playing == False:
        draw_button(-60, -180, 120, 40, "Start")
    goto(tx, ty)


def hop():
    global place, tx, ty, showing
    if playing:
        tx = xs[place]
        ty = ys[place]
        place = (place + 1) % len(xs)
        goto(tx, ty)
        showturtle()
        showing = True
        ontimer(hide, 700)
        ontimer(hop, 1000)


def hide():
    global showing, lives, playing
    if showing:
        lives = lives - 1
        showing = False
        hideturtle()
        if lives == 0:
            playing = False
        draw_scene()


def tick():
    global time_left, playing
    if playing:
        time_left = time_left - 1
        if time_left == 0:
            playing = False
            hideturtle()
        else:
            ontimer(tick, 1000)
        draw_scene()


def start():
    global score, lives, time_left, playing, place
    score = 0
    lives = 3
    time_left = 30
    place = 0
    playing = True
    draw_scene()
    hop()
    ontimer(tick, 1000)


def clicked(x, y):
    global score, showing
    if playing and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
        score = score + 1
        showing = False
        hideturtle()
        draw_scene()
    if playing == False and inside(x, y, -60, -180, 120, 40):
        start()


draw_scene()
onscreenclick(clicked)
listen()
mainloop()

This is your game with lives in place of misses. Read hide(): what changes when the turtle escapes?

You start a game and miss three turtles in a row. What happens?

RunRun it and compare the result with your prediction.

Run

Press Start and miss on purpose. Then play properly and see how long you last.

powerups.py
from turtle import *
from ui import inside, draw_button

speed(0)
penup()
hideturtle()

xs = [-120, 0, 120, 120, 0, -120]
ys = [60, 110, 60, -50, -100, -50]
place = 0
tx = 0
ty = 0
score = 0
lives = 3
showing = False
time_left = 30
playing = False


def draw_scene():
    clear()
    goto(-190, 160)
    write(score, False, "left", ("Arial", 20, "normal"))
    goto(-20, 160)
    write(lives, False, "left", ("Arial", 20, "normal"))
    goto(150, 160)
    write(time_left, False, "left", ("Arial", 20, "normal"))
    if playing == False:
        draw_button(-60, -180, 120, 40, "Start")
    goto(tx, ty)


def hop():
    global place, tx, ty, showing
    if playing:
        tx = xs[place]
        ty = ys[place]
        place = (place + 1) % len(xs)
        goto(tx, ty)
        showturtle()
        showing = True
        ontimer(hide, 700)
        ontimer(hop, 1000)


def hide():
    global showing, lives, playing
    if showing:
        lives = lives - 1
        showing = False
        hideturtle()
        if lives == 0:
            playing = False
        draw_scene()


def tick():
    global time_left, playing
    if playing:
        time_left = time_left - 1
        if time_left == 0:
            playing = False
            hideturtle()
        else:
            ontimer(tick, 1000)
        draw_scene()


def start():
    global score, lives, time_left, playing, place
    score = 0
    lives = 3
    time_left = 30
    place = 0
    playing = True
    draw_scene()
    hop()
    ontimer(tick, 1000)


def clicked(x, y):
    global score, showing
    if playing and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
        score = score + 1
        showing = False
        hideturtle()
        draw_scene()
    if playing == False and inside(x, y, -60, -180, 120, 40):
        start()


draw_scene()
onscreenclick(clicked)
listen()
mainloop()
Try it yourselfYour edits are saved in this browser.

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

Investigate

Look at the program again: which lines draw things the player sees, and which lines decide what happens?

powerups.py
from turtle import *
from ui import inside, draw_button

speed(0)
penup()
hideturtle()

xs = [-120, 0, 120, 120, 0, -120]
ys = [60, 110, 60, -50, -100, -50]
place = 0
tx = 0
ty = 0
score = 0
lives = 3
showing = False
time_left = 30
playing = False


def draw_scene():
    clear()
    goto(-190, 160)
    write(score, False, "left", ("Arial", 20, "normal"))
    goto(-20, 160)
    write(lives, False, "left", ("Arial", 20, "normal"))
    goto(150, 160)
    write(time_left, False, "left", ("Arial", 20, "normal"))
    if playing == False:
        draw_button(-60, -180, 120, 40, "Start")
    goto(tx, ty)


def hop():
    global place, tx, ty, showing
    if playing:
        tx = xs[place]
        ty = ys[place]
        place = (place + 1) % len(xs)
        goto(tx, ty)
        showturtle()
        showing = True
        ontimer(hide, 700)
        ontimer(hop, 1000)


def hide():
    global showing, lives, playing
    if showing:
        lives = lives - 1
        showing = False
        hideturtle()
        if lives == 0:
            playing = False
        draw_scene()


def tick():
    global time_left, playing
    if playing:
        time_left = time_left - 1
        if time_left == 0:
            playing = False
            hideturtle()
        else:
            ontimer(tick, 1000)
        draw_scene()


def start():
    global score, lives, time_left, playing, place
    score = 0
    lives = 3
    time_left = 30
    place = 0
    playing = True
    draw_scene()
    hop()
    ontimer(tick, 1000)


def clicked(x, y):
    global score, showing
    if playing and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
        score = score + 1
        showing = False
        hideturtle()
        draw_scene()
    if playing == False and inside(x, y, -60, -180, 120, 40):
        start()


draw_scene()
onscreenclick(clicked)
listen()
mainloop()

Each part of a game is user interface, a game rule, or both. Match them.

The status bar showing score, lives and time
The Start button
Losing a life when a turtle escapes
A gold turtle worth 5 points
A button that costs 5 points to use

ModifyChange the code on purpose and check the result.

Add the power-ups

Write label(x, y, name, value) and use it to show Score, Lives and Time across the top. One function, three calls.

Need a hint?

def label(x, y, name, value): goto(x, y), write(name), goto(x + 55, y), write(value).

Another hint

In draw_scene: label(-190, 160, "Score", score), then Lives at -50 and Time at 90.

Every third spot, the turtle is gold: draw a gold circle under it, and make catching it worth 5.

Need a hint?

In hop, after place changes: if place % 3 == 0: gold = True, else: gold = False.

Another hint

In draw_scene: if showing and gold: goto(tx, ty) then dot(50, "gold"). In clicked: if gold: score = score + 5, else: score = score + 1.

While playing, the button says Slow (5). Clicking it spends 5 points and slows the turtle down by 200 milliseconds, but only if you can afford it.

Need a hint?

Add delay = 1000 with the other variables, set it back to 1000 in start(), and use ontimer(hop, delay) and ontimer(hide, delay - 300).

Another hint

In clicked: if playing and score >= 5 and inside(x, y, -60, -180, 120, 40): take 5 points, add 200 to delay, draw_scene().

Try it yourselfYour edits are saved in this browser.

A status bar drawn by one function with four parameters, used three times.

    Run your program. This ticks when your code does all of the above.

    Every third spot is gold, shown with a gold circle, and worth 5.

      Run your program. This ticks when your code does all of the above.

      A Slow (5) button that spends points to slow the turtle.

        Run your program. This ticks when your code does all of the above.

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

        Your own power-up

        Invent a power-up of your own. Decide what it does, what it costs and when it can be used, then build it. Write one sentence (as a comment at the top) that explains why the cost is fair.

        Try it yourselfYour edits are saved in this browser.
        Need a hint?

        More time: a button that costs 10 points and adds 5 to time_left.

        Another hint

        Bigger catch box: a power-up that makes the box 60 by 60 instead of 40 by 40 (remember to centre it: tx - 30).

        Another hint

        Double points: a variable that doubles every catch until the next game.

        For teachers

        The second half of the final challenge. Students add lives, a status bar, a gold turtle worth 5 and an upgrade bought with points, then invent a power-up of their own. About 60 minutes.

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

        Students will be able to

        Before class

        This lesson mixes both directions students could take next. The user interface is what the player sees and uses (the status bar, the buttons); the rules decide what each event means (losing a life, gold is worth 5, an upgrade costs 5). The Investigate task sorts parts into the two kinds. Try the upgrade task yourself: it uses a variable delay instead of the fixed 1000 milliseconds.

        Running the lesson

        1. Predict: each miss takes a life; at 0 lives the game stops. Point to the line that ends the game.
        2. Investigate: discuss the match before checking it. 'Both' (a button that costs points) is the interesting one.
        3. Status bar: one function, label(x, y, name, value), called three times. Ask what the alternative would be (copying six lines three times).
        4. Gold turtle: every third spot is gold, using % from Every other. The gold circle is drawn under the turtle.
        5. Upgrade: the button only works if score >= 5. Ask what happens without that check (scores go negative).
        6. Your own power-up: students write one sentence at the top explaining why its cost is fair. Share a few.

        The hard part (on purpose)

        Separating the rules from the display, and the check before buying. Ask what must be true before the player can buy, before they write the if.

        When students get stuck

        Stretch and support

        Stretch: Add a power-up that makes the catch box bigger for 10 seconds, then switches back by itself (a timer).

        Support: Do the status bar together, then let students choose either the gold turtle or the upgrade rather than both.

        Where it leads

        Completing this and Catch the turtle marks the course Challenge complete. Optional next: Control panel (user interface, towards Gradio and web pages) or Game levels (games, towards MakeCode Arcade and microStudio).

        What each step is for

        Now you can
        Next lesson11. Optional: Control panelTurn the game into an app with a panel of buttons made from lists.