# Code Standards - Night Ninja: Twilight Voyage ## Naming Conventions ### Files - **Svelte components**: PascalCase (`Game.svelte`, `GameBoard.svelte`, `PlayerSprite.svelte`) - **JS modules**: kebab-case (`grid-system.js`, `turn-manager.js`, `level-manager.js`) - **JSON/config**: kebab-case (`en.json`, `vi.json`, `theme.css`) ### Variables & Functions - **Classes**: PascalCase (`GridSystem`, `Player`, `RotatingGuard`) - **Methods & Functions**: camelCase (`updateLight()`, `nextTurn()`, `getText()`) - **Constants**: UPPER_CASE for arrays (`LEVELS`), camelCase for others - **Svelte state**: camelCase (`renderVersion`, `isPaused`, `detected`) - **Props**: camelCase (`cellSize`, `oncellclick`, `onplayagain`) ### Grid Coordinates - **row**: Vertical axis (0 = top, increases downward) - **col**: Horizontal axis (0 = left, increases rightward) - **Position objects**: `{ row: num, col: num }` ## Code Organization ### Directory Structure ``` src/ ├── main.js # Entry point, mounts App.svelte ├── App.svelte # Scene router ({#key} + fade) │ ├── scenes/ # Full-page scene components │ ├── MainMenu.svelte │ ├── StoryIntro.svelte │ ├── LevelIntro.svelte │ ├── LevelSelect.svelte │ ├── Game.svelte # Main gameplay (state owner) │ ├── GameOver.svelte │ ├── Settings.svelte │ └── Guide.svelte │ ├── components/ # Reusable UI components │ ├── Button.svelte │ ├── GameBoard.svelte # Grid of pixel tiles │ ├── GameHud.svelte # Pixel hearts + pixel icons + level/turns │ ├── PlayerSprite.svelte # Pixel rabbit │ ├── GuardSprite.svelte # Pixel veggie dispatched by guard.type │ ├── PauseMenu.svelte │ ├── DetectionPopup.svelte │ ├── LevelCompletePopup.svelte │ └── ControlsOverlay.svelte │ ├── lib/ │ ├── game/ # Pure JS game engine (no framework) │ │ ├── grid-system.js │ │ ├── player.js │ │ ├── guards.js # Base + 6 guard subclasses; capture()/apply() contract │ │ ├── turn-manager.js # Uses guard.capture()/apply() for non-destructive preview │ │ ├── level-manager.js # GUARD_REGISTRY factory pattern │ │ ├── game-history.js # Undo/redo system │ │ ├── princess-mechanic.js # Level 12 escalating detection; capture()/apply() │ │ └── touch-controls.js # Mobile swipe support │ │ │ ├── pixel/ # Pixel-art rendering pipeline │ │ ├── Pixel.svelte # String-art + palette → SVG rects │ │ ├── palette.js # NNTV color constants │ │ ├── art-characters.js # Rabbit, princess, 6 veggie guards │ │ ├── art-tiles.js # 16×16 board tiles │ │ ├── art-ui.js # Hearts, moon, logo, icons │ │ └── art-scenes.js # 80×N act backdrops + sceneForLevel(n) │ │ │ ├── levels/ │ │ └── levels.js # 12 level definitions │ │ │ ├── locales/ │ │ ├── en.json │ │ └── vi.json │ ├── audio.js # Web Audio API sounds │ ├── localization.js │ └── progress.js │ └── styles/ └── theme.css # CSS variables (colors, fonts) ``` ### File Size Limits - **Maximum 200 lines per file** before considering split - Scenes with heavy logic → extract to `lib/game/` - Shared UI → extract to `components/` ## Svelte 5 Patterns ### State Management ```javascript // Primitive state let isPaused = $state(false); // Class instances (NOT auto-proxied — use renderVersion pattern) let grid = $state(null); let player = $state(null); let renderVersion = $state(0); // Derived values depend on renderVersion to pick up class mutations let cells = $derived((renderVersion, grid ? grid.getAllCells() : [])); ``` ### Props ```javascript let { navigate, level = 1, lives = 3 } = $props(); ``` ### Event Handlers ```svelte