Students give the Star class methods (move, restart, touches), so the game loop asks each star to act, then add methods of their own and a Rock class with the same method names.
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 and Run 10 min · Investigate 15 min · Modify 10 min · Make 20 min
Read the unit primer first. A method is a function inside a class; its first parameter is self, the object it was called on. star.move() runs move with self as that star, which is why a method without self (the bug task) stops with "takes 0 positional arguments but 1 was given". Methods can call each other (self.restart()) and change the object's own values (self.points += 1). The Make task gives Rock the same method names as Star, so tick treats both the same way. That is the idea behind game engines, without the word polymorphism.
Remembering self in a method's def and inside it. Let the TypeError happen, then ask what Python hands to a method first.
| What you will see | A question to ask | The fix |
|---|---|---|
| TypeError: ... takes 0 positional arguments but 1 was given. | Does the method's def start with self? | def flash(self):, then use self inside it. |
| NameError: name 'turtle' is not defined (or speed). | Inside a method, how do you reach the star's own values? | Use self. in front: self.turtle, self.speed. |
| The method is written but nothing happens. | Where is the method called? | Call it on a star where it should happen, such as star.flash() when a star is caught. |
One possible solution for each task. Other correct programs are fine.
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)
class Star:
def __init__(self, x):
self.turtle = Turtle()
self.turtle.shape("circle")
self.turtle.color("gold")
self.turtle.penup()
self.turtle.goto(x, 200)
self.turtle.setheading(270)
self.speed = random.randint(3, 7)
self.points = 1
def move(self):
self.turtle.forward(self.speed)
if self.turtle.ycor() < -220:
self.restart()
def restart(self):
self.turtle.goto(random.randint(-200, 200), 200)
def touches(self, x, y):
return self.turtle.distance(x, y) < 25
def flash(self):
self.turtle.color("orange")
stars = []
for i in range(4):
stars.append(Star(-150 + i * 100))
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
for star in stars:
star.move()
if star.touches(xcor(), ycor()):
score += star.points
star.flash()
star.restart()
show_score()
ontimer(tick, 50)
onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()
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)
class Star:
def __init__(self, x):
self.turtle = Turtle()
self.turtle.shape("circle")
self.turtle.color("gold")
self.turtle.penup()
self.turtle.goto(x, 200)
self.turtle.setheading(270)
self.speed = random.randint(3, 7)
self.points = 1
def move(self):
self.turtle.forward(self.speed)
if self.turtle.ycor() < -220:
self.restart()
def restart(self):
self.turtle.goto(random.randint(-200, 200), 200)
def touches(self, x, y):
return self.turtle.distance(x, y) < 25
def level_up(self):
self.points += 1
self.speed += 1
stars = []
for i in range(4):
stars.append(Star(-150 + i * 100))
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
for star in stars:
star.move()
if star.touches(xcor(), ycor()):
score += star.points
star.level_up()
star.restart()
show_score()
ontimer(tick, 50)
onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()
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)
class Star:
def __init__(self, x):
self.turtle = Turtle()
self.turtle.shape("circle")
self.turtle.color("gold")
self.turtle.penup()
self.turtle.goto(x, 200)
self.turtle.setheading(270)
self.speed = random.randint(3, 7)
self.points = 1
def move(self):
self.turtle.forward(self.speed)
if self.turtle.ycor() < -220:
self.restart()
def restart(self):
self.turtle.goto(random.randint(-200, 200), 200)
def touches(self, x, y):
return self.turtle.distance(x, y) < 25
stars = []
for i in range(4):
stars.append(Star(-150 + i * 100))
class Rock:
def __init__(self, x):
self.turtle = Turtle()
self.turtle.shape("square")
self.turtle.color("gray")
self.turtle.penup()
self.turtle.goto(x, 200)
self.turtle.setheading(270)
self.speed = random.randint(4, 8)
def move(self):
self.turtle.forward(self.speed)
if self.turtle.ycor() < -220:
self.restart()
def restart(self):
self.turtle.goto(random.randint(-200, 200), 200)
def touches(self, x, y):
return self.turtle.distance(x, y) < 25
rocks = []
for i in range(2):
rocks.append(Rock(-100 + i * 200))
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
for star in stars:
star.move()
if star.touches(xcor(), ycor()):
score += star.points
star.restart()
for rock in rocks:
rock.move()
if rock.touches(xcor(), ycor()):
score -= 3
rock.restart()
show_score()
ontimer(tick, 50)
onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()
Stretch: Add a Heart class that gives back a life, and a lives counter that ends the game at 0.
Support: Give students the Rock class with __init__ and move written, and ask them to add restart and touches by copying Star's.
class Lamp: def __init__(self): self.on = False. Write a method switch that turns it on.
def switch(self): self.on = True (inside the class), called as lamp.switch().
This completes the course. microStudio's sprites and MakeCode Arcade's sprites are objects with their own values and behaviour. Apps with Gradio and Data detective use objects too (a Question class, a row of data).