mirror of
https://github.com/tiennm99/nntv.git
synced 2026-05-18 17:26:48 +00:00
35d3f45d6f
- Fix StaticGuard ignoring litCells and RotatingGuard not lighting facing direction - Fix guard cleanup leak (direction indicators not destroyed) - Add centralized theme system with dark stealth aesthetic - Add scene fade transitions and level completion animation - Add level progress persistence via localStorage - Add turn counter, locked/completed level states in LevelSelect - Redesign 12 levels across 6-act narrative arc with per-level story - Add LevelIntro scene showing story text before each level - Add bilingual (EN/VI) level story descriptions - Remove dead code (counter.js, duplicate game/main.js) - Initialize project docs (overview, architecture, code standards)
7.4 KiB
7.4 KiB
Codebase Summary - Night Ninja: Twilight Voyage
Overview
NNTV is a turn-based stealth puzzle game built with Phaser 3.88.2 and Vite 6.3.6. The codebase is organized into reusable modules with clear separation of concerns: scenes manage UI/flow, game objects handle logic, and utilities provide cross-cutting functionality.
Total Files: 21 JavaScript modules + 2 JSON locale files + config files
Module Inventory
Entry Point
- src/main.js (35 lines)
- Phaser game initialization
- Scene registration (8 scenes in order)
- Canvas size: 1024x768, scale mode FIT
- Arcade physics disabled (grid-based movement only)
Game Scenes (src/game/scenes/)
| File | Lines | Purpose |
|---|---|---|
| Boot.js | ~40 | System initialization |
| Preloader.js | ~60 | Asset loading (sprites, audio) |
| MainMenu.js | ~100 | Start game, settings, guide buttons |
| StoryIntro.js | ~50 | Opening narrative sequence |
| LevelSelect.js | ~120 | Level list, progress display, level launch |
| Game.js | ~300 | Main gameplay loop, UI, input handling |
| GameOver.js | ~80 | Loss screen, retry/menu options |
| Settings.js | ~70 | Language toggle, preferences |
| Guide.js | ~90 | Instructions, controls, gameplay rules |
Core Game Objects (src/game/objects/)
| File | Lines | Purpose |
|---|---|---|
| GridSystem.js | ~100 | Grid state management, cell queries, rendering |
| Player.js | ~80 | Ninja rabbit logic, movement, detection |
| Guard.js | ~150 | Base Guard class + 4 subclasses (Static, Rotating, Blinking, Patrolling) |
| TurnManager.js | ~60 | Turn cycle execution, detection checks |
| LightingSystem.js | ~50 | Light aggregation from guards, rendering |
Level Management (src/game/levels/)
| File | Lines | Purpose |
|---|---|---|
| Levels.js | ~450 | 12 level definitions (grid size, guards, walls, goals) |
| LevelManager.js | ~60 | Load/initialize level by ID |
| LevelTester.js | ~80 | Debug utility for testing levels |
Utilities & Configuration (src/game/)
| File | Lines | Purpose |
|---|---|---|
| theme.js | ~71 | COLORS, FONTS constants; button factory functions |
| localization.js | ~60 | Multi-language string management (EN/VI) |
| progress.js | ~43 | Level completion tracking via localStorage |
Localization (src/game/locales/)
| File | Keys | Purpose |
|---|---|---|
| en.json | ~50 | English translations (titles, buttons, messages) |
| vi.json | ~50 | Vietnamese translations (parallel structure) |
Class Hierarchy
Guard Inheritance
Guard (abstract)
├─ StaticGuard (always light same cells)
├─ RotatingGuard (rotate direction 90° per turn)
├─ BlinkingGuard (toggle lights on/off)
└─ PatrollingGuard (move on path, light adjacent)
All guards share:
- Constructor params:
scene, grid, row, col, color - Methods:
createSprite(),destroy(),update() - Abstract methods (subclass override):
updateLight(),onTurnChange() - Sprite: Phaser circle object (colored by type)
Scene Inheritance
All inherit from Phaser.Scene:
Phaser.Scene
├─ Boot (init phase)
├─ Preloader (asset loading)
├─ MainMenu (UI hub)
├─ StoryIntro (narrative)
├─ LevelSelect (level navigation)
├─ Game (gameplay)
├─ GameOver (loss/retry)
├─ Settings (preferences)
└─ Guide (help)
Key Data Structures
Level Object
{
id: 1, // 1-12
name: "First Steps",
grid: { rows: 6, cols: 6 },
player: { row: 0, col: 0 },
goal: { row: 5, col: 5 },
walls: [{ row: 1, col: 1 }, ...],
guards: [
{ type: "static", position: {...}, litCells: [...] },
{ type: "rotating", position: {...}, direction: 0 },
...
]
}
Cell State
{
isWall: boolean,
isGoal: boolean,
isLight: boolean
}
Progress Object
{
maxLevel: 1, // Highest unlocked level
completedLevels: [1, 2, 3] // Array of completed level IDs
}
Dependencies
| Package | Version | Purpose |
|---|---|---|
| phaser | 3.88.2 | Game framework (rendering, physics, input) |
| vite | 6.3.6 | Build tool, dev server |
| terser | 5.39.0 | JS minification (prod build) |
Public API Summary
GridSystem
new GridSystem(scene, rows, cols, cellSize)
.isValidPosition(row, col) → boolean
.isWall(row, col) → boolean
.setWall(row, col, value)
.isGoal(row, col) → boolean
.setGoal(row, col, value)
.isLight(row, col) → boolean
.setLight(row, col, value)
.render(offsetX, offsetY, cellSize)
Player
new Player(scene, grid, row, col)
.move(newRow, newCol) → boolean
.update()
.destroy()
Guard (Base)
new Guard(scene, grid, row, col, color)
.createSprite()
.updateLight() // Override in subclass
.onTurnChange() // Override in subclass
.destroy()
.update()
TurnManager
new TurnManager(scene)
.nextTurn() // Execute guard actions, detect collision
.reset()
LightingSystem
new LightingSystem(scene, grid)
.clearAllLight()
.updateLightFromGuards(guards)
Localization
getText(key) → string // Get current language text
setLanguage(lang) → boolean // 'en' or 'vi'
getLanguage() → string
initLanguage() // Load from localStorage
Progress
getProgress() → { maxLevel, completedLevels }
completeLevel(levelNum, totalLevels) → updated progress
File Dependency Map
main.js
└─ Boot, Preloader, MainMenu, StoryIntro, LevelSelect, Game, GameOver, Settings, Guide
Game.js
├─ GridSystem
├─ Player
├─ Guard (+ 4 subclasses)
├─ TurnManager
├─ LightingSystem
├─ LevelManager → Levels
├─ localization
├─ theme
└─ progress
LevelManager.js
└─ Levels
LevelSelect.js
├─ LevelManager
├─ progress
├─ localization
└─ theme
All Scenes
├─ localization (for UI text)
├─ theme (for colors, fonts, buttons)
└─ progress (for tracking)
Configuration Files
| File | Purpose |
|---|---|
| vite/config.dev.mjs | Dev server config (hot reload, logging) |
| vite/config.prod.mjs | Prod build config (minify, optimize) |
| index.html | Entry HTML, Phaser div target (#app) |
| public/style.css | Global styles (layout, responsive) |
| package.json | Dependencies, npm scripts |
Asset Organization
- public/assets/: Static sprites, audio, images (served directly)
- Imported in Preloader.js: Load via Phaser loader
- Vite bundling: ES module imports for bundled assets
Build Output
Dev Mode: npm run dev
- Source maps enabled
- Hot module reload
- Dev logging active
Prod Mode: npm run build
- Minified JS (terser)
- Assets optimized
- Output to
dist/directory
Statistics
| Metric | Value |
|---|---|
| Total JS Lines | ~2,100 |
| Number of Classes | 12 (8 scenes + 4 objects) |
| Number of Levels | 12 |
| Localization Keys | ~50 |
| Max Grid Size | 10x10 |
| Max Guards/Level | 8 |
| Browser Support | All (Phaser AUTO) |
Code Quality Notes
- No external frameworks beyond Phaser (pure vanilla JS + ES modules)
- Consistent patterns: Guard inheritance, scene lifecycle, utility exports
- Error handling: Try-catch in localStorage, null checks for dynamic objects
- Localization: Full coverage EN/VI, fallback to English
- Performance: Synchronous turn system, optimized lighting calculations