Module 14

Metroidvania

Interconnected exploration with ability-gated progression — the world is the puzzle.

"The measure of a hero is not in the strength of their arm, but in the doors they can finally open."


Prerequisites

ModuleWhat You Used From It
Module 02 - PlatformerPlatformer movement, gravity, and collision
Module 07 - RoguelikeInventory concepts and persistent game state

Week 1: History & Design Theory

The Origin

Super Metroid (1994), developed by Nintendo R&D1 and Intelligent Systems and directed by Yoshio Sakamoto, defined the template for interconnected exploration games. While the original Metroid (1986) introduced the concept of a large, non-linear world gated by ability pickups, Super Metroid perfected the formula by giving players an atmospheric, labyrinthine map where every room connected meaningfully to others, environmental storytelling replaced exposition, and newly acquired abilities — the Morph Ball, Grapple Beam, Speed Booster — constantly recontextualized spaces the player had already traversed.

How the Genre Evolved

Castlevania: Symphony of the Night (1997) fused the Metroid exploration structure with RPG systems — experience points, equipment, leveling, and a vast bestiary. The inverted castle doubled the game's content by literally flipping the world. The game coined the second half of the genre name and proved that layering progression systems onto exploration created extraordinary replay value.

Hollow Knight (2017) showed that the Metroidvania could thrive in the indie era with a massive, hand-crafted interconnected world, a Souls-like difficulty philosophy, and a charm system for build customization. Critically, it demonstrated that the map itself could be a discoverable item — you had to find the cartographer in each area before your minimap would populate.

Ori and the Blind Forest (2015) brought a focus on kinetic movement and emotional storytelling. The "bash" ability showed that movement abilities could be both traversal tools and combat mechanics simultaneously, blurring the line between ability-gating and skill-gating.

What Makes Metroidvania Great

The core design insight of the Metroidvania is delayed gratification through spatial memory. The genre works because it trusts the player to notice a ledge they cannot reach, a wall they cannot break, or a gap they cannot cross — and to remember it. When the player finally acquires the ability that unlocks that area, the satisfaction is doubled: the joy of the new power itself, plus the accumulated anticipation of every locked door they mentally catalogued. Each new ability doesn't just open one path — it opens dozens of previously glimpsed possibilities across the entire world.

The Essential Mechanic

Ability-gated exploration — you see areas you cannot reach yet, then return with new powers to unlock them, transforming the entire world map into a puzzle that unfolds over time.


Week 2: Build the MVP

What You're Building

A small interconnected world of 8-12 rooms arranged as a graph, where the player starts with basic movement and must find 2-3 abilities (such as double jump and dash) to reach new areas and eventually arrive at a final room. The focus is on the world structure, ability-gating logic, and a minimap.

Core Concepts (Must Implement)

1. World Map as a Graph

The interconnected world is represented as a graph data structure where each room is a node and each door or passage is an edge. Edges carry metadata indicating which ability (if any) is required to traverse them.

# World definition
rooms = {
  "start":    { edges: [{ to: "cave_l", dir: "right", requires: null }] },
  "cave_l":   { edges: [
                  { to: "start", dir: "left", requires: null },
                  { to: "cave_u", dir: "up", requires: "double_jump" },
                  { to: "shaft", dir: "right", requires: null }
                ]},
  "cave_u":   { edges: [{ to: "cave_l", dir: "down", requires: null },
                         { to: "peak", dir: "right", requires: "dash" }] },
  "shaft":    { edges: [{ to: "cave_l", dir: "left", requires: null },
                         { to: "ability_room_1", dir: "down", requires: null }] },
  "ability_room_1": { edges: [...], grants_ability: "double_jump" },
  ...
}

Why it matters: The graph is the backbone of the entire game. Every system — gating, minimap, save state, non-linear progression — reads from this structure.

Interactive: World Map Graph

Rooms are nodes, doors are edges. Doors are color-coded by required ability: white=none, red=missile, blue=double-jump, green=wall-climb. Click the ability buttons to "acquire" them and see which doors unlock. Locked doors are shown as dashed lines.

2. Ability-Gating

Each edge in the world graph may specify a required ability. When the player attempts to traverse an edge, the system checks whether the player's acquired abilities satisfy the requirement.

function can_traverse(player, edge):
    if edge.requires is null:
        return true
    return edge.requires in player.abilities

function attempt_door(player, edge):
    if can_traverse(player, edge):
        transition_to_room(edge.to)
    else:
        show_feedback("You need " + edge.requires + " to pass.")

Why it matters: Ability-gating is what transforms a collection of rooms into a Metroidvania. Without it, you have a platformer with room transitions. The gates create the "I'll come back later" moments that define the genre.

3. Backtracking-Friendly Level Design

Rooms must be designed so that returning to them with new abilities feels rewarding rather than tedious. Rooms should have multiple exits gated at different ability levels, shortcuts that open from one side, and visual hints of unreachable areas.

# Room layout principle:
# Each room has a "base path" accessible on first visit
# and "gated paths" visible but blocked.
room_cave_l = {
  platforms: [
    { x: 0, y: 0, w: 300, h: 20 },          # ground floor
    { x: 200, y: -120, w: 80, h: 20 },       # high ledge (needs double_jump)
  ],
  doors: [
    { x: 290, y: 0, leads_to: "shaft", requires: null },
    { x: 220, y: -120, leads_to: "cave_u", requires: "double_jump" },
  ]
}

Why it matters: Backtracking is the most common criticism of the genre when done poorly. Good backtracking design ensures the player always sees something new on a return trip.

4. Minimap / Map System

