Skip to content

Course 9: Eight Advanced - Capstone Projects

Course overview

This course teaches the core concepts of integrate every concept learned so far. Students build a complete, actually playable game and experience how multiple systems work together. Along the way, they face the real-world challenges of software design, debugging, and optimization.

Estimated time: 20-40 hours

The time required depends on the student's grade level, prior experience, and learning speed, and varies greatly. It also differs between just learning the basic concepts and moving on, versus additional practice problems or creative projects: taking those on makes a difference too. The times above are an average range, so please proceed flexibly at your child's pace.

What abilities will it build?

integrate multiple data systems into one complete system. This trains the ability to . Modern services run with multiple data systems connected together, such as user data, product data, payment data, and analytics data. This integration-design skill is a core competency of software architects and data engineers.

What principles will you learn?

  • (Data flow design) You design the flow of data that goes player → weapon → enemy → score → UI, the data flow. Real services are also built around a data flow of order → payment → shipping → notification.
  • (Data-driven debugging) Tracking down "where did the data go wrong?", you check the state of the data and solve the problem. This is how real developers find bugs.
AI-era thinking: computing (problem-solving) | data-driven | probabilistic thinking

Computational Thinking

Skill Description Example activity
🧩 Divide and conquer Break a big problem into smaller ones FPS = input + physics + rendering + UI
🔗 System integration Connect independent modules Player ↔ inventory ↔ UI integration
🐛 Systematic debugging Trace and fix the cause of errors Find the bug's location with binary search
📊 Project management Prioritization and step-by-step progress MVP first, add features later

Mathematical connections

Math concept Programming application Learning benefit
Divide and conquer Complex problem → small subproblems Recursive problem solving
Graphs/networks Connection relationships between systems Identifying dependencies
Logical reasoning Tracing the cause of bugs Hypothesis-verification process
Optimization Writing efficient code Time/space complexity

Divide and conquer strategy (Divide & Conquer)

flowchart TD
    A["🎯 Big problem<br/>Build a complete FPS game"] --> B["👤 1. Player"]
    A --> C["🔫 2. Weapon"]
    A --> D["👾 3. Enemy"]
    A --> E["📊 4. UI"]

    B --> B1[Movement]
    B --> B2[View control]
    B --> B3[Health management]

    C --> C1[Fire gun]
    C --> C2[Reload]
    C --> C3[Damage calculation]

    D --> D1[AI movement]
    D --> D2[Attack]
    D --> D3[Spawn]

    E --> E1[Health bar]
    E --> E2[Score]
    E --> E3[Minimap]

Key point: develop each independently → integrate → test

Debugging = the scientific method

Steps Scientific method Applied to debugging
1. Observe Observe the phenomenon Confirm the bug's symptoms
2. Hypothesize Guess the cause "This variable is probably the problem"
3. Experiment Test the hypothesis Check values with print()
4. Conclude Analyze the results Confirm the cause or form a new hypothesis
5. Verify Confirm the fix Test after fixing

Project management - the Agile approach

Iteration 1: Core features (MVP)
├── Player moves ✓
├── Can fire a gun ✓
└── Enemies appear ✓

Iteration 2: Game logic
├── Score when you hit an enemy ✓
├── Take damage when hit by an enemy ✓
└── Game over condition ✓

Iteration 3: Improvements
├── Add UI
├── Sound effects
└── Difficulty tuning

"A working version beats a perfect plan"

The MVC pattern - separation of concerns

Component Role Example
Model data Inventory array, item info
View Screen display UI buttons, item icons
Controller Logic handling Use an item on click
💻 Code examples & visualization

Example 1: A modular game structure

# ==================== player.py ====================
class Player:
    def __init__(self):
        self.health = 100
        self.position = (0, 0, 0)
        self.inventory = []

    def move(self, direction):
        # Movement logic
        pass

    def take_damage(self, amount):
        self.health -= amount

# ==================== enemy.py ====================
class Enemy:
    def __init__(self, position):
        self.health = 50
        self.position = position

    def update(self, player_pos):
        # AI logic: chase the player
        pass

# ==================== weapon.py ====================
class Weapon:
    def __init__(self, name, damage):
        self.name = name
        self.damage = damage

    def fire(self):
        # Firing logic
        pass

# ==================== main.py ====================
from player import Player
from enemy import Enemy
from weapon import Weapon

player = Player()
enemies = [Enemy((5, 0, 0)), Enemy((10, 0, 0))]
gun = Weapon("Pistol", 25)

Module structure:

game_project/
├── main.py          ← Main entry point
├── player.py        ← Player class
│   └── class Player
│       ├── move()
│       └── take_damage()
├── enemy.py         ← Enemy class
│   └── class Enemy
│       └── update()
└── weapon.py        ← Weapon class
    └── class Weapon
        └── fire()

Each file is independent → easy to test!


