Unit 12.3A · Term 3

Full Game Project: "Catch the Data"

It's time to bring it all together! We will build a complete game called "Catch the Data" where the player moves a basket to catch falling data packets while avoiding viruses.

Learning Objectives

  • 12.5.3.9 Create a simple computer game

Lesson Presentation

12.3A-full-game.pdf · Slides for classroom use

Game Design

The Blueprint

  • Player: Only moves left/right at the bottom.
  • Packets (Green): Fall from top. +10 Score.
  • Viruses (Red): Fall from top. Game Over if hit.
  • Win Condition: Reach 500 points.
  • Lose Condition: Hit a virus.

Complete Code

Copy this code into a new file catch_the_data.py and run it.

import pygame import sys import random # --- Constants --- WIDTH, HEIGHT = 800, 600 FPS = 60 WHITE = (255, 255, 255) BLACK = (0, 0, 0) GREEN = (0, 200, 100) RED = (200, 50, 50) BLUE = (50, 100, 255) # --- Classes --- class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.Surface((60, 40)) self.image.fill(BLUE) self.rect = self.image.get_rect(center=(WIDTH//2, HEIGHT - 50)) self.speed = 8 def update(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.rect.x -= self.speed if keys[pygame.K_RIGHT]: self.rect.x += self.speed # Keep on screen self.rect.clamp_ip(pygame.Rect(0, 0, WIDTH, HEIGHT)) class FallingObject(pygame.sprite.Sprite): def __init__(self, obj_type): super().__init__() self.type = obj_type size = 30 if obj_type == "packet" else 40 self.image = pygame.Surface((size, size)) if self.type == "packet": self.image.fill(GREEN) self.speed = random.randint(4, 7) else: self.image.fill(RED) self.speed = random.randint(6, 9) self.rect = self.image.get_rect( center=(random.randint(20, WIDTH-20), -20) ) def update(self): self.rect.y += self.speed if self.rect.top > HEIGHT: self.kill() # --- Setup --- pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Catch the Data!") clock = pygame.time.Clock() font = pygame.font.SysFont("Arial", 28) big_font = pygame.font.SysFont("Arial", 72) # Game State player = Player() all_sprites = pygame.sprite.Group(player) packets = pygame.sprite.Group() viruses = pygame.sprite.Group() score = 0 game_state = "playing" # playing, won, lost # Timer for spawning SPAWN_EVENT = pygame.USEREVENT + 1 pygame.time.set_timer(SPAWN_EVENT, 500) # Every 500ms # --- Main Loop --- running = True while running: # 1. Event Handling for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if game_state == "playing": if event.type == SPAWN_EVENT: # 80% chance for packet, 20% for virus if random.random() < 0.8: obj = FallingObject("packet") packets.add(obj) all_sprites.add(obj) else: obj = FallingObject("virus") viruses.add(obj) all_sprites.add(obj) # Restart logic if game_state != "playing" and event.type == pygame.KEYDOWN: if event.key == pygame.K_r: # Reset game game_state = "playing" score = 0 all_sprites.empty() packets.empty() viruses.empty() player = Player() all_sprites.add(player) # 2. Update if game_state == "playing": all_sprites.update() # Check collisions # Packet hits hits = pygame.sprite.spritecollide(player, packets, True) if hits: score += 10 * len(hits) # Virus hits hits = pygame.sprite.spritecollide(player, viruses, False) if hits: game_state = "lost" # Win condition if score >= 500: game_state = "won" # 3. Render screen.fill(BLACK) if game_state == "playing": all_sprites.draw(screen) # Draw UI score_text = font.render(f"Data: {score}/500", True, WHITE) screen.blit(score_text, (10, 10)) elif game_state == "lost": text = big_font.render("SYSTEM INFECTED!", True, RED) rect = text.get_rect(center=(WIDTH//2, HEIGHT//2)) screen.blit(text, rect) sub = font.render("Press R to Reboot", True, WHITE) sub_rect = sub.get_rect(center=(WIDTH//2, HEIGHT//2 + 60)) screen.blit(sub, sub_rect) elif game_state == "won": text = big_font.render("UPLOAD COMPLETE!", True, GREEN) rect = text.get_rect(center=(WIDTH//2, HEIGHT//2)) screen.blit(text, rect) sub = font.render(f"Final Score: {score}. Press R to Play Again", True, WHITE) sub_rect = sub.get_rect(center=(WIDTH//2, HEIGHT//2 + 60)) screen.blit(sub, sub_rect) pygame.display.flip() clock.tick(FPS) pygame.quit() sys.exit()

Code Breakdown

1. Game States

We use a variable game_state separate logic for playing, winning, and losing. When the game ends, we stop updating sprites and stop spawning items, but keep the loop running to show the "Game Over" text and wait for a restart key.

2. Timers (USEREVENT)

Instead of relying on random chance every frame (which varies with FPS), we use pygame.time.set_timer() to trigger a customer event exactly every 500 milliseconds. This makes spawning consistent.

3. Inheritance

Use a single FallingObject class for both packets and viruses. We pass a type argument to __init__ to decide if it's green (good) or red (bad). This saves writing two nearly identical classes.

Project Extensions

Apply

Add a "Golden Packet" that spawns rarely gives +50 points and plays a sound.

Create

Add difficulty scaling: Make objects fall faster as the score gets higher.

Create

Add lives: Allow the player to hit 3 viruses before Game Over. Display lives as icons.