← Teacher guide

Stars as objects

Students bring the Star class from Objects with turtles into microStudio, where each star keeps self.x and self.y and draws itself, fix a method that forgets self, give each star its own colour, make 8 stars, and add a class of their own.

Games with microStudio · A whole game · 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. This lesson leans on Objects with turtles (classes, self, methods, a list of objects); the only new idea is that a star keeps its own x and y and paints itself in draw(), since there are no turtles. random works in microStudio's Python as usual. print() writes in microStudio's console, under the game. The bug task is the forgotten self from Objects with turtles, in a method this time.

Running the lesson

  1. Predict: write i = 0, 1, 2, 3 on the board with each x beside it.
  2. Run: ask what replaced the turtle before Investigate asks it.
  3. Investigate: the forgotten self: say the line aloud as this star's y.
  4. Make: ask each pair which list holds their new objects, and where it is moved and drawn.

The hard part (on purpose)

Moving from turtles to drawing by position: a star is now just numbers, painted each frame. Compare the two versions side by side.

When students get stuck

What you will seeA question to askThe fix
cannot access local variable 'y'.Whose y is it: a new variable, or this star's?Write self.y.
NameError: name 'random' is not defined.Is import random at the top of the file?Add import random as the first line.
The new objects are made but never seen.Are they drawn in draw(), after screen.clear?Add a loop in draw() that calls each one's draw().
All the stars have the same colour.Is the colour picked in __init__ (once per star) or in draw()?Pick it in __init__ and store it in self.colour.

Answers to the checks

  1. Predict: What does it print?
    20. stars[2] is the third star, made when i was 2, so its x is -60 + 2 × 40 = 20. (In microStudio, print() writes in the console under the game.)
  2. Turtle to engine: This is the turtle version of Star. What has the microStudio version got instead of self.turtle?
    self.x and self.y, and a draw() method that paints the star there
    A turtle remembered where it was and drew itself. With no turtle, the star keeps self.x and self.y, and draw() paints a dot at that place every frame.
  3. Match the lines: Match each line with what it does.
    self.y -= self.speed → D. moves this star down by its own speed; for star in stars: star.move() → C. tells every star to move; screen.fillRound(self.x, self.y, 8, 8, ...) → B. paints this star where it is now; stars.append(Star(-60 + i * 40)) → A. makes a star and adds it to the list
  4. Spot the bug: This stops with an error: cannot access local variable 'y'. Click the line that causes it.
    line 10
    Inside a method, y on its own is a new local variable, not the star's. self.y -= self.speed changes this star's y.
  5. Where this leads: A game has 3 kinds of thing, each with move() and draw(). What does update() need?
    A loop for each list that calls move()
    Each object knows how to move; update() only asks each one to. New kinds of thing add a class and a short loop, not more code in update().

Solutions

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

Modify › A colour each

import random

class Star:
    def __init__(self, x):
        self.x = x
        self.y = 100
        self.speed = random.randint(5, 15) / 10
        self.colour = random.choice(["rgb(255,210,0)", "rgb(255,120,160)", "rgb(120,220,255)"])

    def move(self):
        self.y -= self.speed
        if self.y < -100:
            self.y = 100
            self.x = random.randint(-90, 90)

    def draw(self):
        screen.fillRound(self.x, self.y, 8, 8, self.colour)

def init():
    global stars
    stars = []
    for i in range(4):
        stars.append(Star(-60 + i * 40))

def update():
    for star in stars:
        star.move()

def draw():
    screen.clear("rgb(10,10,40)")
    for star in stars:
        star.draw()

Modify › More stars

import random

class Star:
    def __init__(self, x):
        self.x = x
        self.y = 100
        self.speed = random.randint(5, 15) / 10

    def move(self):
        self.y -= self.speed
        if self.y < -100:
            self.y = 100
            self.x = random.randint(-90, 90)

    def draw(self):
        screen.fillRound(self.x, self.y, 8, 8, "rgb(255,210,0)")

def init():
    global stars
    stars = []
    for i in range(8):
        stars.append(Star(-84 + i * 24))

def update():
    for star in stars:
        star.move()

def draw():
    screen.clear("rgb(10,10,40)")
    for star in stars:
        star.draw()

another class

import random

class Star:
    def __init__(self, x):
        self.x = x
        self.y = 100
        self.speed = random.randint(5, 15) / 10

    def move(self):
        self.y -= self.speed
        if self.y < -100:
            self.y = 100
            self.x = random.randint(-90, 90)

    def draw(self):
        screen.fillRound(self.x, self.y, 8, 8, "rgb(255,210,0)")

class Cloud:
    def __init__(self, y):
        self.x = -120
        self.y = y

    def move(self):
        self.x += 0.3
        if self.x > 120:
            self.x = -120

    def draw(self):
        screen.fillRound(self.x, self.y, 30, 12, "rgb(200,200,220)")

def init():
    global stars, clouds
    stars = []
    for i in range(4):
        stars.append(Star(-60 + i * 40))
    clouds = [Cloud(60), Cloud(20)]

def update():
    for star in stars:
        star.move()
    for cloud in clouds:
        cloud.move()

def draw():
    screen.clear("rgb(10,10,40)")
    for cloud in clouds:
        cloud.draw()
    for star in stars:
        star.draw()

Stretch and support

Stretch: Give stars a size as well as a colour, or make some stars twinkle by changing their size in move().

Support: Give students the Cloud class's __init__ and ask them only for move() and draw().

Exit ticket

Why does each star have self.x and self.y?

So that each star remembers where it is; draw() paints it there and move() changes it, for that star only.

What each step is for

Where it leads

Next lesson: catching stars with the paddle and keeping score, which is the turtle course's Catch the turtle in a game engine.