Skip to main content

Stage 4: Spawn the Alien Fleet

Course progressStage 4 of 10
~35 min
One game, one Trinket

Keep building in the workspace on the right.

This stage is part of the same Python Arcade project you started in Setup. Type each new code block into the Trinket rail and keep building on the last stage.

Build

a grid of enemy turtles lined up like an arcade fleet

Learn

how nested loops build rows and columns from one helper

Ship

a multi-row alien fleet waiting at the top of the screen

The big idea

Last stage you built the most reusable pattern in the whole course: a list of game objects + a game loop that walks the list. Today we use it again. Aliens are temporary game objects, just like lasers — they appear, move, and get cleaned up.

What changes is the layout. Lasers spawn one at a time from the cannon. Aliens need to start as a formation: multiple rows and columns lined up near the top of the screen, like a classic space-invader fleet.

Stage 3 — Lasers: Stage 4 — Aliens:

player presses space -> make a grid once
│ │
▼ ▼
fire_laser() spawn_alien_fleet()
│ │
▼ ▼
lasers.append(...) aliens.append(...) for each alien

The list, the append, and the cleanup are still reused. A fleet is not a new data structure yet. It is regular alien Turtles added to the same aliens list, one alien at a time.

The new tool today is a nested loop. One loop walks through Y positions for rows. Inside it, a second loop walks through X positions for columns. That pair of loops is how one helper turns into a full arcade formation.

Before you start

Your cannon should move, and pressing space should fire lasers.

Build it

Step 1 — Decide the alien rules

Just like the laser cap, we make the alien numbers easy to tune. ALIEN_COLUMNS are the X positions across the screen. ALIEN_ROWS are the Y positions stacked near the top.

Add these near your other constants:

ALIEN_COLUMNS = [-240, -120, 0, 120, 240]
ALIEN_ROWS = [TOP - 40, TOP - 90, TOP - 140]
aliens = []

aliens = [] is the empty list, exactly like lasers = [] from Stage 3. The shape of the pattern is already familiar.

ALIEN_COLUMNS is the column map. Each number is an X position. ALIEN_ROWS is the row map. Each number is a Y position. Together, they make a grid.

Step 2 — Write the alien helper

This helper builds one alien — a new Turtle, colored and shaped, dropped at one column in the row — and puts it in the list. From that moment on, the game owns the alien through the list.

Build this helper above the game loop:

Your turn

Write the alien like a laser

Before looking at the full helper, write the first four lines of make_alien(x, y) from memory by reusing the pattern of fire_laser(), not the exact values.

Need a hint?

Build the Turtle, lift the pen, choose color and shape, choose a position, then append it to `aliens`.

Stuck? Compare carefully
Answer check
Debug compare only

main.py

Write the first four lines from the laser pattern first, then reveal to check the whole function.

def make_alien(x, y):
alien = turtle.Turtle()
alien.penup()
alien.color("lime")
alien.shape("circle")
alien.setposition(x, y)
aliens.append(alien)

The helper takes x and y as parameters. That means the row function can decide where aliens go, and this helper only handles how one alien is built.

Step 3 — Spawn the full fleet

Now write the function that makes the formation. The outside loop picks a row. The inside loop fills that row with aliens across every column.

Stuck? Compare carefully
Answer check
Debug compare only

main.py

Write the loop yourself first, then reveal to check.

def spawn_alien_fleet():
for y in ALIEN_ROWS:
for x in ALIEN_COLUMNS:
make_alien(x, y)

This is the moment the aliens line up. Three Y positions times five X positions makes fifteen aliens, all still stored in one flat aliens list.

Step 4 — Create the fleet before the loop

Now wire the fleet into the program. We want a starting formation, so call the function once before the game loop begins.

Put this after your key bindings and draw_cannon() call, just before while True::

Think first

Nested loop size

If `ALIEN_COLUMNS` has 5 numbers and `ALIEN_ROWS` has 3 numbers, how many aliens does `spawn_alien_fleet()` make?

Check your thinking

15 aliens. The nested loop makes one alien for every row-column pair.

spawn_alien_fleet()

Run the game. A multi-row fleet should appear near the top. It will not move yet — that happens in Stage 5 — but it should look like a real arcade formation, not one overlapping row.

Optional — Skin the circle aliens with sprite files

The circle aliens are the reliable baseline. After they spawn correctly, you can make those same alien Turtles use the colored pixel sprites from the hero image.

If you uploaded the alien GIFs in Setup, add this block near your alien constants:

Python code task
Optional polish

main.py

Where it goes: Put this near the alien constants, immediately after `aliens = []`.

Skip this if you are keeping circle aliens.

ALIEN_SPRITES = [
"alien-purple.gif",
"alien-blue.gif",
"alien-green.gif",
"alien-yellow.gif",
"alien-red.gif",
]

USE_ALIEN_SPRITES = True

try:
for sprite in ALIEN_SPRITES:
screen.addshape(sprite)
except:
USE_ALIEN_SPRITES = False

Then replace the appearance lines inside make_alien(x, y) with this version. The alien is still a Turtle in the aliens list; only its visual skin changes:

