← Teacher guide

Many turtles

Students make extra turtles with Turtle(), give each one commands by name, and play a catch-the-stars game built from three separate star variables, so they can count what each star costs in code.

Objects with turtles · Many things on screen · about 50 minutes · Open the student lesson

Classroom resources

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.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min

Before class

Read the unit primer first. a = Turtle() makes a new turtle; a.forward(100) moves only a. Commands with no name in front (forward, goto, xcor()) go to the default turtle, the one from the turtle course. As in real Python, the default turtle only appears once such a command uses it, which is why the Predict program shows two turtles, not three. In the game the student is the default turtle; the stars are s1, s2 and s3; pen is a hidden turtle that writes the score. Keys need the picture clicked first.

Running the lesson

  1. Predict: most students say 3. Run it and ask where the third turtle went: nothing ever used it.
  2. Run: give two minutes to play. Then ask students to put a finger on every line about s1.
  3. Investigate: the count (11 lines per star) is the point of the lesson. Ask what 20 stars would cost.
  4. Bug task: a missing name sends the command to the default turtle, which then appears. Students meet this again in their own games.
  5. Make: the rock is a whole new block of lines. Ask how many lines it took, and keep the number for next lesson.

The hard part (on purpose)

Seeing that every command needs the turtle's name and a dot. When the wrong turtle moves, ask whose name is in front of that line.

When students get stuck

What you will seeA question to askThe fix
An extra turtle appears in the middle, or the player moves when a star should.Does every command for a star have the star's name and a dot in front?Add the name: s4.forward(5), not forward(5).
The arrow keys do nothing.Did you click the picture after pressing Run?Click the picture once, then use the arrow keys.
NameError: name 's4' is not defined.Is s4 made (s4 = Turtle()) before tick uses it?Put the lines that make s4 with the other stars, above the functions.

Answers to the checks

  1. Predict: How many turtles are on the screen when it finishes?
    2: a and b. Every command has a name in front of it, so the turtle you used in the turtle course (the default turtle) is never used, and Python does not draw it.
  2. Match the lines: Match each line with what it does.
    s1 = Turtle() → A. makes a new turtle and names it s1; s1.forward(4) → B. moves s1 only; goto(xcor() - 25, ycor()) → D. moves you, the turtle at the bottom; pen.write(...) → C. writes the score with the hidden pen turtle
  3. Count the cost: Count the lines that mention s1 (making it, moving it, catching it, sending it back to the top). How many are there?
    11
    Six lines make s1, then five more in tick move it, catch it and send it back. Every star costs those 11 lines again, so twenty stars would need about 220.
  4. Spot the bug: This should draw a red line to the right and a blue line straight up. The blue line goes right instead, and a third turtle appears. Click the line that causes it.
    line 8
    left(90) has no name in front, so it turns the default turtle (which then appears) instead of b. It should be b.left(90).
  5. Where this leads: A game needs 50 falling stars. What is the trouble with s1, s2, s3 … s50?
    About 550 near-identical lines, and a change to how stars move must be made 50 times
    Separate variables cost the same block of lines for every star. Next lesson keeps the stars in a list, so a loop does the work for all of them.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › A blue star

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

s1 = Turtle()
s1.shape("circle")
s1.color("gold")
s1.penup()
s1.goto(-120, 200)
s1.setheading(270)

s2 = Turtle()
s2.shape("circle")
s2.color("blue")
s2.penup()
s2.goto(0, 200)
s2.setheading(270)

s3 = Turtle()
s3.shape("circle")
s3.color("gold")
s3.penup()
s3.goto(120, 200)
s3.setheading(270)

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    s1.forward(4)
    if s1.distance(xcor(), ycor()) < 25:
        score += 1
        s1.goto(random.randint(-200, 200), 200)
    if s1.ycor() < -220:
        s1.goto(random.randint(-200, 200), 200)
    s2.forward(9)
    if s2.distance(xcor(), ycor()) < 25:
        score += 1
        s2.goto(random.randint(-200, 200), 200)
    if s2.ycor() < -220:
        s2.goto(random.randint(-200, 200), 200)
    s3.forward(3)
    if s3.distance(xcor(), ycor()) < 25:
        score += 1
        s3.goto(random.randint(-200, 200), 200)
    if s3.ycor() < -220:
        s3.goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Modify › A fourth star

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

