# Architecture **Analysis Date:** 2026-02-04 ## Pattern Overview **Overall:** Scene-based state machine with linear progression through game states. **Key Characteristics:** - Phaser 3 game framework with arcade physics - Scene-based architecture where each major game location is a self-contained scene - Inventory as shared game state passed between scenes via scene data - Input-driven gameplay with dual control schemes (mouse/keyboard and touch) - Responsive scaling for mobile and desktop viewports ## Layers **Presentation Layer (Scenes):** - Purpose: Render game visuals and handle user interaction - Location: `src/scenes/` - Contains: Five scene classes extending Phaser.Scene - Depends on: Phaser framework, Phaser graphics/text/physics utilities - Used by: Main application entry point in `src/main.js` **Game State Layer (Inventory):** - Purpose: Track player progress across scenes (fuel, whale oil, penguins) - Location: Passed as data object between scenes via `scene.start(nextScene, { inventory: ... })` - Contains: Simple object with three numeric properties: `whaleOil`, `fuel`, `penguins` - Depends on: Nothing - Used by: All scenes read/modify inventory during gameplay **Framework Configuration Layer:** - Purpose: Initialize Phaser game with physics, scaling, scene list - Location: `src/main.js` - Contains: Phaser.Game configuration and setup - Depends on: All scene classes - Used by: Entry point for application startup ## Data Flow **Game Startup:** 1. Browser loads `index.html` which imports `src/main.js` as module 2. `src/main.js` creates Phaser.Game instance with config 3. IntroScene is the first scene in the scene list, auto-starts 4. Player interaction triggers scene transitions **Between-Scene Transitions:** 1. Current scene calls `this.scene.start(nextSceneKey, { inventory: this.inventory })` 2. Phaser stops current scene, starts next scene 3. Next scene receives inventory data in `init(data)` lifecycle method 4. Scene reads `data.inventory` and stores it locally 5. Scene's `create()` method renders UI with current inventory state **Inventory State:** - IntroScene initializes: `{ whaleOil: 0, fuel: 100, penguins: 0 }` - ShipDeckScene receives and passes forward - MapScene receives, displays, and passes forward - TransitionScene modifies (deducts fuel if applicable) and passes forward - HuntingScene receives, displays, modifies (fuel cost, oil gain, penguin discovery) and returns to MapScene - Penguin discovery (penguins > 0) unlocks penguin cage UI in ShipDeckScene ## Key Abstractions **Scene Class Pattern:** - Purpose: Encapsulate game logic and rendering for a specific game state - Examples: `src/scenes/IntroScene.js`, `src/scenes/ShipDeckScene.js`, `src/scenes/MapScene.js`, `src/scenes/TransitionScene.js`, `src/scenes/HuntingScene.js` - Pattern: Each scene extends `Phaser.Scene`, implements `create()` for setup and `update()` for per-frame logic **Interactive UI Elements:** - Purpose: Handle pointer (mouse/touch) input for clickable objects - Pattern: Rectangle or circle objects with `.setInteractive()` and `.on('pointerdown')` or `.on('pointerup')` listeners - Examples in ShipDeckScene: wheel click to open map, barrel zones, penguin cage - Examples in MapScene: location markers with hover effects and click handlers - Examples in HuntingScene: crosshair positioning and firing **Inventory Display Pattern:** - Purpose: Show player resources in consistent UI - Pattern: Text panel with semi-transparent background showing formatted resource strings - Used in: ShipDeckScene, MapScene, HuntingScene - Format: Multi-line text with labels and current/max values **Message System Pattern:** - Purpose: Communicate game state changes and feedback to player - Pattern: Semi-transparent rectangle with text object, updated via `showMessage(text)` method - Used in: ShipDeckScene, MapScene, TransitionScene, HuntingScene ## Entry Points **Application Entry:** - Location: `index.html` - Triggers: Page load - Responsibilities: Load HTML structure, import main.js as module, render into game-container div **Game Initialization:** - Location: `src/main.js` - Triggers: Module import by index.html - Responsibilities: Configure Phaser game (physics, scaling, resolution), instantiate Phaser.Game, list all scenes **First Scene:** - Location: `src/scenes/IntroScene.js` - Triggers: Phaser auto-starts first scene in config array - Responsibilities: Display title, draw decorative elements, show SET SAIL button, initialize inventory with defaults ## Error Handling **Strategy:** Silent failures with user messaging; no error boundaries or try-catch blocks in current codebase. **Patterns:** - Fuel depletion check before whale processing (HuntingScene.killWhale): if fuel < 2, whale is discarded without processing - Whale only spawns if no alive whale exists: `if (this.currentWhale && this.currentWhale.getData('alive')) return;` - Inventory bounds clamped by Math.min/Math.ceil to prevent negative values - Crosshair position clamped to screen bounds: `Phaser.Math.Clamp(value, 0, max)` ## Cross-Cutting Concerns **Logging:** None implemented. Debug would require browser console. **Validation:** Minimal; mostly relies on initial state setup and boundary clamping. - Fuel: clamped to [0, 100] via Math.min operations - Whale oil: clamped to [0, 50] via Math.min operations - Penguins: clamped to [0, 20] via Math.min operations - Crosshair X: `Phaser.Math.Clamp(x, 0, 800)` - Crosshair Y: `Phaser.Math.Clamp(y, 0, 600)` **Authentication:** Not applicable; single-player game. **Device Detection:** Mobile detection via user agent regex in HuntingScene.create(): ```javascript this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); ``` --- *Architecture analysis: 2026-02-04*