Python code task
Optional polish

main.py

Where it goes: Inside `make_alien(x, y)`, replace only the existing `alien.color(...)` and `alien.shape(...)` lines.

Keep the rest of `make_alien(x, y)` in the same order.

if USE_ALIEN_SPRITES:
alien.setheading(270)
alien.shape(ALIEN_SPRITES[len(aliens) % len(ALIEN_SPRITES)])
else:
alien.color("lime")
alien.shape("circle")

Run it. If the uploads worked, aliens appear in the same purple, blue, green, yellow, and red pixel style as the hero image. The setheading(270) line points sprite aliens downward, matching the direction they move in Stage 5. If they appear as lime circles, keep going — the fallback means the game is still playable.

File order checkpoint

By the end of Stage 4, your main.py should be ordered like this:

  1. Imports at the top: turtle and time
  2. Screen setup and constants, including ALIEN_COLUMNS, ALIEN_ROWS, and aliens = []
  3. Optional alien sprite setup, if you are using GIF skins
  4. Helper functions, including make_alien(x, y) and spawn_alien_fleet()
  5. Key bindings and the existing draw_cannon() call
  6. spawn_alien_fleet() once before the game loop
  7. The game loop, with the Stage 3 laser loop still inside it

Understand it

The whole stage is a lesson in pattern reuse. Look at your code side-by-side: aliens is to lasers what make_alien is to fire_laser. The layout changed, the appearance changed, the position rules changed — but the shape of the code is identical. Recognizing this is a real coding superpower. Next time you need an extra system in a game, ask: "is this a list of things that appear and disappear?" If yes, you already know the bones.

Rows are built from individual aliens on purpose. We could store each row as its own list, but that would make Stage 6's collision loop harder for no benefit. A flat aliens list means every later system can ask the same simple question: "for each alien, what should happen?"

The important detail is that spawn_alien_fleet() runs once, outside the loop. If it ran inside while True:, the program would create a new fleet every frame and flood the screen. If it only made one Y position, the player would see one row. The two lists are what make the formation: ALIEN_COLUMNS controls width, and ALIEN_ROWS controls height.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first

Add one more number to ALIEN_ROWS, like TOP - 190. Before you run, predict how many aliens the fleet will have. Now run it. Did the formation grow the way you expected?

Compare

Temporarily move spawn_alien_fleet() inside the game loop. Run for just a second, then stop it. What happened? Put it back before the loop. Why does one line's position change the whole game?

Connect

Stage 5 makes the aliens move. Look at your Stage 3 laser game-loop code — specifically the for laser in lasers[:]: block. What needs to change for aliens? What stays exactly the same?

Test your stage

Stuck? Compare carefully
Answer check
Debug compare only

required Stage 4 code

Where it goes: Compare this with the Stage 4 pieces in your file: alien constants before the helper functions, `spawn_alien_fleet()` before the game loop, and the Stage 3 laser loop still inside the game loop.

Use this after you compare the alien pattern to the laser pattern.

ALIEN_COLUMNS = [-240, -120, 0, 120, 240]
ALIEN_ROWS = [TOP - 40, TOP - 90, TOP - 140]
aliens = []

def make_alien(x, y):
alien = turtle.Turtle()
alien.penup()
alien.color("lime")
alien.shape("circle")
alien.setposition(x, y)
aliens.append(alien)

def spawn_alien_fleet():
for y in ALIEN_ROWS:
for x in ALIEN_COLUMNS:
make_alien(x, y)

spawn_alien_fleet()

while True:
# Stage 3 laser loop stays here.
time.sleep(0.02)
screen.update()
  • The fleet appears without anyone pressing a key.
  • The fleet has multiple rows and five clean columns.
  • The cannon and lasers still work.
  • The screen does not instantly flood with duplicate fleets.
  • Optional sprite check: uploaded alien GIFs render as colored pixel aliens, or the game safely falls back to lime circles.
  • Design check. Does the starting formation read like a space-invader fleet, or does it look too sparse?
  • From memory. Without looking, write the nested loop that builds the fleet. Compare — did you loop through rows first, then columns?

If it breaks

  • Only one row appears. Check that you created ALIEN_ROWS with multiple Y positions, and that spawn_alien_fleet() has two loops: for y in ALIEN_ROWS: and inside it for x in ALIEN_COLUMNS:.
  • No aliens appear. Make sure spawn_alien_fleet() is called once before while True:. Defining the function is not enough; you also have to call it.
  • The fleet appears off-screen. Check the numbers in ALIEN_COLUMNS. They should stay between LEFT + 40 and RIGHT - 40; with the Stage 1 screen, [-240, -120, 0, 120, 240] fits.
  • The fleet appears too low or too high. Tune the numbers in ALIEN_ROWS. They should be near the top but still visible.
  • The fleet spawns but the rest of the game freezes. Check that spawn_alien_fleet() is not in an infinite loop by mistake. It should use two short for loops, not its own while True:.
  • The sprite aliens do not show. Every filename must match exactly. If one upload is missing or renamed, USE_ALIEN_SPRITES falls back to the circle alien so the game does not crash.