s1 = Turtle()
s1.shape("circle")
s1.color("gold")
s1.penup()
s1.goto(-120, 200)
s1.setheading(270)

s2 = Turtle()
s2.shape("circle")
s2.color("gold")
s2.penup()
s2.goto(0, 200)
s2.setheading(270)

s3 = Turtle()
s3.shape("circle")
s3.color("gold")
s3.penup()
s3.goto(120, 200)
s3.setheading(270)

s4 = Turtle()
s4.shape("circle")
s4.color("gold")
s4.penup()
s4.goto(60, 200)
s4.setheading(270)

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    s1.forward(4)
    if s1.distance(xcor(), ycor()) < 25:
        score += 1
        s1.goto(random.randint(-200, 200), 200)
    if s1.ycor() < -220:
        s1.goto(random.randint(-200, 200), 200)
    s2.forward(6)
    if s2.distance(xcor(), ycor()) < 25:
        score += 1
        s2.goto(random.randint(-200, 200), 200)
    if s2.ycor() < -220:
        s2.goto(random.randint(-200, 200), 200)
    s3.forward(3)
    if s3.distance(xcor(), ycor()) < 25:
        score += 1
        s3.goto(random.randint(-200, 200), 200)
    if s3.ycor() < -220:
        s3.goto(random.randint(-200, 200), 200)
    s4.forward(5)
    if s4.distance(xcor(), ycor()) < 25:
        score += 1
        s4.goto(random.randint(-200, 200), 200)
    if s4.ycor() < -220:
        s4.goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Make a rock

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

s1 = Turtle()
s1.shape("circle")
s1.color("gold")
s1.penup()
s1.goto(-120, 200)
s1.setheading(270)

s2 = Turtle()
s2.shape("circle")
s2.color("gold")
s2.penup()
s2.goto(0, 200)
s2.setheading(270)

s3 = Turtle()
s3.shape("circle")
s3.color("gold")
s3.penup()
s3.goto(120, 200)
s3.setheading(270)

rock = Turtle()
rock.shape("square")
rock.color("gray")
rock.penup()
rock.goto(-60, 200)
rock.setheading(270)

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    s1.forward(4)
    if s1.distance(xcor(), ycor()) < 25:
        score += 1
        s1.goto(random.randint(-200, 200), 200)
    if s1.ycor() < -220:
        s1.goto(random.randint(-200, 200), 200)
    s2.forward(6)
    if s2.distance(xcor(), ycor()) < 25:
        score += 1
        s2.goto(random.randint(-200, 200), 200)
    if s2.ycor() < -220:
        s2.goto(random.randint(-200, 200), 200)
    s3.forward(3)
    if s3.distance(xcor(), ycor()) < 25:
        score += 1
        s3.goto(random.randint(-200, 200), 200)
    if s3.ycor() < -220:
        s3.goto(random.randint(-200, 200), 200)
    rock.forward(5)
    if rock.distance(xcor(), ycor()) < 25:
        score -= 3
        rock.goto(random.randint(-200, 200), 200)
    if rock.ycor() < -220:
        rock.goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Stretch and support

Stretch: Give the rock its own speed that increases a little every time it is sent back to the top.

Support: Give students the six lines that make the rock, and ask them to add only its lines in tick.

Exit ticket

a = Turtle(), then forward(50). Which turtle moves?

The default turtle, not a: forward(50) has no name in front. a.forward(50) would move a.

What each step is for

Where it leads

Next lesson keeps the stars in lists, so one loop moves them all and adding a star is one number. Real games (Arcade sprites, microStudio, every game engine) are many objects like these, each with its own position and behaviour.