In Stage 5 you started shooting bullets. In Stage 6 you finally have something to shoot AT: five red aliens that fall from random spots above the screen.
Before we dive in โ can you remember from Lesson 5 (Bullets)?
One variable that holds many items in order. Like a shopping basket โ you can add items, remove items, and loop through them. bullets = [] starts an empty one.
bullets[:] when removing items in a loop?It makes a quick copy to loop over so we can safely .remove() from the original list. Without the copy, Python gets confused mid-loop.
โถ
โ
You're on Stage 6 of 10. The Body of the rocket is almost done!
We could write five separate pygame.Rect(...)
lines, but that's boring โ and it would be 100 lines if we ever wanted 100
aliens. Instead we use a for loop to build the
list once, and then change the number whenever we want more.
enemies = []
enemy_speed = 2
for i in range(5): # five times...
e = pygame.Rect(random.randint(0, WIDTH - 50), # random x across the top
random.randint(-300, 0), # random y ABOVE the screen
50, 50) # 50ร50 alien
enemies.append(e) # add it to the list
๐ฒ random.randint(a, b) gives a random whole number
from a up to b. Negative
y values mean the enemy starts above the visible window โ so they slide
down and look like they're coming from space.
With bullets we removed them when they flew off the screen. With enemies we do something cleverer: when one reaches the bottom, we send it back to the top at a new random spot. The list always has exactly 5 enemies, but they keep coming forever โ much smoother than spawning new objects every second.
for e in enemies:
e.y += enemy_speed
if e.y > HEIGHT: # reached the bottom?
e.y = random.randint(-200, -50) # send it back up
e.x = random.randint(0, WIDTH - 50) # at a new random x
๐ก Think of it like a treadmill: the same five aliens loop forever. Recycling is one of the most-used tricks in game programming.
Now that we have bullets AND enemies on the screen, we can ask pygame the
most important question in any shooter: "did anything hit anything?"
Every Rect has a built-in helper called .colliderect()
that returns True if two rectangles overlap.
for b in bullets[:]:
for e in enemies:
if b.colliderect(e): # did this bullet touch this enemy?
bullets.remove(b)
e.y = random.randint(-200, -50) # recycle the alien
e.x = random.randint(0, WIDTH - 50)
score += 1
We'll formally add score in Lesson 7. For now,
just notice the pattern: for each bullet, check every enemy.
# Stages 1โ5 already in place...
import pygame
import random
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Galaxy Defender")
clock = pygame.time.Clock()
YELLOW = (255, 215, 0)
RED = (255, 0, 0)
SPACE = (0, 0, 50)
# ๐ Cartoon ship (from Lesson 5)
def draw_ship(s, x, y):
pygame.draw.polygon(s, (0, 230, 100),
[(x+30,y),(x+60,y+40),(x+40,y+30),(x+20,y+30),(x,y+40)])
pygame.draw.circle (s, (100, 200, 255), (x+30, y+18), 6)
pygame.draw.polygon(s, (255, 100, 0), [(x+25,y+30),(x+35,y+30),(x+30,y+42)])
# โจ Fiery laser (new this lesson!)
def draw_laser(s, b):
pygame.draw.ellipse(s, (255, 100, 0), (b.x-3, b.y-5, b.width+6, b.height+10)) # glow
pygame.draw.ellipse(s, (255, 220, 0), b) # core
player = pygame.Rect(370, 520, 60, 40)
player_speed = 5
bullets = []
bullet_speed = 10
# Stage 6 โ Enemies โจ
enemies = []
enemy_speed = 2
for i in range(5):
e = pygame.Rect(random.randint(0, WIDTH - 50),
random.randint(-300, 0),
50, 50)
enemies.append(e)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
bullets.append(pygame.Rect(player.x + 27, player.y, 6, 15))
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player.x > 0:
player.x -= player_speed
if keys[pygame.K_RIGHT] and player.x < WIDTH - 60:
player.x += player_speed
# move bullets
for b in bullets[:]:
b.y -= bullet_speed
if b.y < 0:
bullets.remove(b)
# move + recycle enemies
for e in enemies:
e.y += enemy_speed
if e.y > HEIGHT:
e.y = random.randint(-200, -50)
e.x = random.randint(0, WIDTH - 50)
# collisions (sneak peek of Lesson 7)
for b in bullets[:]:
for e in enemies:
if b.colliderect(e):
if b in bullets:
bullets.remove(b)
e.y = random.randint(-200, -50)
e.x = random.randint(0, WIDTH - 50)
screen.fill(SPACE)
draw_ship(screen, player.x, player.y) # ๐ cartoon ship
for b in bullets:
draw_laser(screen, b) # โจ fiery laser
for e in enemies:
pygame.draw.rect(screen, RED, e) # plain red squares (we cartoon them in L7)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Run it. Five red aliens drift down from random spots. Move LEFT/RIGHT, hit SPACE to shoot, and watch the aliens disappear and reappear at the top when you hit them. You just built the heart of a real shooter. ๐พ
๐ฎ Want to play with more code? Scroll down to the Lesson 6 Code Library (6 enemy games). Copy any program, paste it into the editor below, and press the green โถ Run button.
Type the code above into the editor, then click โถ Run.
range(5) to range(15).enemy_speed = 2 to 8.50, 50 at the end of the Rect to 20, 20. (Don't forget to update WIDTH - 50 to WIDTH - 20.)enemies, then pick a random one in the collision block.Print these, keep them open in another tab, or download them to your computer.
๐ Lesson 6 Code Library โ 6 brand-new pygame mini-games all about enemies, spawning, recycling, and collisions: One Falling Enemy, Recycle the Enemy, Five Enemies, Asteroid Field, Touch Detector, Mini Defender.
๐ Lesson 6 Code Library (6 enemy games) ๐จ Sprite Bonus (visual polish) ๐ Lesson 5 Code Library ๐ Lesson 4 Code Library ๐ Lesson 3 Code Library ๐ Lesson 2 Code Library ๐ Lesson 1 Code Library
๐บ๏ธ The big-picture handouts โ keep these by your side for the whole course.
๐ Rocket Ladder ๐ Code Comic ๐ Pixel Cheat Sheet ๐ Code Recipe ๐ผ๏ธ 6 Parts of a Turtle Program
๐ค Want to try your own idea? Ask an AI like Claude or ChatGPT something like "Write me a short pygame program where 10 aliens fall from the top of the screen", then paste the code into the Trinket above and click Run.