Learning Goals
3 minBy the end of this lesson you can:
- Build a list of Actors using a
forloop andlist.append(). - Update all actors in one loop inside
update(). - Draw all actors in one loop inside
draw(), producing a multi-sprite scene.
Warm-Up · Lists Review
5 minYou built lists back in Level 1. What does this code print?
names = ["Aisyah", "Wei Jie", "Priya"] for name in names: print("Hello,", name)
Show the answer
Output
Hello, Aisyah Hello, Wei Jie Hello, Priya
The loop visits each item once. Today we do the same thing with a list of Actors instead of names.
New Concept · Actors in a List
12 minThink of a list of actors like a class register: every student is in the list, and when the teacher calls the roll they visit each student in order. Our for loop is the roll-call.
Building the list
Create an empty list, then append one Actor at a time:
stars = [] for i in range(5): star = Actor("alien") star.x = i * 100 star.y = 200 stars.append(star)
After this loop, stars holds five Actor objects at x = 0, 100, 200, 300, 400.
Drawing all of them
def draw(): screen.fill("black") for star in stars: star.draw()
One loop, one call per actor. Adding a sixth star to the list automatically gets drawn too — no extra code.
Updating all of them
def update(dt): for star in stars: star.x += 150 * dt if star.x > WIDTH: star.x = 0
Every actor moves at 150 px/s and wraps independently. Each actor keeps its own .x value.
Why it matters
Lists + loops unlock enemy waves, bullet streams, coin fields, and particle effects — everything that makes a game feel alive. The pattern never changes: build the list once, loop over it in update() and draw().
Worked Example · Kuih Parade
12 minThe story
Nurul wants four kuih sprites sliding across the screen at the same speed, evenly spaced. Save this as kuih_parade.py:
# kuih_parade.py — four actors in a list import pgzrun WIDTH = 600 HEIGHT = 400 TITLE = "Kuih Parade" kuih_list = [] for i in range(4): k = Actor("alien") k.x = i * 150 k.y = 200 kuih_list.append(k) def draw(): screen.fill("hotpink") for k in kuih_list: k.draw() screen.draw.text( f"{len(kuih_list)} kuih on screen", topleft=(10, 10), fontsize=22, color="white", ) def update(dt): for k in kuih_list: k.x += 120 * dt if k.x > WIDTH: k.x = 0 pgzrun.go()
What you will see
Notice the label uses len(kuih_list) — so if you change the range to 6, the label updates automatically.
Try It Yourself
13 minChange the range in kuih_parade.py to spawn 8 sprites instead of 4. Adjust the spacing (i * 75) so they all fit on screen at the start. Run it and confirm all 8 appear.
Hint
for i in range(8): k = Actor("alien") k.x = i * 75 k.y = 200 kuih_list.append(k)
Give each actor a different y position by using the loop counter: k.y = 50 + i * 60. The sprites should form a staircase pattern going down the screen.
Hint
for i in range(4): k = Actor("alien") k.x = i * 150 k.y = 50 + i * 60 kuih_list.append(k)
Mini-Challenge · The Missing Sprites
8 minDaniel's script should show three sprites but only one appears. The concept combines lists (today) with the position setting from PZ-07. Find the two bugs:
# daniel_trio.py — buggy
import pgzrun
WIDTH = 600
HEIGHT = 400
aliens = []
for i in range(3):
a = Actor("alien")
a.x = 100
a.y = 200
aliens.append(a)
def draw():
screen.fill("black")
for a in aliens:
a.draw()
def update(dt):
for a in aliens:
a.x = a.x + 80 * dt
pgzrun.go()It works if…
three clearly separate sprites are visible and all slide to the right
Show the fix
# daniel_trio.py — fixed import pgzrun WIDTH = 600 HEIGHT = 400 aliens = [] for i in range(3): a = Actor("alien") a.x = i * 150 + 75 # spread them out using the loop counter a.y = 200 aliens.append(a) def draw(): screen.fill("black") for a in aliens: a.draw() def update(dt): for a in aliens: a.x += 80 * dt if a.x > WIDTH: a.x = 0 pgzrun.go()
The fix: use i * 150 + 75 for a.x so the three sprites start at different positions. A wrap check was also added so they reappear.
Recap
3 minA list of Actors is the standard way to manage multiple sprites. Build the list once with a for loop, then loop over it in both update() and draw(). Each Actor stores its own position, so they move independently without any extra effort.
Vocabulary Card
- sprite list
- A Python list that holds Actor objects. One loop processes all of them at once.
- list.append(item)
- Adds one item to the end of a list. Used to populate the sprite list during setup.
- for actor in actors
- Visits each Actor in the list in order — same pattern as any other Python for loop.
- len(list)
- Returns the number of items in a list. Handy for on-screen counters and spawn logic.
Homework
4 minCreate star_field.py. Spawn five stars in a vertical column (same x, y values at 60, 140, 220, 300, 380). Make them all slide to the right at 100 px/s using dt and wrap. Bring a screenshot to the next class.
Stretch. Give each star a slightly different y position by adding a random offset of ±20 px using random.randint(-20, 20). Import random at the top.
Sample · star_field.py
# star_field.py — five stars in a column, sliding right import pgzrun WIDTH = 600 HEIGHT = 400 y_positions = [60, 140, 220, 300, 380] stars = [] for y in y_positions: s = Actor("alien") s.x = 50 s.y = y stars.append(s) def draw(): screen.fill("navy") for s in stars: s.draw() def update(dt): for s in stars: s.x += 100 * dt if s.x > WIDTH: s.x = 0 pgzrun.go()
Your y positions and background colour may differ. The key pattern: build the list once, loop in both update and draw.