Point-and-Click Adventure
Puzzle-solving through object interaction and conversation — every item is a question; every combination is an answer.
"I'm selling these fine leather jackets."
Prerequisites
| Module | What You Used From It |
|---|---|
| Module 01 - Pong | Basic game loop, rendering, and state management. Point-and-click adventures are mechanically simple but architecturally demanding. |
Week 1: History & Design Theory
The Origin
The Secret of Monkey Island (1990), designed by Ron Gilbert and Tim Schafer at LucasArts, perfected the point-and-click adventure formula by solving the genre's greatest problem: unfair death. Sierra On-Line's earlier adventures (King's Quest, 1984) punished players with frequent, often unpredictable deaths and dead-end states where the game became unwinnable without the player knowing. Gilbert's philosophy, codified in his "Why Adventure Games Suck" manifesto, insisted that the player should never die and should never be able to reach a dead end. Monkey Island implemented this by designing every puzzle as a contained logical problem with discoverable solutions, using humor to make failed attempts entertaining rather than punishing, and building an inventory-combination system where the fun was in experimentation. The SCUMM engine (Script Creation Utility for Maniac Mansion) gave designers a verb-based interaction system — Look At, Pick Up, Use, Talk To — that made every screen a dense web of discoverable interactions.
How the Genre Evolved
Myst (1993): Cyan Worlds' Rand and Robyn Miller stripped away the verb interface, inventory, and dialogue entirely, replacing them with environmental puzzles embedded in hauntingly beautiful pre-rendered worlds. Players clicked to move between static viewpoints and manipulated mechanisms directly. Myst proved that point-and-click adventure did not require inventory or conversation — pure environmental observation and logical deduction could sustain an entire game.
Disco Elysium (2019): ZA/UM's masterwork reimagined the adventure game through the lens of a tabletop RPG. Instead of combining physical objects, the player combined ideas in an internalized "thought cabinet." Every conversation was a potential puzzle, with 24 distinct skills functioning as inner voices that provided clues, opinions, and sometimes unreliable advice. It demonstrated that the core loop of point-and-click — observe, gather information, combine knowledge to progress — could be applied to dialogue and character psychology rather than physical inventory puzzles.
What Makes Point-and-Click "Great"
The core design insight of the point-and-click adventure is lateral thinking as gameplay. The genre asks the player to look at the world not as it is but as it could be — a rubber chicken is not just a rubber chicken but a potential tool when combined with a pulley. This trains a specific cognitive skill: the ability to hold multiple unrelated objects in mind and ask "what if these go together?" The best adventure games design puzzles where the solution, once discovered, feels obvious in retrospect ("of course you use the monkey as a wrench") — this retrospective clarity is the "aha!" moment that drives the entire genre.
The Essential Mechanic
Combining found objects and information to solve environmental puzzles — the player observes, collects, reasons about connections, and applies items or knowledge to overcome obstacles.
Week 2: Build the MVP
What You're Building
A 3-5 room adventure game with an inventory system, at least one item-combination puzzle, a dialog tree with a single NPC, and a puzzle dependency chain where solving one puzzle unlocks the next. The player clicks to interact with hotspots, collects items, and combines them to progress.
This module is 2D. No engine is required.
Core Concepts (Must Implement)
1. Inventory System with Item Combination
The player carries a collection of items represented as objects with properties (name, description, icon, use-cases). Items can be used on hotspots in the world or combined with each other in the inventory to produce new items.
class Item:
def __init__(self, id, name, description, icon):
self.id = id
self.name = name
self.description = description
self.icon = icon
class Inventory:
def __init__(self):
self.items = {} # id -> Item
def add(self, item):
self.items[item.id] = item
def remove(self, item_id):
del self.items[item_id]
def has(self, item_id):
return item_id in self.items
def try_combine(self, item_a_id, item_b_id):
key = frozenset([item_a_id, item_b_id])
if key in COMBINATION_RECIPES:
result = COMBINATION_RECIPES[key]
self.remove(item_a_id)
self.remove(item_b_id)
self.add(result)
return result
return None
COMBINATION_RECIPES = {
frozenset(["rope", "hook"]): Item("grapple", "Grappling Hook",
"A hook tied to a rope. Could reach high places.", "grapple.png"),
frozenset(["key_half_a", "key_half_b"]): Item("full_key", "Complete Key",
"Both halves joined together.", "full_key.png"),
} Why it matters: The inventory is the player's toolkit. Every puzzle in the game is ultimately solved by having the right item and applying it in the right place. The combination system multiplies puzzle possibilities exponentially — N items yield N*(N-1)/2 potential combinations.
Click on highlighted objects in the scene to pick them up. Items appear in the inventory bar at the bottom. Click an inventory item to select it (yellow border), then click another item to try combining them. Use combined items on the locked chest to solve the puzzle!
2. Puzzle Dependency Graph
The game's puzzles form a directed acyclic graph (DAG) where each puzzle has prerequisites (items, flags, or other puzzles). Designing this graph up front ensures puzzles are solvable in a valid order and prevents dead ends.
puzzle_graph = {
"get_rope": {
requires: [],
grants: ["rope"],
description: "Pick up rope from the dock"
},
"talk_to_fisherman": {
requires: [],
grants: ["flag:fisherman_talked"],
description: "Learn that the fisherman lost his hook"
},
"get_hook": {
requires: ["flag:fisherman_talked"],
grants: ["hook"],
description: "Fisherman gives you his spare hook"
},
"make_grapple": {
requires: ["rope", "hook"],
grants: ["grapple"],
description: "Combine rope + hook = grappling hook"
},
"climb_tower": {
requires: ["grapple"],
grants: ["flag:reached_tower_top"],
description: "Use grappling hook to reach the tower top"
},
"open_gate": {
requires: ["key"],
grants: ["flag:game_complete"],
description: "Use key on the locked gate — victory!"
}
} Why it matters: The puzzle dependency graph is the game's blueprint. Without it, designers risk creating unsolvable states, circular dependencies, or puzzles where the player has no idea what to do next.
3. Dialog Trees
Conversations with NPCs are represented as a graph of dialog nodes. Each node contains NPC text and a list of player response options. Selecting a response may lead to another dialog node, set a game state flag, give the player an item, or end the conversation.
dialog_fisherman = {
"start": {
npc_text: "Ahoy! I'd be fishing, but I lost my best hook overboard.",
options: [
{ text: "That's too bad.", next: "sympathy" },
{ text: "Do you have a spare?", next: "spare_hook" },
{ text: "Goodbye.", next: null }
]
},
"sympathy": {
npc_text: "Aye, it's been a rough week. Say, you look resourceful...",
options: [
{ text: "Do you have a spare hook?", next: "spare_hook" },
{ text: "I should go.", next: null }
]
},
"spare_hook": {
npc_text: "Matter of fact, I do. Here, take it.",
options: [
{ text: "Thanks!", next: null }
],
on_enter: [
{ action: "give_item", item: "hook" },
{ action: "set_flag", flag: "fisherman_talked", value: true }
]
}
} Why it matters: Dialog is the primary way adventure games deliver narrative, character, and puzzle clues. The tree structure lets designers create conversations that feel responsive to the player's curiosity while ensuring that essential information is always reachable.
Click on dialog options to navigate the conversation. The graph on the right updates in real-time showing which nodes you have visited (green), your current node (yellow), and unvisited nodes (gray). Flags set by the conversation appear at the bottom. Choices can unlock or lock future options!
4. Hotspot Interaction System
Each scene contains clickable hotspots — regions of the screen that the player can interact with. Hotspots have a position, a bounding area, and responses for different interaction types (look, use, use-item-on). The cursor changes to indicate when it is over a hotspot.
class Hotspot:
def __init__(self, id, name, bounds, interactions):
self.id = id
self.name = name
self.bounds = bounds # {x, y, width, height}
self.interactions = interactions
self.active = true
def contains(self, mouse_x, mouse_y):
b = self.bounds
return (b.x <= mouse_x <= b.x + b.width and
b.y <= mouse_y <= b.y + b.height)
def handle_click(mouse_x, mouse_y, current_scene, selected_item):
for hotspot in current_scene.hotspots:
if not hotspot.active or not hotspot.contains(mouse_x, mouse_y):
continue
if selected_item:
use_item = hotspot.interactions.get("use_item", {})
response = use_item.get(selected_item.id, use_item.get("default"))
else:
response = hotspot.interactions.get("look")
execute_response(response)
return
deselect_item() Why it matters: Hotspots are the player's primary interface with the game world. They transform a static background image into an interactive space. The cursor feedback is critical — the player must be able to discover what is interactive without clicking blindly on every pixel.
5. Scene / Room Management
The game is organized into discrete scenes (rooms), each with its own background image, hotspots, NPCs, and entry/exit points. A scene manager handles loading scenes, running transitions between them, and maintaining per-scene state.
class SceneManager:
def __init__(self):
self.scenes = {}
self.current_scene = null
self.transition_state = "none"
self.fade_alpha = 0.0
def change_scene(self, target_id):
self.transition_state = "fading_out"
self.next_scene_id = target_id
def update(self, dt):
if self.transition_state == "fading_out":
self.fade_alpha += dt * FADE_SPEED
if self.fade_alpha >= 1.0:
self.current_scene = self.scenes[self.next_scene_id]
self.transition_state = "fading_in"
elif self.transition_state == "fading_in":
self.fade_alpha -= dt * FADE_SPEED
if self.fade_alpha <= 0.0:
self.fade_alpha = 0.0
self.transition_state = "none" Why it matters: Scene management is the architecture that holds the entire game together. Clean scene management makes the game trivially extensible — adding a new room means defining a new data object, not modifying core logic.
6. Game State Flags
A centralized flag system tracks everything the player has done, seen, and said. Flags are boolean or string values keyed by name. Hotspots, dialog options, and puzzle logic all read from and write to this shared state.
class GameStateFlags:
def __init__(self):
self.flags = {}
def set_flag(self, name, value=true):
self.flags[name] = value
def get_flag(self, name, default=false):
return self.flags.get(name, default)
def check_condition(self, condition):
if " AND " in condition:
parts = condition.split(" AND ")
return all(self.check_condition(p.strip()) for p in parts)
if " OR " in condition:
parts = condition.split(" OR ")
return any(self.check_condition(p.strip()) for p in parts)
if condition.startswith("!"):
return not self.check_flag(condition[1:])
return self.check_flag(condition) Why it matters: Flags are the memory of the game world. They are how the game tracks cause and effect across rooms, conversations, and time. Without a centralized flag system, tracking what the player has done becomes a tangled mess of ad-hoc variables.
Stretch Goals
- Character walking: The player character walks to the clicked hotspot before interacting, with simple pathfinding around obstacles.
- Verb interface: Add a classic verb bar (Look At, Pick Up, Use, Talk To) where the player selects a verb before clicking a hotspot.
- Conditional dialog options: Dialog options that only appear when certain flags are set.
- Hint system: A progressive hint system that provides increasingly specific clues when the player is stuck.
MVP Spec
| Feature | Required |
|---|---|
| 3-5 scenes with background images | Yes |
| Clickable hotspots with look/use responses | Yes |
| Inventory UI with item collection | Yes |
| At least one item combination puzzle | Yes |
| Use-item-on-hotspot interaction | Yes |
| At least one NPC with dialog tree | Yes |
| Scene transitions (fade or cut) | Yes |
| Game state flags driving conditional content | Yes |
| Puzzle dependency chain of 4+ steps | Yes |
| Context-sensitive cursor | Yes |
| Character walking animation | Stretch |
| Verb bar interface | Stretch |
| Conditional dialog options | Stretch |
| Hint system | Stretch |
Deliverable
Submit your playable adventure game with source code and a puzzle dependency graph diagram showing all puzzles as nodes, their prerequisites as edges, and the items/flags each puzzle grants. Include a short write-up (300-500 words) answering: How did you design your puzzle chain to be solvable without a walkthrough? What clues did you embed in dialog, item descriptions, and environmental details to guide the player toward solutions?
Analogies by Background
These analogies map game dev concepts to patterns you already know.
For Backend Developers
| Game Dev Concept | Backend Analogy |
|---|---|
| Inventory with item combination | A key-value store with composite key lookups — items are values, combinations are queries against a recipe table, producing new entries |
| Puzzle dependency graph | A task DAG (like Airflow or Makefile targets) — each task has prerequisites that must complete before it can execute |
| Dialog trees | A state machine for request handling — each state presents a response and a set of valid transitions, with side effects triggered on state entry |
| Hotspot interaction system | A URL router with method handling — each hotspot is a route, each interaction type is an HTTP method |
| Scene / room management | Microservice orchestration — each scene is an independent service with its own state, and the scene manager is the API gateway |
| Game state flags | A feature flag service (LaunchDarkly, etc.) — a centralized boolean store that all services query to determine behavior |
For Frontend Developers
| Game Dev Concept | Frontend Analogy |
|---|---|
| Inventory with item combination | Shopping cart with bundle logic — items in the cart can be combined into bundles, producing a new line item |
| Puzzle dependency graph | Component dependency tree — components (puzzles) can only render (solve) when their required props (items/flags) are provided |
| Dialog trees | A multi-step wizard/form — each step shows content and options, the selected option determines the next step |
| Hotspot interaction system | Event delegation on a composite UI — clickable regions within an image map, each with hover states and click handlers |
| Scene / room management | Client-side routing — each scene is a route/page, the scene manager is the router |
| Game state flags | Global application state (Redux/Zustand) — a centralized store that components subscribe to |
For Data / ML Engineers
| Game Dev Concept | Data / ML Analogy |
|---|---|
| Inventory with item combination | Feature engineering — raw features (items) are combined through defined transformations (recipes) to produce derived features |
| Puzzle dependency graph | A data pipeline DAG (Airflow, dbt) — each node is a transformation with defined inputs |
| Dialog trees | A decision tree classifier — each node splits on a player choice, leaf nodes produce outcomes |
| Hotspot interaction system | Labeled training data — each hotspot is an annotated region in an image with associated metadata |
| Scene / room management | Dataset partitioning — each scene is a partition of the total game data, loaded independently |
| Game state flags | Experiment tracking metadata — a centralized log of which experiments (actions) have been run |
Discussion Questions
- Fair puzzles vs. obscure puzzles: Classic adventure games were notorious for illogical puzzles (the "cat hair mustache" problem). How do you design puzzles that are challenging but fair? What is the role of the puzzle dependency graph in ensuring the player always has enough information?
- The dead-end problem: Ron Gilbert's manifesto argued that adventure games should never create unwinnable states. How does your puzzle dependency graph guarantee this? Could a game intentionally use dead ends as a design tool?
- Dialog as puzzle: In games like Disco Elysium, dialog itself is the puzzle. How does this differ from using dialog purely as a clue-delivery system?
- The hint economy: When a player is stuck, they will either consult a walkthrough (leaving your game) or quit. How would you design an in-game hint system that helps stuck players without spoiling satisfaction?