docs: Standardize module documentation and focus on final product
- Added complete documentation for state.js, maze.js, grid.js, sfx.js (was: 'Already Well-Structured — No Changes') - Removed 'Refactoring Summary' section (process-focused content) - Restructured 'Design Decisions & Rationale' to document current architecture rather than refactoring journey - Updated 'AI Assistance' section to mention refactoring work in context of overall development - Simplified 'Files Structure' legend to remove distinction between refactored and original modules - All 14 modules now documented consistently with Purpose/Functions/Benefits Result: Documentation now explains the final product cleanly without the 'something changed' narrative, while preserving context of development work.
This commit is contained in:
257
README.md
257
README.md
@@ -108,9 +108,12 @@ sfx/
|
|||||||
└── sfx_chest_close.wav # Chest closing sound
|
└── sfx_chest_close.wav # Chest closing sound
|
||||||
```
|
```
|
||||||
|
|
||||||
**Legend:**
|
**Module Organization:**
|
||||||
- ✓ Unchanged from original (already well-structured)
|
- **game/**: Core game logic (state, generation, collision, audio)
|
||||||
- Without checkmark = newly extracted/refactored
|
- **controls/**: Input and event handling
|
||||||
|
- **assets/**: Reusable factories (materials, textures)
|
||||||
|
- **ui/**: Visual feedback (HUD, overlays)
|
||||||
|
- Root level (babylon_panel.js): Main orchestrator that ties everything together
|
||||||
|
|
||||||
### Core Modules
|
### Core Modules
|
||||||
|
|
||||||
@@ -289,21 +292,96 @@ Page Load → babylon_panel.js
|
|||||||
- Reusable styling/animation controls
|
- Reusable styling/animation controls
|
||||||
- Can easily add new HUD elements
|
- Can easily add new HUD elements
|
||||||
|
|
||||||
#### 11. **game/state.js** (Shared State) ✓
|
#### 11. **game/state.js** (Shared State)
|
||||||
**Already Well-Structured — No Changes**
|
**Purpose:** Centralized game state management to prevent coupling between modules
|
||||||
Centralized game configuration and runtime state
|
|
||||||
|
|
||||||
#### 12. **game/maze.js** (Procedural Generation) ✓
|
**Structure:**
|
||||||
**Already Well-Structured — No Changes**
|
```javascript
|
||||||
Recursive backtracking with seeded RNG
|
window.mazeGameState = {
|
||||||
|
config: {
|
||||||
|
seed, // Reproducible maze generation
|
||||||
|
level, // Current progression level
|
||||||
|
mazeWidth: 11, // Base width (increases per level)
|
||||||
|
mazeHeight: 11, // Base height
|
||||||
|
minChestDeadEnds: 2 // Min chests to place
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
runActive, // Is gameplay active?
|
||||||
|
hasKey, // Player collected key?
|
||||||
|
roundsCompleted, // Levels completed this run
|
||||||
|
elapsedSeconds, // Countdown timer (60 → 0)
|
||||||
|
message // Status text for HUD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### 13. **game/grid.js** (Coordinate Utilities) ✓
|
**Benefits:**
|
||||||
**Already Well-Structured — No Changes**
|
- Single source of truth for all game state
|
||||||
Grid-to-world conversions and walkability checks
|
- All modules read/write to same object (no data duplication)
|
||||||
|
- Easy to serialize/save game state
|
||||||
|
- Enables time-travel debugging via console inspection
|
||||||
|
|
||||||
#### 14. **game/sfx.js** (Audio System) ✓
|
#### 12. **game/maze.js** (Procedural Generation)
|
||||||
**Already Well-Structured — No Changes**
|
**Purpose:** Generate solvable, deterministic mazes using seeded randomization
|
||||||
ES6 import-based audio loading and playback
|
|
||||||
|
**Functions:**
|
||||||
|
- `seededRng(seed)` — Deterministic random number generator (same seed = same sequence)
|
||||||
|
- `generateMazeGrid(w, h, seed)` — Recursive backtracking maze algorithm
|
||||||
|
- `findDeadEnds(grid)` — Locate dead-end cells for chest/exit placement
|
||||||
|
|
||||||
|
**Algorithm:**
|
||||||
|
Recursive backtracking with seeded RNG ensures:
|
||||||
|
- Every maze is solvable (connected)
|
||||||
|
- Same seed produces identical maze (perfect for replays)
|
||||||
|
- Configurable difficulty (width/height parameters)
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Deterministic yet varied level generation
|
||||||
|
- No performance issues (pre-computed before rendering)
|
||||||
|
- Perfect reproducibility for competitive play
|
||||||
|
|
||||||
|
#### 13. **game/grid.js** (Coordinate Utilities)
|
||||||
|
**Purpose:** Convert between grid coordinates and 3D world space for collision detection
|
||||||
|
|
||||||
|
**Functions:**
|
||||||
|
- `gridCellToWorld(grid, x, y, cellSize)` — Grid cell → world position (returns `{x, z}`)
|
||||||
|
- `isWalkableCell(grid, x, y)` — Check if cell is navigable (not a wall)
|
||||||
|
|
||||||
|
**Key Insight:**
|
||||||
|
Mazes are generated as 2D grids (1 = wall, 0 = path). This module bridges the gap between grid coordinates used by `maze.js` and 3D world positions used by `level-generator.js`.
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Decouples grid logic from spatial positioning
|
||||||
|
- Makes collision detection and pathfinding calculations simpler
|
||||||
|
- Reusable for any grid-based game mechanic
|
||||||
|
|
||||||
|
#### 14. **game/sfx.js** (Audio System)
|
||||||
|
**Purpose:** Load and playback polyphonic sound effects with Web Audio API
|
||||||
|
|
||||||
|
**Functions:**
|
||||||
|
- `playSfx(name, volume)` — Play a sound effect by name (cloned for polyphony)
|
||||||
|
- `primeSfx()` — Initialize audio context (required by browser for first sound)
|
||||||
|
|
||||||
|
**Audio Files** (imported via ES6, bundled by Vite):
|
||||||
|
```javascript
|
||||||
|
import clickUrl from "../../sfx/sfx_click.wav"
|
||||||
|
import chestOpenUrl from "../../sfx/sfx_chest_open.wav"
|
||||||
|
import chestCloseUrl from "../../sfx/sfx_chest_close.wav"
|
||||||
|
import keyUrl from "../../sfx/sfx_key.wav"
|
||||||
|
import clockUrl from "../../sfx/sfx_clock.wav"
|
||||||
|
import stepUrl from "../../sfx/sfx_step.wav"
|
||||||
|
import winUrl from "../../sfx/sfx_win.wav"
|
||||||
|
import loseUrl from "../../sfx/sfx_lose.wav"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Polyphony via Cloning:**
|
||||||
|
Each call to `playSfx()` clones the audio node, allowing multiple sounds to play simultaneously (e.g., footsteps + clock alarm).
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Polyphonic sound effects (no cutting each other off)
|
||||||
|
- Browser-compatible audio context priming
|
||||||
|
- ES6 imports ensure assets are bundled by Vite
|
||||||
|
- Centralized audio management (easy to add volume controls, reverb, etc.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -330,7 +408,6 @@ ES6 import-based audio loading and playback
|
|||||||
- Audio context requires user interaction priming via `primeSfx()`—automatically triggered on first W/A/S/R key press
|
- Audio context requires user interaction priming via `primeSfx()`—automatically triggered on first W/A/S/R key press
|
||||||
|
|
||||||
**Performance Optimizations:**
|
**Performance Optimizations:**
|
||||||
- Vite's ES6 module bundling and tree-shaking
|
|
||||||
- Asset optimization (textures, audio)
|
- Asset optimization (textures, audio)
|
||||||
- Efficient raycasting for chest targeting (not per-pixel)
|
- Efficient raycasting for chest targeting (not per-pixel)
|
||||||
- Single draw call per maze (not per cell)
|
- Single draw call per maze (not per cell)
|
||||||
@@ -358,99 +435,49 @@ ES6 import-based audio loading and playback
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Refactoring Summary (Phase 3 Complete)
|
|
||||||
|
|
||||||
### Code Metrics
|
|
||||||
| Metric | Before | After | Change |
|
|
||||||
|--------|--------|-------|--------|
|
|
||||||
| Main file (babylon_panel.js) | 570 lines | 195 lines | -66% |
|
|
||||||
| Total source files | 5 | 14 | +9 new modules |
|
|
||||||
| Build modules | 355 | 364 | +9 (new files) |
|
|
||||||
| Cyclomatic complexity | High | Low | Each module < 20 lines avg |
|
|
||||||
|
|
||||||
### Dependency Graph
|
|
||||||
```
|
|
||||||
babylon_panel.js (Orchestrator)
|
|
||||||
├── game/scene-init.js
|
|
||||||
├── game/camera-manager.js
|
|
||||||
├── controls/input-handler.js
|
|
||||||
│ └── game/sfx.js
|
|
||||||
├── game/level-generator.js
|
|
||||||
│ ├── game/maze.js
|
|
||||||
│ ├── game/grid.js
|
|
||||||
│ └── assets/materials.js
|
|
||||||
├── game/game-loop.js
|
|
||||||
│ ├── game/sfx.js
|
|
||||||
│ ├── game/collisions.js
|
|
||||||
│ └── ui/hud.js
|
|
||||||
├── game/screen-manager.js
|
|
||||||
│ └── p5_particles.js
|
|
||||||
└── game/state.js (shared by all)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Module Characteristics
|
|
||||||
- **No circular dependencies:** Each module imports only from modules below it
|
|
||||||
- **Shared state:** All modules read/write `window.mazeGameState` (single source of truth)
|
|
||||||
- **Event-driven:** Input → callbacks → state update → HUD refresh
|
|
||||||
- **Callback pattern:** Higher modules pass callbacks to lower modules for decoupling
|
|
||||||
|
|
||||||
### Refactoring Safety Checklist
|
|
||||||
✓ **Build tested:** `npm run build` completes with 364 modules, no errors
|
|
||||||
✓ **No breaking changes:** `window.mazeGameApi.generateLevel()` still exported
|
|
||||||
✓ **Audio bundling intact:** All 8 SFX files in dist/assets/ with hashes
|
|
||||||
✓ **Backwards compatible:** All gameplay mechanics unchanged
|
|
||||||
✓ **No new dependencies:** Uses existing npm packages only
|
|
||||||
✓ **ESM imports work:** Vite resolves all relative paths correctly
|
|
||||||
|
|
||||||
### Next Steps for Future Maintenance
|
|
||||||
1. **Add new interaction types:** Extend `game/collisions.js` with new raycasts
|
|
||||||
2. **Add gamepad support:** Extend `controls/input-handler.js` with gamepad listeners
|
|
||||||
3. **Add new screens:** Add functions to `game/screen-manager.js`
|
|
||||||
4. **Add new camera modes:** Extend `game/camera-manager.js` with new camera types
|
|
||||||
5. **Add sound designer tools:** Extend `game/sfx.js` with volume/pan controls
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Design Decisions & Rationale
|
## Design Decisions & Rationale
|
||||||
|
|
||||||
### Refactoring Strategy (Phase 3 Complete)
|
### 1. Modular Architecture with Separation of Concerns
|
||||||
**Objective:** Improve code maintainability without breaking gameplay
|
**Decision:** Organize code into 14 focused modules rather than monolithic files
|
||||||
|
|
||||||
**Approach:** Modular separation of concerns by extracting 9 new modules from the original monolithic `babylon_panel.js` (570 lines → 195 lines).
|
**Rationale:**
|
||||||
|
- Each module has a single responsibility (scene setup, input handling, collision detection, etc.)
|
||||||
|
- No circular dependencies — clean dependency flow from orchestrator down to utilities
|
||||||
|
- Easier to test, debug, and extend individual features
|
||||||
|
- New developers can understand one module without understanding the whole codebase
|
||||||
|
- Easy to add features: extend relevant modules instead of modifying monolithic files
|
||||||
|
|
||||||
#### Why This Structure?
|
**Architecture Pattern:**
|
||||||
|
```
|
||||||
|
babylon_panel.js (orchestrator) ← high-level control
|
||||||
|
├→ game/scene-init.js ← rendering setup
|
||||||
|
├→ game/camera-manager.js ← camera control
|
||||||
|
├→ controls/input-handler.js ← event routing
|
||||||
|
├→ game/level-generator.js ← spatial layout
|
||||||
|
├→ game/game-loop.js ← frame updates
|
||||||
|
├→ game/screen-manager.js ← UI transitions
|
||||||
|
└→ game/state.js ← shared data (all modules)
|
||||||
|
```
|
||||||
|
|
||||||
| Module | Benefit |
|
### 2. Shared State Pattern via window.mazeGameState
|
||||||
|--------|---------|
|
**Decision:** Centralize all game state in single `window.mazeGameState` object
|
||||||
| **scene-init.js** | Isolate Babylon.js boilerplate from game logic |
|
|
||||||
| **camera-manager.js** | Encapsulate complex camera configuration; easy to test/add modes |
|
|
||||||
| **level-generator.js** | Pure spatial functions; reusable for future level types |
|
|
||||||
| **game-loop.js** | Frame-by-frame logic visible in one place; easier to debug timing |
|
|
||||||
| **collisions.js** | Isolated raycasting; reusable for new interaction types |
|
|
||||||
| **input-handler.js** | Centralized event routing; easy to add gamepad/mobile controls |
|
|
||||||
| **screen-manager.js** | p5 lifecycle management; easy to add new screens (pause, level intro) |
|
|
||||||
| **materials.js** | Texture setup reusable by other systems; centralized configuration |
|
|
||||||
| **hud.js** | DOM updates separate from game state; CSS animations cleanly decoupled |
|
|
||||||
|
|
||||||
#### Testing Benefits
|
|
||||||
- **Unit testable:** Each module has single responsibility, minimal dependencies
|
|
||||||
- **Integration testable:** Callbacks allow mocking of complex systems
|
|
||||||
- **Less fragile:** Changing one concern doesn't require refactoring others
|
|
||||||
|
|
||||||
#### Developer Experience
|
|
||||||
- **Faster onboarding:** New developers can understand features one module at a time
|
|
||||||
- **Feature additions:** Adding chests, NPCs, traps only requires extending relevant modules
|
|
||||||
- **Debugging:** Isolating bugs is easier when concerns are separated
|
|
||||||
|
|
||||||
### Original Design Decisions (Unchanged)
|
|
||||||
**Decision:** Isolate game state in `game/state.js` rather than scatter variables globally
|
|
||||||
|
|
||||||
**Rationale:**
|
**Rationale:**
|
||||||
- Prevents tight coupling between UI, physics, and rendering systems
|
- Prevents tight coupling between UI, physics, and rendering systems
|
||||||
|
- All modules read/write from same source of truth (no data duplication)
|
||||||
|
- Simplifies debugging (inspect state in console at any time)
|
||||||
- Enables hot-reloading during development
|
- Enables hot-reloading during development
|
||||||
- Simplifies debugging (single place to inspect game state)
|
|
||||||
|
|
||||||
#### 2. Babylon.js Over Three.js
|
### 3. Callback-Based Event Routing
|
||||||
|
**Decision:** Lower modules don't know about higher modules; communication via callbacks
|
||||||
|
|
||||||
|
**Rationale:**
|
||||||
|
- Reduces coupling between layers
|
||||||
|
- Easy to mock/test: pass different callbacks to change behavior
|
||||||
|
- Flexible event handling: same module used for different purposes
|
||||||
|
- Example: `registerGameLoop(scene, state, callbacks)` doesn't know about UI — it just calls callbacks
|
||||||
|
|
||||||
|
### 4. Babylon.js Over Three.js
|
||||||
**Decision:** Used Babylon.js for 3D graphics
|
**Decision:** Used Babylon.js for 3D graphics
|
||||||
|
|
||||||
**Rationale:**
|
**Rationale:**
|
||||||
@@ -459,7 +486,7 @@ babylon_panel.js (Orchestrator)
|
|||||||
- Efficient mesh instancing for maze cells
|
- Efficient mesh instancing for maze cells
|
||||||
- Excellent documentation for procedural generation
|
- Excellent documentation for procedural generation
|
||||||
|
|
||||||
#### 3. p5.js for Particle Effects
|
### 5. p5.js for Particle Effects
|
||||||
**Decision:** Delegated particle rendering to p5.js instead of Babylon.js
|
**Decision:** Delegated particle rendering to p5.js instead of Babylon.js
|
||||||
|
|
||||||
**Rationale:**
|
**Rationale:**
|
||||||
@@ -468,7 +495,7 @@ babylon_panel.js (Orchestrator)
|
|||||||
- Easy to swap/experiment with particle physics without affecting core game
|
- Easy to swap/experiment with particle physics without affecting core game
|
||||||
- Full-screen 2D canvas doesn't compete with 3D rendering pipeline
|
- Full-screen 2D canvas doesn't compete with 3D rendering pipeline
|
||||||
|
|
||||||
#### 4. Time-Attack Mode (vs. Exploration, Level Editing)
|
### 6. Time-Attack Mode (vs. Exploration, Level Editing)
|
||||||
**Decision:** 60-second countdown instead of unlimited time
|
**Decision:** 60-second countdown instead of unlimited time
|
||||||
|
|
||||||
**Rationale:**
|
**Rationale:**
|
||||||
@@ -476,20 +503,34 @@ babylon_panel.js (Orchestrator)
|
|||||||
- Enables meaningful progression (faster times unlock harder mazes)
|
- Enables meaningful progression (faster times unlock harder mazes)
|
||||||
- Reduces scope (no need for complex AI, item management, etc.)
|
- Reduces scope (no need for complex AI, item management, etc.)
|
||||||
|
|
||||||
|
### 7. Procedural Maze Generation with Seeded RNG
|
||||||
|
**Decision:** Use seeded random number generator for deterministic maze generation
|
||||||
|
|
||||||
|
**Rationale:**
|
||||||
|
- Same seed produces identical maze (perfect for replays/debugging)
|
||||||
|
- Varied layouts via different seeds (infinite replayability)
|
||||||
|
- Better than storing pre-made levels (scalable to any difficulty)
|
||||||
|
- Recursive backtracking ensures every maze is solvable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Help from AI & Resources
|
## Help from AI & Resources
|
||||||
|
|
||||||
### AI Assistance
|
### AI Assistance
|
||||||
- **GitHub Copilot:** Used for code structure review and refactoring suggestions
|
- **GitHub Copilot:** Used throughout development for code quality, structure, and refactoring
|
||||||
- Suggested separating static maze data from dynamic game state (instead of coupling both in a single 2D array)
|
- **Early Development:** Suggested separating static maze data from dynamic game state (prevents coupling)
|
||||||
- Helped organize modules into logical file structure
|
- **Module Organization:** Proposed logical file structure to improve maintainability
|
||||||
- Reviewed p5.js particle physics for correctness
|
- **Code Review:** Reviewed p5.js particle physics, Babylon.js camera control, Web Audio API integration
|
||||||
|
- **Refactoring (Phase 3):** Assisted with modularizing 570-line monolithic file into 14 focused modules
|
||||||
|
- Extracted scene initialization, camera management, game loop, level generation, collision detection
|
||||||
|
- Created input handler, material factories, HUD updates, screen manager modules
|
||||||
|
- Verified no breaking changes, ensured build compatibility, tested audio bundling
|
||||||
|
|
||||||
### Resources & Documentation
|
### Resources & Documentation
|
||||||
- **Babylon.js Playground:** Reference for collision detection and camera control
|
- **Babylon.js Playground:** Reference for collision detection, camera control, and mesh creation
|
||||||
- **p5.js Documentation:** Async setup pattern for p5.js 2.0+ (no `preload()`)
|
- **p5.js Documentation:** Async setup pattern for p5.js 2.0+ (no `preload()` function)
|
||||||
- **MDN Web Audio API:** Context priming for cross-browser audio compatibility
|
- **MDN Web Audio API:** Context priming and polyphonic sound playback patterns
|
||||||
|
- **Vite Documentation:** ES6 module bundling, asset optimization, and build configuration
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user