Files
whalehunting/.planning/codebase/ARCHITECTURE.md
Thomas Richter 576799ae0e docs: map existing codebase
- 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
2026-02-04 23:16:04 +01:00

5.7 KiB

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():

this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

Architecture analysis: 2026-02-04