Example 2: FPS game system integration

from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController

app = Ursina()

# ===== System 1: Player =====
player = FirstPersonController()
player.health = 100

# ===== System 2: Weapon =====
class Gun(Entity):
    def __init__(self):
        super().__init__(
            model='cube',
            color=color.gray,
            scale=(0.1, 0.1, 0.5),
            parent=camera,
            position=(0.5, -0.3, 0.5)
        )
        self.damage = 25

    def shoot(self):
        # Collision check via raycast
        hit_info = raycast(camera.position, camera.forward, distance=100)
        if hit_info.hit:
            if hasattr(hit_info.entity, 'take_damage'):
                hit_info.entity.take_damage(self.damage)

gun = Gun()

# ===== System 3: Enemy =====
class Enemy(Entity):
    def __init__(self, position):
        super().__init__(
            model='cube',
            color=color.red,
            position=position,
            collider='box'
        )
        self.health = 50

    def take_damage(self, amount):
        self.health -= amount
        if self.health <= 0:
            destroy(self)
            update_score(10)

enemies = [Enemy((5, 1, 10)), Enemy((-5, 1, 15))]

# ===== System 4: UI =====
score = 0
score_text = Text(text=f'Score: {score}', position=(-0.85, 0.45))
health_bar = Entity(model='quad', color=color.red,
                    scale=(0.5, 0.03), position=(-0.6, 0.4))

def update_score(points):
    global score
    score += points
    score_text.text = f'Score: {score}'

# ===== System integration: input handling =====
def input(key):
    if key == 'left mouse down':
        gun.shoot()

app.run()

System integration diagram:

flowchart TD
    subgraph FPS["🎮 FPS game"]
        direction TB
        P["👤 Player System"] -->|owns| G["🔫 Gun System"]
        G -->|attacks| E["👾 Enemy System"]
        P --> UI["📊 UI System"]
        G --> UI
        E --> S["🏆 Score System"]
        S --> UI
    end

Example 3: The debugging process

# Buggy code
def calculate_damage(base_damage, multiplier, defense):
    # Bug: should subtract defense but it's adding!
    damage = base_damage * multiplier + defense
    return damage

# Debugging process
def calculate_damage_debug(base_damage, multiplier, defense):
    print(f"[DEBUG] base_damage: {base_damage}")
    print(f"[DEBUG] multiplier: {multiplier}")
    print(f"[DEBUG] defense: {defense}")

    damage = base_damage * multiplier + defense  # ← Found the problem!
    print(f"[DEBUG] calculated damage: {damage}")

    # Fix: + → -
    damage = base_damage * multiplier - defense
    print(f"[DEBUG] corrected damage: {damage}")

    return max(0, damage)  # Also prevent negatives

Debugging flow:

flowchart TD
    A["🐛 1. Found a bug<br/>Damage is too high!"] --> B["🤔 2. Form a hypothesis<br/>Damage calculation issue?"]
    B --> C["🔍 3. Check with print<br/>base=10, mult=2, def=5<br/>result: 25 ← expected: 15"]
    C --> D["💡 4. Found the cause<br/>Should be - not +!"]
    D --> E["✅ 5. Fix and verify<br/>damage = base×mult - def<br/>result: 15 ✓"]

Example 4: MVC pattern - inventory system

# ===== Model (data) =====
class InventoryModel:
    def __init__(self, rows, cols):
        self.grid = [[None for _ in range(cols)] for _ in range(rows)]

    def add_item(self, row, col, item):
        if self.grid[row][col] is None:
            self.grid[row][col] = item
            return True
        return False

    def remove_item(self, row, col):
        item = self.grid[row][col]
        self.grid[row][col] = None
        return item

# ===== View (screen display) =====
class InventoryView:
    def __init__(self, model):
        self.model = model
        self.buttons = []

    def create_ui(self):
        for row in range(len(self.model.grid)):
            for col in range(len(self.model.grid[0])):
                btn = Button(
                    position=(col * 0.1 - 0.2, -row * 0.1 + 0.2),
                    scale=0.08
                )
                self.buttons.append(btn)

    def update_display(self):
        for row in range(len(self.model.grid)):
            for col in range(len(self.model.grid[0])):
                item = self.model.grid[row][col]
                idx = row * len(self.model.grid[0]) + col
                if item:
                    self.buttons[idx].text = item.name[0]
                else:
                    self.buttons[idx].text = ""

# ===== Controller (logic) =====
class InventoryController:
    def __init__(self, model, view):
        self.model = model
        self.view = view
        self.selected = None

    def on_slot_click(self, row, col):
        if self.selected is None:
            # Select an item
            self.selected = (row, col)
        else:
            # Move an item
            self.swap_items(self.selected, (row, col))
            self.selected = None
            self.view.update_display()

MVC structure diagram:

