Session 9: Boss Battle
The boss is waiting for you. It moves back and forth, shoots bullets and gets more dangerous as its HP drops. You shoot back, keep track of its HP on a bar, and survive three phases. This is the hardest session, and the most satisfying one if you make it through.
What you’ll learn today
- Drawing an HP bar on the screen
- A state machine: the boss behaves differently in each phase
- Making the boss shoot with a bullet timer
- Activating phases at HP thresholds
Step 0: Setup
- Open Thonny.
- Download the starter via this link, unpack the ZIP and open
main.pyin Thonny. - Click Run. You see the boss at the top, your ship at the bottom. No movement, no bullets yet.
- Problems? Ask a coach.
Step 1: Making the boss move
The boss moves back and forth across the screen. When it hits the edge, it turns around.
Find # STEP 1 and add:
boss_rect.x += boss_speed
# Turn around at the edge
if boss_rect.right >= WIDTH or boss_rect.left <= 0:
boss_speed = -boss_speedboss_speed = 3 is already at the top. Click Run: the boss thunders from left to right!
Moving the player and shooting (find # PLAYER):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
player_rect.x -= PLAYER_SPEED
if keys[pygame.K_RIGHT] and player_rect.right < WIDTH:
player_rect.x += PLAYER_SPEED
# Shoot (find # SHOOT in the event loop):
player_bullets.append(pygame.Rect(player_rect.centerx - 3, player_rect.top - 15, 6, 15))Step 2: ✅ Basic: hitting the boss and the HP bar
Collision player bullet with boss:
Find # STEP 2:
for b in player_bullets[:]:
b.y -= 8
if b.y < 0:
player_bullets.remove(b)
continue
pygame.draw.rect(screen, YELLOW, b)
if b.colliderect(boss_rect):
player_bullets.remove(b)
boss_hp -= 1
if boss_hp <= 0:
running = False # player wins!Drawing the HP bar (find # HP BAR):
# Background of the bar
pygame.draw.rect(screen, DARK_RED, (10, 10, 300, 20))
# Filled bar based on the current HP
breedte = int(300 * boss_hp / BOSS_MAX_HP)
pygame.draw.rect(screen, RED, (10, 10, breedte, 20))
# Label
hp_surf = font.render(f"Boss HP: {boss_hp}", True, WHITE)
screen.blit(hp_surf, (320, 10))Click Run. Shoot at the boss: the HP bar shrinks!
Step 3: ⭐ Stretch: the boss shoots back
The boss fires a bullet downwards every N frames.
Find # STEP 3:
boss_shoot_timer += 1
if boss_shoot_timer >= boss_shoot_interval:
boss_shoot_timer = 0
boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))Updating boss bullets:
for b in boss_bullets[:]:
b.y += 6
if b.y > HEIGHT:
boss_bullets.remove(b)
continue
pygame.draw.rect(screen, ORANGE, b)
if b.colliderect(player_rect):
boss_bullets.remove(b)
player_lives -= 1
if player_lives <= 0:
running = FalseDraw player_lives as hearts or red blocks at the bottom of the screen.
Step 4: 🔥 Expert: three phases
Now the boss reacts to its HP:
- Phase 1 (HP 100 to 50): normal behaviour
- Phase 2 (HP 50 to 25): move faster, shoot more often
- Phase 3 (HP < 25): maximum speed, double bullets
Find # STEP 4:
if boss_hp > 50:
boss_phase = 1
boss_speed_abs = 3
boss_shoot_interval = 60
elif boss_hp > 25:
boss_phase = 2
boss_speed_abs = 5
boss_shoot_interval = 35
else:
boss_phase = 3
boss_speed_abs = 7
boss_shoot_interval = 20
# Adjust the speed without changing direction:
boss_speed = boss_speed_abs * (1 if boss_speed > 0 else -1)Phase 3: double bullets (add this in the shoot code):
if boss_phase == 3:
boss_bullets.append(pygame.Rect(boss_rect.left + 10, boss_rect.bottom, 8, 16))
boss_bullets.append(pygame.Rect(boss_rect.right - 18, boss_rect.bottom, 8, 16))
else:
boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))Win screen at boss_hp <= 0:
screen.fill(BLACK)
win = font.render("BOSS DEFEATED!", True, YELLOW)
screen.blit(win, (WIDTH // 2 - win.get_width() // 2, HEIGHT // 2))
pygame.display.flip()
pygame.time.wait(3000)Showcase
Show your game to a coach and a buddy. Who reaches phase 3 and survives?
See you next time!
“Next time: your own game, from scratch, completely your own idea.”
Take it home
Try one of these extensions at home:
- Easy: change the colour of the boss per phase (green → orange → red).
- Medium: add a score: the faster you beat the boss, the more points.
- Hard: let the boss shoot diagonal bullets in phase 2 too (slanted left and right).
- Very hard: add a second player who can join in with WASD keys.