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
| Module | What You Used From It |
|---|---|
| Module 02 - Platformer | Platformer movement, gravity, and collision |
| Module 07 - Roguelike | Inventory 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.
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.
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
- Hidden breakable walls: Certain tiles can be destroyed with a specific ability, revealing secret passages.
- Ability-based combat: Enemies that can only be damaged by specific abilities.
- Map item collectibles: Percentage-tracked collectibles throughout the world.
- Fast travel between save rooms: Instant travel between visited save rooms to reduce late-game backtracking.
MVP Spec
| Feature | Required |
|---|---|
| World graph with 8-12 rooms | Yes |
| Player movement (walk, jump) | Yes |
| 2-3 ability pickups (e.g., double jump, dash) | Yes |
| Ability-gated doors/passages | Yes |
| Room transitions on door entry | Yes |
| Minimap showing visited rooms | Yes |
| Save/load game state to file | Yes |
| Save room mechanic | Yes |
| At least 2 valid paths to the final room | Yes |
| Visual cues for gated passages | Yes |
| Hidden breakable walls | Stretch |
| Enemies with ability-specific weaknesses | Stretch |
| Collectibles with completion percentage | Stretch |
| Fast travel between save rooms | Stretch |
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
| Concept | Analogy |
|---|---|
| World map as a graph | A microservice topology — nodes are services, edges are API calls with auth requirements |
| Ability-gating | Role-based access control (RBAC) — access only with the required permission |
| Backtracking design | Database migration rollbacks — revisiting previous states with new schema capabilities |
| Minimap / map system | Service discovery and health dashboards |
| Save / checkpoint system | Database snapshots or transaction savepoints |
| Non-linear progression | Eventual consistency — multiple valid orderings converging to the same final state |
For Frontend Developers
| Concept | Analogy |
|---|---|
| World map as a graph | A single-page app's route graph — pages are nodes, some routes are protected |
| Ability-gating | Route guards or feature flags |
| Backtracking design | Browser history with progressive enhancement |
| Minimap / map system | A site map or breadcrumb navigation |
| Save / checkpoint system | localStorage or sessionStorage persistence |
| Non-linear progression | Flexible user flows — multi-step form sections in any order |
For Data / ML Engineers
| Concept | Analogy |
|---|---|
| World map as a graph | A computation DAG (Airflow or Spark) — nodes are tasks, edges are dependencies |
| Ability-gating | Feature dependencies in a pipeline |
| Backtracking design | Iterative model refinement — re-examining data with a better model |
| Minimap / map system | Experiment tracking dashboards (MLflow, W&B) |
| Save / checkpoint system | Model checkpointing during training |
| Non-linear progression | Hyperparameter search — multiple valid paths through the search space |
Discussion Questions
- 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?
- 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?
- The backtracking problem: What design techniques can mitigate the tedium of revisiting rooms without eliminating the satisfaction of returning with new abilities?
- Difficulty and gating: Some Metroidvanias use skill-gates alongside ability-gates. How does mixing these two types change the player experience?