Module 20 of 20 Phase: Capstone

The Final Capstone
Plan, Build & Ship a Real Game

Everything from Module 1 to Module 19 exists to build one complete, shipped game. This capstone brief walks you through a design document, folder organization, tying your systems together, testing, and packaging for release.

🏆
Full Project
Capstone build
1-3 wks
Suggested time
📊
Advanced
Difficulty
🎓
Certificate
On completion
Step 1

Write a Game Design Document

Before writing code, define the game on paper. A one-page GDD prevents scope creep and keeps the project finishable:

💡
Concept
One sentence: what is the game? ("A top-down dungeon crawler where you dash between rooms collecting keys.")
🎮
Core Mechanics
The 3-4 verbs the player does most: move, dash, attack, collect. Everything else supports these.
⌨️
Controls
WASD/arrows to move, Space to dash, Left-click to attack — exact key bindings, decided up front.
🏁
Win/Lose Conditions
What ends the game? (all keys collected = win, health reaches 0 = lose/game over).
Step 2

Organize Assets & Code

Apply Module 18's architecture from day one — retrofitting structure onto a messy prototype later costs far more time than starting clean.

project structure
my_game/
  main.py
  config.py
  assets.py
  scenes/
    menu_scene.py
    play_scene.py
    game_over_scene.py
  entities/
    player.py
    enemy.py
    particle.py
  assets/
    images/
    sounds/
  README.md
Step 3

Code the Core Mechanics — A Starter Scene Skeleton

Combine the Scene pattern (Module 18), sprite groups (Module 6), movement (Module 8) and the event loop (Module 2) into one minimal but complete shell you can build your capstone on top of:

main.py
import pygame
from config import SCREEN_WIDTH, SCREEN_HEIGHT, FPS, BG_COLOR

class PlayScene:
    def __init__(self):
        self.all_sprites = pygame.sprite.Group()
        self.player = Player((SCREEN_WIDTH//2, SCREEN_HEIGHT//2))
        self.all_sprites.add(self.player)

    def handle_events(self, events):
        for e in events:
            if e.type == pygame.KEYDOWN and e.key == pygame.K_SPACE:
                self.player.try_dash()

    def update(self, dt):
        self.all_sprites.update(dt)

    def draw(self, screen):
        screen.fill(BG_COLOR)
        self.all_sprites.draw(screen)


class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill((52, 211, 153))
        self.rect = self.image.get_rect(center=pos)
        self.vel = pygame.Vector2(0, 0)

    def update(self, dt):
        keys = pygame.key.get_pressed()
        direction = pygame.Vector2(
            keys[pygame.K_d] - keys[pygame.K_a],
            keys[pygame.K_s] - keys[pygame.K_w],
        )
        if direction.length_squared() > 0:
            direction = direction.normalize()
        self.vel = direction * 250
        self.rect.center += self.vel * dt

    def try_dash(self):
        pass  # Module 8 dash logic goes here


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    clock = pygame.time.Clock()
    scene = PlayScene()
    running = True
    while running:
        dt = clock.tick(FPS) / 1000
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                running = False
        scene.handle_events(events)
        scene.update(dt)
        scene.draw(screen)
        pygame.display.flip()
    pygame.quit()

if __name__ == "__main__":
    main()
Step 4

UI, Sound, Testing & Performance Pass

Layer in the remaining systems in this order: menus and HUD (Module 11), sound effects and music (Module 10), then a dedicated testing pass — play through the entire game start to finish multiple times looking specifically for crashes, softlocks, and unfair difficulty spikes. Finish with a performance pass using Module 19's optimization checklist.

Step 5

Package & Present Your Portfolio Piece

Package your finished game with PyInstaller (Module 19), then write a short README covering: what the game is, controls, screenshots or a gameplay GIF, and credits for any third-party assets. Upload the build to itch.io or a public GitHub repository — this capstone is now a real portfolio piece you can link from a resume or job application.

🏆

Course Complete!

You've gone from a Python refresher to shipping a fully playable, packaged game. Every system in your capstone — movement, collision, animation, AI, sound, UI — is something you built yourself from Modules 1 through 19. That's the real skill: not memorizing an API, but knowing how to combine simple pieces into something players can enjoy.

Step 6

Your Capstone's Folder Structure

Applying Module 18's architecture to the capstone gives every file a clear, predictable home before you write a single line of gameplay code.

my_game/ game.py scenes/ assets/ images/ assets/ sounds/ config.py
One root folder, five clearly separated concerns — code, scenes, and assets never mix

🧠 Quick Knowledge Check

1. Why write a Game Design Document before coding?
2. Why apply the Module 18 architecture from day one instead of retrofitting it later?
3. In the starter skeleton, what does the PlayScene class combine?
4. What should a testing pass specifically look for before shipping?
5. What makes the capstone game a genuine portfolio piece?
Finished Module 20?

Mark it complete to finish Complete Pygame Mastery 2026!

🗒 Cheat Sheet 📝 Worksheet