A minimap tracks which rooms the player has visited and displays them relative to the current room. Unvisited rooms can be hidden or shown as outlines.

class MiniMap:
    def __init__(self, world_graph):
        self.world = world_graph
        self.visited = set()
        self.room_positions = {}
        self.assign_grid_positions()

    def visit_room(self, room_id):
        self.visited.add(room_id)

    def render(self, current_room, screen, corner_x, corner_y):
        for room_id, (gx, gy) in self.room_positions.items():
            if room_id not in self.visited:
                continue
            rx = corner_x + gx * CELL_SIZE
            ry = corner_y + gy * CELL_SIZE
            color = COLOR_CURRENT if room_id == current_room else COLOR_VISITED
            draw_rect(screen, color, rx, ry, CELL_SIZE, CELL_SIZE)

Why it matters: Without a map, players get lost and frustrated. The minimap transforms spatial confusion into spatial mastery.

5. Save / Checkpoint System

The game must persist the player's state — current room, acquired abilities, visited rooms, and any collected items.

class GameState:
    def __init__(self):
        self.current_room = "start"
        self.abilities = set()
        self.visited_rooms = set()
        self.items_collected = set()

    def to_dict(self):
        return {
            "current_room": self.current_room,
            "abilities": list(self.abilities),
            "visited_rooms": list(self.visited_rooms),
            "items_collected": list(self.items_collected),
        }

def save_game(state, filepath):
    write_json(filepath, state.to_dict())

def load_game(filepath):
    data = read_json(filepath)
    state = GameState()
    state.from_dict(data)
    return state

Why it matters: Metroidvanias are long-form experiences. Without persistence, the genre cannot function.

6. Non-Linear Progression

The world graph should support multiple valid orderings for acquiring abilities. At least two abilities should be reachable from the starting area.

def find_all_completion_orders(world, start, goal):
    results = []
    def explore(current_room, abilities, visited, path):
        if current_room == goal:
            results.append(path[:])
            return
        for edge in world[current_room].edges:
            if edge.to in visited:
                continue
            if edge.requires and edge.requires not in abilities:
                continue
            new_abilities = abilities.copy()
            if hasattr(world[edge.to], 'grants_ability'):
                new_abilities.add(world[edge.to].grants_ability)
            explore(edge.to, new_abilities, visited | {edge.to}, path + [edge.to])
    explore(start, set(), {start}, [start])
    return results

Why it matters: Non-linearity gives players agency. Two players can compare notes and realize they played the same game in different orders.

Interactive: Ability Gating Visualizer

A side-view mini level with barriers. Toggle abilities (Double Jump, Wall Climb, Dash) using the buttons to see which areas become reachable. Reachable areas light up green; unreachable areas stay dim.


Stretch Goals

MVP Spec

FeatureRequired
World graph with 8-12 roomsYes
Player movement (walk, jump)Yes
2-3 ability pickups (e.g., double jump, dash)Yes
Ability-gated doors/passagesYes
Room transitions on door entryYes
Minimap showing visited roomsYes
Save/load game state to fileYes
Save room mechanicYes
At least 2 valid paths to the final roomYes
Visual cues for gated passagesYes
Hidden breakable wallsStretch
Enemies with ability-specific weaknessesStretch
Collectibles with completion percentageStretch
Fast travel between save roomsStretch

Deliverable

Submit your playable Metroidvania MVP with source code and a world map diagram showing all rooms as nodes, edges with their gate requirements, and the locations of ability pickups. Include a short write-up (300-500 words) answering: How did you decide which rooms to gate with which abilities, and what tradeoffs did you make between linearity and non-linearity?


Analogies by Background

These analogies map game dev concepts to patterns you already know. Find your background below.

For Backend Developers

ConceptAnalogy
World map as a graphA microservice topology — nodes are services, edges are API calls with auth requirements
Ability-gatingRole-based access control (RBAC) — access only with the required permission
Backtracking designDatabase migration rollbacks — revisiting previous states with new schema capabilities
Minimap / map systemService discovery and health dashboards
Save / checkpoint systemDatabase snapshots or transaction savepoints
Non-linear progressionEventual consistency — multiple valid orderings converging to the same final state

For Frontend Developers

ConceptAnalogy
World map as a graphA single-page app's route graph — pages are nodes, some routes are protected
Ability-gatingRoute guards or feature flags
Backtracking designBrowser history with progressive enhancement
Minimap / map systemA site map or breadcrumb navigation
Save / checkpoint systemlocalStorage or sessionStorage persistence
Non-linear progressionFlexible user flows — multi-step form sections in any order

For Data / ML Engineers

ConceptAnalogy
World map as a graphA computation DAG (Airflow or Spark) — nodes are tasks, edges are dependencies
Ability-gatingFeature dependencies in a pipeline
Backtracking designIterative model refinement — re-examining data with a better model
Minimap / map systemExperiment tracking dashboards (MLflow, W&B)
Save / checkpoint systemModel checkpointing during training
Non-linear progressionHyperparameter search — multiple valid paths through the search space

Discussion Questions

  1. The "Aha!" moment: How would you design visual and audio cues to ensure that a player who sees a gated door at hour 1 still remembers it at hour 4? What role does the map system play?
  2. Linearity vs. freedom: If you make the world too open, players may get lost or sequence-break. If you make it too linear, you lose the genre's appeal. Where did your MVP land on this spectrum?
  3. The backtracking problem: What design techniques can mitigate the tedium of revisiting rooms without eliminating the satisfaction of returning with new abilities?
  4. Difficulty and gating: Some Metroidvanias use skill-gates alongside ability-gates. How does mixing these two types change the player experience?