flowchart TD
    U["🖱️ User input<br/>(click)"] --> C["🎛️ Controller<br/>Logic handling"]
    C --> M["📦 Model<br/>Data"]
    C --> V["🖥️ View<br/>Screen"]
    M <-->|sync| V
    V --> R["✨ Screen update"]

Key point: Model changes → View updates automatically


Example 5: Project progression stages

"""
FPS game development roadmap

=== Phase 1: MVP (core features) ===
[x] Player movement
[x] Mouse view control
[x] Fire gun (click)
[x] Spawn enemies

=== Phase 2: Game logic ===
[x] Enemy health system
[x] Gain score on enemy kill
[x] Player health system
[ ] Game over condition

=== Phase 3: Improvements ===
[ ] Enemy AI (chase the player)
[ ] Sound effects
[ ] Particle effects
[ ] Difficulty system

=== Phase 4: Polishing ===
[ ] Main menu
[ ] Settings screen
[ ] Save/load
"""

# Currently in Phase 2...

Development progress visualization:

Phase 1 ████████████████████ 100% ✓
Phase 2 ████████████░░░░░░░░  60%
Phase 3 ░░░░░░░░░░░░░░░░░░░░   0%
Phase 4 ░░░░░░░░░░░░░░░░░░░░   0%

MVP done! → A working game secured
          → Then gradual improvements

"Working code beats a perfect plan!"


Why do capstone projects matter?

Educational value

Learning individual concepts and integrating and applying them are different abilities:

Individual learning Capstone project
Understanding conditionals Choosing conditionals in the right situations
How to use lists Deciding where a list is needed in a game
Defining a class Designing what should become a class
Memorizing concepts Applying concepts to solve problems

The capstone project is from "I know it" to "I can do it" a shift .


Project 1: FPS Complete - a finished FPS game

Item Content
What will you learn? Building a complete first-person shooter
Integrated concepts Input, physics, collision, classes, events

Build a complete FPS game from start to finish. Player movement, view control, gun firing, enemy AI, the health system, and the score system are all integrated. Students understand how each system connects to the others. When a bug occurs, they build the debugging skill to trace where the problem arose. They share the finished game with friends and sense of accomplishmentof creating their own world.


The challenge of system integration

Item Content
What will you learn? Managing complex systems
Core Concepts Modularization, debugging, testing

When multiple systems run at once, unexpected interactions can occur. They find and fix edge cases like "a bug appears when you jump while firing." Students learn the importance of organizing code into modules (functional units). They also learn how to test each module independently and then integrate them. This is the standard approachIt is.


Project 2: Inventory Complete - a finished inventory system

Item Content
What will you learn? A complete item management system
Integrated concepts 2D arrays, classes, UI, events

Acquiring, using, equipping, and dropping items is a complete inventory. You design the inheritance structure of item classes (weapons, armor, consumables). You implement a UI that moves items via drag and drop. Students experience the important design principle of separating the data model from the UI. This system is a core featureIt is.


Separating data and UI

Item Content
What will you learn? Good software design
Core Concepts MVC pattern, separation of concerns

the data (which item is where)and the UI (how it looks on screen)You separate from . When the data changes, you design the UI to update automatically. This pattern is MVC(Model-View-Controller) called this, and it is the standard in professional development. Students learn how to structure code to be easy to maintain . Later, in web and app development, they apply the same principle.


Project 3: Minecraft with Items - Minecraft + items

Item Content
What will you learn? Integrating a block world with an item system
Integrated concepts 2D arrays, classes, inventory, physics

Add an item system to a Minecraft-style world. When you mine a block it is added to the inventory, and when you select it from the inventory you can place it. Various block types (dirt, stone, wood) are implemented with class inheritance. Students experience integrating several large systems. This project is the curriculum's final challenge and comprehensive assessmentIt is.


Project management experience

Item Content
What will you learn? Tackling a big project
Core Concepts Planning, prioritization, iterative development

A big project is not finished in one go. Students divide features by priority and implement them step by step. First they build the core features (placing/removing blocks), then gradually add more. This is similar to the Agile methodology of real software development. Rather than chasing perfection and never finishing, it's important to build a working version first .


What the capstone project means

Completing the learning

After finishing the capstone project, students gain:

  1. confidence: the confidence that "I can build a game too"
  2. Portfolio: a real piece of work they can show
  3. Problem-solving experience: the experience of overcoming real difficulties
  4. Design ability: the ability to break a big problem into small parts
  5. The experience of finishing: the satisfaction of seeing it through to the end

This experience applies not only to programming but to projects in every field.


When you finish this course...

Learning outcomes

Students will be able to:

  • Build a complete game by integrating multiple systems
  • Plan a big project and carry it out step by step
  • Trace and fix bugs: the debugging skill
  • Structure code by modularizing and organizing it: the design skill
  • The experience of actually Completedoing it with a real game
  • Ready to expand to more complex projects or other fields