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.
Make your prediction first. Help opens once you've locked it in.
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?
Press Start and miss on purpose. Then play properly and see how long you last.
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()
Look at the program again: which lines draw things the player sees, and which lines decide what happens?
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.
Write label(x, y, name, value) and use it to show Score, Lives and Time across the top. One function, three calls.
def label(x, y, name, value): goto(x, y), write(name), goto(x + 55, y), write(value).
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.
In hop, after place changes: if place % 3 == 0: gold = True, else: gold = False.
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.
Add delay = 1000 with the other variables, set it back to 1000 in start(), and use ontimer(hop, delay) and ontimer(hide, delay - 300).
In clicked: if playing and score >= 5 and inside(x, y, -60, -180, 120, 40): take 5 points, add 200 to delay, draw_scene().
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.
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.
More time: a button that costs 10 points and adds 5 to time_left.
Bigger catch box: a power-up that makes the box 60 by 60 instead of 40 by 40 (remember to centre it: tx - 30).
Double points: a variable that doubles every catch until the next game.
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.
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.
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.
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.
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).