← Games with microStudio

Stars as objects

Bring the Star class from Objects with turtles into a game engine: each star moves itself in update() and draws itself in draw(). Change colours and numbers, then add a class of your own.

Your falling-stars game from the turtle course, rebuilt in a game engine: same class, same methods, smoother and faster.

In Objects with turtles each star was an object with its own turtle, speed and move() method. A game engine has no turtles, so a star keeps its own position in self.x and self.y, and gets a draw() method that paints it where it is. Everything else is what you already know.

PredictRead the code and say what it will do before you run anything. A wrong guess is fine: it shows you what to look for.

Predict

game.py
class Star:
    def __init__(self, x):
        self.x = x
        self.y = 100

stars = []
for i in range(4):
    stars.append(Star(-60 + i * 40))
print(stars[2].x)

Which i made stars[2]?

What does it print?

RunRun it and compare the result with your prediction.

Run

Put this game in a new microStudio project (or replace your code) and run it. Each frame, update() tells every star to move, and draw() tells every star to draw itself.

game.py
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(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()
Play itClick the game to play. Make your own on microstudio.dev.

InvestigateTrace how each line of code connects to what you see.

Investigate

game.py
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(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()

The turtle version, from Objects with turtles:

class Star:
    def __init__(self, x):
        self.turtle = Turtle()
        self.turtle.goto(x, 200)
        self.speed = random.randint(3, 7)

    def move(self):
        self.turtle.forward(self.speed)

Who does what.

A star that cannot move.

This is the turtle version of Star. What has the microStudio version got instead of self.turtle?

Match each line with what it does.

self.y -= self.speed
for star in stars: star.move()
screen.fillRound(self.x, self.y, 8, 8, ...)
stars.append(Star(-60 + i * 40))

This stops with an error: cannot access local variable 'y'. Click the line that causes it.

ModifyChange the code on purpose and check the result.

Modify

game.py
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(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()

Give each star its own colour, picked at random when it is made. The game on this page does.

Need a hint?

Store a colour in init: self.colour = random.choice([...]) with two or three colours.

Another hint

In draw(), use self.colour instead of "rgb(255,210,0)".

Make 8 stars, spread across the screen.

Need a hint?

range(4) makes 4 stars. Change it to range(8).

Another hint

Space them out: -84 + i * 24 fits 8 stars across.

Play itClick the game to play. Make your own on microstudio.dev.

MakeBuild something new using what you have learned. Expect a few tries; that is normal.

Another class

Add a class of your own, with its own __init__, move() and draw(): clouds that drift sideways, snowflakes that wobble, a moon that grows. Keep its objects in their own list, and move and draw them in update() and draw(). The game on this page adds slow clouds behind the stars.

game.py
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(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()

# Your own class: something else on the screen with its own move and draw methods.
Play itClick the game to play. Make your own on microstudio.dev.

Info

Where this leads

Real game engines are built this way: every enemy, bullet and cloud is an object with its own update and draw. Next: a paddle that catches the stars, with a score.

A game has 3 kinds of thing, each with move() and draw(). What does update() need?

For teachers

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. About 50 minutes.

Open the teacher guide: answers, solutions, slides and a worksheet.

Students will be able to

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

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().

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.

What each step is for

Now you can
Next lesson4. Catch and scorePut the paddle and the stars together: a star that touches the paddle scores a point and starts again. Add lives, a game over and a restart, then a power-up of your own.