- STACK.md - Technologies and dependencies - ARCHITECTURE.md - System design and patterns - STRUCTURE.md - Directory layout - CONVENTIONS.md - Code style and patterns - TESTING.md - Test structure - INTEGRATIONS.md - External services - CONCERNS.md - Technical debt and issues
135 lines
5.7 KiB
Markdown
135 lines
5.7 KiB
Markdown
# 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*
|