mirror of
https://github.com/tiennm99/nntv.git
synced 2026-10-15 22:14:57 +00:00
c2c8ad0ab2f0e3a87b7b29bd5859f6aa75e8914f
Asset review + regeneration - Regenerate keyart-palace.png to remove STUDIOSWAG watermark - Regenerate keyart-portrait.png as true 16-bit pixel art (was 3D/cinematic) - Regenerate vi-welcome.mp3 as a 31KB short line (was 808KB misplaced story) - Generate 10 missing VI voice lines (levelclear, princess-help, princess-run, gameover, 6 act intros) in Vietnamese_kindhearted_girl - Replace broken PHASER logo + 16x16 favicon with proper NNTV wordmark + 32x32 rabbit sprite - Add UI scene backgrounds (scene-menu/story/guide/settings) for in-app use - Add 6 keyart images (1280x720) + portrait (1024x1024) + poster for store/social - Delete orphan assets: bg.png, nntv-generated-sheet.png, scraps/sketch.napkin - Add MANIFEST.json + MEDIA.json documenting the asset corpus BGM integration - New src/lib/bgm.js: HTMLAudioElement BGM manager with 600ms crossfade, per-track loop, autoplay-blocked fallback, persistent sfxMuted/bgmMuted/ bgmVolume in localStorage (key: nntv-audio-settings) - App.svelte scene router picks the track per scene; L12 uses the climactic chamber track, all other Game scenes use the levels loop - audio.js: setMuted/isMuted now mirror bgm.js so GameHud's SND/MUTE button silences both SFX and BGM (master toggle) - Settings.svelte: new Audio panel with SFX toggle, BGM toggle, BGM volume slider (0-100%, disabled when BGM is off); bilingual - MainMenu/StoryIntro/Guide/Settings: top band scene backdrops at ~0.5 opacity - New i18n keys: audioSettings, sfxLabel, bgmLabel, volumeLabel, on, off, muted, sound (en + vi) - GameHud label localized (SND / MUTED) Tests: 180/180 passing. Build: clean (139KB JS / 28KB CSS gzipped).
Night Ninja: Twilight Voyage
Turn-based stealth puzzle game built with Svelte 5. Play as a ninja rabbit navigating grid-based levels inside the Vegetable Kingdom, avoiding detection by vegetable guards to rescue the missing carrot princess.
Play: pnpm dev → http://localhost:5173
Features
- 12 levels across 6 acts — grids grow from 8×8 to 13×13; difficulty escalates per act
- 8 guard types — Static (wilting aura), Rotating (beam), Blinking (toggle), Patrolling, Mirror (beam redirect), Chaser (BFS hunt), Sniper (fixed line of sight), Suspicion (tier alert)
- Throwable stones — press E to distract rotating, patrolling, and chaser guards
- Doors and keys — color-coded key items unlock matching doors
- One-way tiles — arrow tiles enforce entry direction
- Decay tiles — cells that cool over turns; dangerous while warm
- Undo/redo — press Z / Y (when level allows); full state snapshots including door state
- Turn preview — press V to preview next-turn lighting (when level allows)
- Procedural audio — Web Audio API; move, detect, throw, key pickup, door unlock, suspicion
- Pixel-art rendering — all sprites drawn as string-art palettes → SVG rects
- BFS solvability CI — levels L1–L11 verified beatable in CI; L12 intentionally unsolvable
- Bilingual — English and Vietnamese (VI) locale support
Requirements
Quick Start
git clone https://github.com/tiennm99/nntv
cd nntv
pnpm install
pnpm dev # dev server at http://localhost:5173
Commands
| Command | Description |
|---|---|
pnpm dev |
Start development server |
pnpm build |
Production build → dist/ |
pnpm preview |
Preview production build locally |
pnpm test |
Run all unit + solvability tests |
pnpm test:solvability |
Run only the BFS solvability suite |
Controls
| Input | Action |
|---|---|
| Arrow keys / WASD | Move one cell |
| Click adjacent cell | Move |
| Space | Wait one turn |
| V | Preview next-turn lighting |
| Z / Y | Undo / redo |
| E | Enter stone-throw targeting mode |
| Enter / E (in throw mode) | Throw stone |
| Esc | Cancel throw |
Architecture
Pure JavaScript game engine with a Svelte 5 rendering layer.
src/
├── lib/game/ # Pure JS engine
│ ├── grid.js # Cell state: walls, goals, lighting, doors, warm tiles
│ ├── player.js # Position, movement validation, key inventory (bitmask)
│ ├── guards.js # 8 guard type implementations
│ ├── throwable.js # Stone inventory, throw validation (Manhattan ≤3, LoS)
│ ├── turn.js # Turn cycle with preview simulation
│ ├── history.js # Undo/redo via state snapshots
│ └── solver.js # BFS solvability checker (reused by CI + runtime AI)
├── lib/levels/ # 12 level definitions + solvability test suite
├── lib/pixel/ # Pixel-art renderer, palette, sprite/tile/scene art
├── lib/locales/ # en.json + vi.json
├── lib/audio.js # Procedural Web Audio sound effects
├── scenes/ # MainMenu, Game, Guide, Settings, GameOver
└── components/ # GameBoard, HUD, sprites, overlays
Engine loop: each player action triggers TurnManager, which advances all guard
states simultaneously, recomputes lit cells, checks detection, and appends a snapshot
to GameHistory. LevelSolver (BFS over the same state machine) is run in CI against
every level definition to catch regressions before merge.
Project Structure
| Path | Description |
|---|---|
index.html |
HTML entry point |
src/main.js |
Application bootstrap |
src/App.svelte |
Scene router + migration modal |
src/styles/theme.css |
CSS variables: colors, fonts, guard palette |
svelte.config.js |
Svelte 5 + Vite config |
vite.config.js |
Vite build config |
License
Apache 2.0
Languages
JavaScript
98.2%
CSS
0.9%
HTML
0.8%
TypeScript
0.1%