Files
nntv/docs/codebase-summary.md
T
tiennm99 35d3f45d6f feat: redesign architecture, UI/UX, and story-driven levels
- 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)
2026-04-12 10:53:04 +07:00

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