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.
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, Run and Investigate 15 min · Status bar 10 min · Gold turtle 10 min · Upgrade 10 min · Your own power-up 15 min
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.
| What you will see | A question to ask | The fix |
|---|---|---|
| The upgrade can be bought with 0 points and the score goes negative. | What should be true before the player can buy it? | Add score >= 5 to the if that checks the button. |
| The gold circle stays on screen after the turtle moves on. | When is the gold circle drawn, and what clears it? | Draw it only when showing and gold are both True, and redraw (draw_scene) after a catch or a hide. |
| The upgrade button seems to do nothing. | Does hop() use delay, or still the number 1000? | Use ontimer(hop, delay) and ontimer(hide, delay - 300). |
One possible solution for each task. Other correct programs are fine.
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 label(x, y, name, value):
goto(x, y)
write(name, False, "left", ("Arial", 14, "normal"))
goto(x + 55, y)
write(value, False, "left", ("Arial", 14, "bold"))
def draw_scene():
clear()
label(-190, 160, "Score", score)
label(-50, 160, "Lives", lives)
label(90, 160, "Time", time_left)
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()
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
gold = False
time_left = 30
playing = False
def label(x, y, name, value):
goto(x, y)
write(name, False, "left", ("Arial", 14, "normal"))
goto(x + 55, y)
write(value, False, "left", ("Arial", 14, "bold"))
def draw_scene():
clear()
label(-190, 160, "Score", score)
label(-50, 160, "Lives", lives)
label(90, 160, "Time", time_left)
if playing == False:
draw_button(-60, -180, 120, 40, "Start")
if showing and gold:
goto(tx, ty)
dot(50, "gold")
goto(tx, ty)
def hop():
global place, tx, ty, showing, gold
if playing:
tx = xs[place]
ty = ys[place]
place = (place + 1) % len(xs)
if place % 3 == 0:
gold = True
else:
gold = False
showing = True
draw_scene()
showturtle()
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):
if gold:
score = score + 5
else:
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()
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
gold = False
time_left = 30
playing = False
delay = 1000
def label(x, y, name, value):
goto(x, y)
write(name, False, "left", ("Arial", 14, "normal"))
goto(x + 55, y)
write(value, False, "left", ("Arial", 14, "bold"))
def draw_scene():
clear()
label(-190, 160, "Score", score)
label(-50, 160, "Lives", lives)
label(90, 160, "Time", time_left)
if playing:
draw_button(-60, -180, 120, 40, "Slow (5)")
else:
draw_button(-60, -180, 120, 40, "Start")
if showing and gold:
goto(tx, ty)
dot(50, "gold")
goto(tx, ty)
def hop():
global place, tx, ty, showing, gold
if playing:
tx = xs[place]
ty = ys[place]
place = (place + 1) % len(xs)
if place % 3 == 0:
gold = True
else:
gold = False
showing = True
draw_scene()
showturtle()
ontimer(hide, delay - 300)
ontimer(hop, delay)
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, delay
score = 0
lives = 3
delay = 1000
time_left = 30
place = 0
playing = True
draw_scene()
hop()
ontimer(tick, 1000)
def clicked(x, y):
global score, showing, delay
if playing and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
if gold:
score = score + 5
else:
score = score + 1
showing = False
hideturtle()
draw_scene()
if playing and score >= 5 and inside(x, y, -60, -180, 120, 40):
score = score - 5
delay = delay + 200
draw_scene()
if playing == False and inside(x, y, -60, -180, 120, 40):
start()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
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
gold = False
time_left = 30
playing = False
delay = 1000
# My power-up: More time costs 10 points and adds 5 seconds.
# Fair because 10 points is about two gold turtles, and 5 seconds can win them back.
def label(x, y, name, value):
goto(x, y)
write(name, False, "left", ("Arial", 14, "normal"))
goto(x + 55, y)
write(value, False, "left", ("Arial", 14, "bold"))
def draw_scene():
clear()
label(-190, 160, "Score", score)
label(-50, 160, "Lives", lives)
label(90, 160, "Time", time_left)
if playing:
draw_button(-130, -180, 120, 40, "Slow (5)")
draw_button(10, -180, 120, 40, "Time (10)")
else:
draw_button(-60, -180, 120, 40, "Start")
if showing and gold:
goto(tx, ty)
dot(50, "gold")
goto(tx, ty)
def hop():
global place, tx, ty, showing, gold
if playing:
tx = xs[place]
ty = ys[place]
place = (place + 1) % len(xs)
if place % 3 == 0:
gold = True
else:
gold = False
showing = True
draw_scene()
showturtle()
ontimer(hide, delay - 300)
ontimer(hop, delay)
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, delay
score = 0
lives = 3
delay = 1000
time_left = 30
place = 0
playing = True
draw_scene()
hop()
ontimer(tick, 1000)
def clicked(x, y):
global score, showing, delay, time_left
if playing and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
if gold:
score = score + 5
else:
score = score + 1
showing = False
hideturtle()
draw_scene()
if playing and score >= 10 and inside(x, y, 10, -180, 120, 40):
score = score - 10
time_left = time_left + 5
draw_scene()
if playing and score >= 5 and inside(x, y, -130, -180, 120, 40):
score = score - 5
delay = delay + 200
draw_scene()
if playing == False and inside(x, y, -60, -180, 120, 40):
start()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
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.
Name one part of your game that is user interface and one that is a game rule.
For example: the status bar is user interface (it shows the state); losing a life on a miss is a game rule.
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).