Turn the game into a real game with screens, levels and a turtle that moves.
Every game is a loop that updates its data and redraws, and a few screens it moves between.
Your game starts as soon as you press Start and just stops at the end. Real games have screens (a title, the game, game over), get harder as you play, and have things that move. Each is a small change to the game you already built.
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
showing = False
time_left = 30
state = "title"
def big(text, x, y):
goto(x, y)
write(text, False, "left", ("Arial", 28, "bold"))
def draw_scene():
clear()
if state == "title":
big("Catch the turtle", -140, 40)
draw_button(-60, -180, 120, 40, "Play")
if state == "play":
goto(-190, 160)
write(score, False, "left", ("Arial", 20, "normal"))
goto(150, 160)
write(time_left, False, "left", ("Arial", 20, "normal"))
if state == "over":
big("Game over", -90, 40)
big(score, -10, -10)
draw_button(-60, -180, 120, 40, "Again")
goto(tx, ty)
def hop():
global place, tx, ty, showing
if state == "play":
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
if showing:
showing = False
hideturtle()
def tick():
global time_left, state
if state == "play":
time_left = time_left - 1
if time_left == 0:
state = "over"
hideturtle()
else:
ontimer(tick, 1000)
draw_scene()
def start():
global score, time_left, place, state
score = 0
time_left = 30
place = 0
state = "play"
draw_scene()
hop()
ontimer(tick, 1000)
def clicked(x, y):
global score, showing
if state == "play" and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
score = score + 1
showing = False
hideturtle()
draw_scene()
if state != "play" and inside(x, y, -60, -180, 120, 40):
start()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
state is "title", "play" or "over". draw_scene draws a different screen for each one.
Play a game to the end, then play again.
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
showing = False
time_left = 30
state = "title"
def big(text, x, y):
goto(x, y)
write(text, False, "left", ("Arial", 28, "bold"))
def draw_scene():
clear()
if state == "title":
big("Catch the turtle", -140, 40)
draw_button(-60, -180, 120, 40, "Play")
if state == "play":
goto(-190, 160)
write(score, False, "left", ("Arial", 20, "normal"))
goto(150, 160)
write(time_left, False, "left", ("Arial", 20, "normal"))
if state == "over":
big("Game over", -90, 40)
big(score, -10, -10)
draw_button(-60, -180, 120, 40, "Again")
goto(tx, ty)
def hop():
global place, tx, ty, showing
if state == "play":
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
if showing:
showing = False
hideturtle()
def tick():
global time_left, state
if state == "play":
time_left = time_left - 1
if time_left == 0:
state = "over"
hideturtle()
else:
ontimer(tick, 1000)
draw_scene()
def start():
global score, time_left, place, state
score = 0
time_left = 30
place = 0
state = "play"
draw_scene()
hop()
ontimer(tick, 1000)
def clicked(x, y):
global score, showing
if state == "play" and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
score = score + 1
showing = False
hideturtle()
draw_scene()
if state != "play" and inside(x, y, -60, -180, 120, 40):
start()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
Find every line that changes state. Which event causes each change?
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
showing = False
time_left = 30
state = "title"
def big(text, x, y):
goto(x, y)
write(text, False, "left", ("Arial", 28, "bold"))
def draw_scene():
clear()
if state == "title":
big("Catch the turtle", -140, 40)
draw_button(-60, -180, 120, 40, "Play")
if state == "play":
goto(-190, 160)
write(score, False, "left", ("Arial", 20, "normal"))
goto(150, 160)
write(time_left, False, "left", ("Arial", 20, "normal"))
if state == "over":
big("Game over", -90, 40)
big(score, -10, -10)
draw_button(-60, -180, 120, 40, "Again")
goto(tx, ty)
def hop():
global place, tx, ty, showing
if state == "play":
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
if showing:
showing = False
hideturtle()
def tick():
global time_left, state
if state == "play":
time_left = time_left - 1
if time_left == 0:
state = "over"
hideturtle()
else:
ontimer(tick, 1000)
draw_scene()
def start():
global score, time_left, place, state
score = 0
time_left = 30
place = 0
state = "play"
draw_scene()
hop()
ontimer(tick, 1000)
def clicked(x, y):
global score, showing
if state == "play" and showing and inside(x, y, tx - 20, ty - 20, 40, 40):
score = score + 1
showing = False
hideturtle()
draw_scene()
if state != "play" and inside(x, y, -60, -180, 120, 40):
start()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
Every 5 points, go up a level and make the turtle faster. Show the level at the top.
In clicked, after score = score + 1: if score % 5 == 0 and delay > 400: level = level + 1, delay = delay - 150.
Use ontimer(hop, delay) and ontimer(hide, delay - 300), and reset level and delay in start().
Make the turtle walk to each spot instead of jumping, in 10 small steps. It is harder to catch, and you can see where it is heading.
move(): if state == "play" and steps > 0: tx = tx + dx, ty = ty + dy, goto(tx, ty), steps = steps - 1, ontimer(move, 50).
hop(): dx = (xs[place] - tx) / 10, the same for dy, steps = 10, then move() instead of goto.
Every 5 points the level goes up and the turtle gets faster.
Run your program. This ticks when your code does all of the above.
The turtle walks to each spot in small steps.
Run your program. This ticks when your code does all of the above.
Add a rule that makes the game your own. Where this leads: MakeCode Arcade and microStudio give you sprites that move by themselves and screens to switch between. Under the hood they run the same loop you just built: update the data, check for hits, redraw.
Boss turtle: every tenth spot needs three clicks. Count hits in a variable and only score when it reaches 3.
High score: a best variable that only changes when a game ends with a higher score, shown on the over screen.
An optional lesson in the games direction. Students add screens (title, play, game over), levels that speed up and a turtle that walks between spots, the way game engines move sprites. About 45 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
state holds one of three words: "title", "play" or "over". It replaces True and False because a game has three screens, and two values cannot tell them apart. The moving turtle takes 10 small steps, one every 50 milliseconds, instead of jumping. (An animated move with speed() would make the program ignore clicks until the move finished.)
A state variable deciding which screen runs. Ask them to say which state the game is in after each click, and check the spelling is the same everywhere.
Stretch: Add a boss turtle every tenth spot that needs three clicks, with its own hit counter.
Support: Do Levels together; leave Moving turtle as an extra for those who finish.
MakeCode Arcade and microStudio give you sprites that move by themselves and screens to switch between. Underneath they run the same loop: update the data, check for hits, redraw.