Commit Graph
76 Commits
Author SHA1 Message Date
tiennm99 0aad28e81d feat(levels): redesign L3 and L4 on 9x9 grid
Act 2 redesign — rotating guard (L3) and blinking guard (L4) introduced.
Both levels widened to 9x9. L4 solution requires a wait action to
synchronize with the blinking cycle, teaching the timing mechanic.
2026-04-21 21:22:30 +07:00
tiennm99 33f6c98a14 fix(levels): redesign L1 and L2 on 8x8 grid
L2 right-side region was disconnected — player could not reach the goal
via any sequence of moves (verified via BFS). New L2 places three static
guards with two viable paths. L1 widens to 8x8 as a gentle Act 1 intro.
Preserves id/name/storyKey/isFinalLevel for progress persistence.
2026-04-21 21:20:25 +07:00
tiennm99 bfed64d871 test(levels): add solvability suite with metadata invariants
Asserts L1/5-8/10 solvable, L12 unsolvable (easter-egg invariant), and
locks the 12-level count. Known-broken levels (L2/3/4/9/11) tracked
explicitly and auto-unskip when their redesign phases flip them.
2026-04-21 21:20:19 +07:00
tiennm99 19e3e9cb67 feat(game): add BFS level solver for solvability validation
Pure BFS over (player, guard snapshots, princess state). Reuses guards.js
and princess-mechanic.js so solver verdicts match runtime behavior. State
budget cap prevents runaway search on impossible levels.
2026-04-21 21:20:12 +07:00
tiennm99 0bf72c50d8 feat(game): scrollable viewport with camera-follow for large grids
Fix cellSize at 50 and wrap board-container with overflow:auto + smooth
scrollTo effect centered on player. Unlocks grid sizes beyond 9x9 without
shrinking cells below readable size.
2026-04-21 21:20:04 +07:00
tiennm99 6e2114162f docs(plans): add level redesign brainstorm and 11-phase plan
Fixes L2 unsolvable bug and widens grids across all 12 levels.
L12 preserved as unsolvable-by-normal-play (easter egg).
2026-04-21 21:19:56 +07:00
dependabot[bot] 692d90cafb build(deps): bump rollup from 4.40.0 to 4.60.1 (#7)
Bumps [rollup](https://github.com/rollup/rollup) from 4.40.0 to 4.60.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.40.0...v4.60.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.60.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 22:55:58 +07:00
dependabot[bot] 11860bcda3 build(deps-dev): bump vite from 6.3.6 to 6.4.2 (#6)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.3.6 to 6.4.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.4.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.4.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.4.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 22:54:45 +07:00
tiennm99 fb88e86d9a chore: ignore local .claude/ scratch dir 2026-04-20 22:46:27 +07:00
tiennm99 656c9ea504 fix: use relative asset base for portable build output
Built index.html now references ./assets/... instead of /assets/...
so the dist folder works when opened directly (file://), served from a
subpath (github pages project site, netlify deploy preview, etc.), or
any non-root path. Previously the absolute-root paths produced a blank
page with module load failures in those environments.

Also ignore .claude/ local scratch dir.
2026-04-20 22:46:14 +07:00
tiennm99 932516ca3e refactor: address code review — capture/apply contract, tests, docs
- Guards: add capture()/apply() dynamic-state snapshot contract; removes fragile per-type field lists in previewNextTurn and game-history
- TurnManager.previewNextTurn: use guard.capture/apply so new dynamic fields are picked up automatically
- PrincessMechanic: add capture()/apply() and include messageShown in undo snapshots
- Game.svelte: navigate to MainMenu when loadLevel returns null; track detection setTimeout for unmount cleanup
- LevelSelect: use getTotalLevels() instead of hardcoded 12
- audio.js: swallow resume() promise rejections
- art-scenes: norm() pads short rows with '.' transparent instead of last-char bleed
- Rename controls-overlay.svelte → ControlsOverlay.svelte (match PascalCase convention)
- Add vitest + tests for grid, player, guards, princess, turn-manager, game-history (46 tests)
- Update docs (codebase-summary, system-architecture, code-standards, README) for pixel pipeline and capture/apply contract
2026-04-20 22:22:03 +07:00
tiennm99 fb2f72f85b feat: apply pixel-art design assets across sprites, tiles, hud, and scenes 2026-04-20 22:03:16 +07:00
tiennm99 6a1b3ec572 feat: add design canvas assets from claude design 2026-04-20 21:46:21 +07:00
tiennm99 286edc3c1d remove completed plan and report files
Plans for Svelte 5 rewrite and gameplay improvements have been
fully implemented — removing the now-obsolete plan phases and
research report.
2026-04-14 11:43:03 +07:00
tiennm99 7233310662 feat: add undo/redo, audio, mobile controls, BFS pathfinding, and accessibility
- Fix ChaserGuard with BFS pathfinding and proper chase/return states
- Add undo/redo system (Z/Y keys) with full state snapshots
- Add procedural audio via Web Audio API (move, wait, detection, complete)
- Add mobile swipe controls with touch gesture detection
- Add detection feedback (cell flash, player shake animation)
- Add CSS transitions on grid cells for smooth lighting changes
- Add ARIA accessibility labels on game board and cells
- Add controls overlay ("?" button) showing all keyboard/touch shortcuts
- Add mute toggle in HUD
- Update Guide scene with chaser/mirror guard descriptions and tips
- Replace guard switch statement with factory registry pattern
- Extract princess mechanic and touch controls into separate modules
- Localize all UI strings (EN/VI) including new controls and tips
- Update README for Svelte 5 architecture with all current features
- Update project docs (architecture, code standards, codebase summary)
2026-04-13 18:24:46 +07:00
tiennm99 7aa81730a6 feat: add gameplay improvements — wait action, star rating, chaser guard, vision preview
- Wait action (Space/click player): skip turn while guards advance, enables timing puzzles
- Star rating system: 1-3 stars per level based on par moves, persisted in localStorage
- Level complete popup with animated star display and move count vs par
- Stars and best moves shown on level select screen
- ChaserGuard: new guard type that chases player's last known position when nearby
- All 12 levels redesigned with tighter corridors, more guards, and chasers in Act 5
- Guard vision preview (V key/button): ghost overlay shows next-turn danger zones
- Level 12 remains intentionally unbeatable with added chaser
2026-04-13 14:47:42 +07:00
tiennm99 710d7dec27 docs: add game design document with full level and mechanic specs
Complete game design requirements: story, 5 guard types, exact 12-level
spec (levels 1-11 solvable, level 12 unsolvable by design), escalating
princess detection, visual design, controls, UI screens, localization.
2026-04-12 23:35:10 +07:00
tiennm99 40a5b6218f docs: update all project docs for Svelte 5 rewrite and remove old plan
Rewrote project-overview-pdr, system-architecture, code-standards, and
codebase-summary to reflect current Svelte 5 architecture, mirror guard
mechanic, renderVersion reactivity pattern, and redesigned level
progression. Removed obsolete plan/NNTV.md (Phaser 3 plan).
2026-04-12 23:16:48 +07:00
tiennm99 0a00209881 fix: resolve Svelte 5 reactivity for class instances and redesign levels
Svelte 5 does not proxy class instances, so self-assignment (grid = grid)
was a no-op. Introduced renderVersion counter to force re-derivation of
all rendering data after game state mutations.

Also redesigned level progression with better mechanic teaching arc,
added Mirror Guard type (reflects rotating beams), and replaced instant
final-level detection with escalating light wave radiating from goal.
2026-04-12 22:58:05 +07:00
tiennm99 a1b9f38dea fix: downgrade vite-plugin-svelte to v6 for vite 6.x compatibility
@sveltejs/vite-plugin-svelte@7 requires vite@^8.0.0 but we use
vite@6.3.6. Downgrade to v6 which supports vite@^6.3.0.
Fixes npm ci failure in GitHub Actions deploy workflow.
2026-04-12 20:01:28 +07:00
tiennm99 f52dfde719 feat: rewrite from Phaser 3 to Svelte 5
Replace Phaser 3 game engine (~1MB) with Svelte 5 + Vite.
Bundle size: 77KB JS (28KB gzip) vs ~1MB with Phaser.

Architecture:
- src/lib/game/ — Pure JS game logic (guards, grid, player, turns)
- src/components/ — Svelte UI components (GameBoard, sprites, HUD)
- src/scenes/ — Scene components with fade transitions
- src/App.svelte — Scene router
- CSS Grid for game board, CSS transitions for movement
- svelte/transition for scene switching

All game logic preserved: 12 levels, 4 guard types, turn system,
detection, lives, progress persistence, bilingual localization,
level 12 special mechanic.

Removed: Phaser, terser, canvas rendering, physics engine,
custom vite configs, log.js telemetry.
2026-04-12 18:58:19 +07:00
tiennm99 4461e45502 fix: reset game state flags in init() so input works on level transitions
Phaser constructor only runs once; init() runs on every scene.start().
handleLevelComplete() was setting isPaused=true/inputEnabled=false which
persisted into subsequent levels, freezing player input.
2026-04-12 11:14:31 +07:00
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
dependabot[bot] 7eb454443c build(deps-dev): bump vite from 6.3.4 to 6.3.6
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.3.4 to 6.3.6.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.3.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.3.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 08:45:30 +07:00
tiennm99 103170db25 feat: update guard logics 2025-05-03 14:39:48 +07:00
tiennm99 8d0ff8ff03 feat: remove camera follow 2025-05-03 14:31:04 +07:00
tiennm99 df5c0c051c feat: intro 2025-05-03 14:26:08 +07:00
tiennm99 e3939d4132 feat: update story 2025-05-03 14:14:06 +07:00
tiennm99 f38b0d6865 fix: center game 2025-05-03 13:32:07 +07:00
tiennm99 44db5a4470 feat: update readme, merge style 2025-05-03 13:26:23 +07:00
tiennm99 09bf0863a4 feat: remove mobile buttons 2025-05-03 13:20:25 +07:00
tiennm99 b209662a67 Merge branch 'main' of https://github.com/tiennm99/nntv 2025-05-03 13:20:12 +07:00
dependabot[bot] 45b480753d build(deps-dev): bump vite from 6.3.2 to 6.3.4
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.3.2 to 6.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.3.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-03 13:12:55 +07:00
tiennm99 d81e800609 feat: merge plans 2025-05-03 13:10:39 +07:00
tiennm99 76d010267d feat: update plan & localize 2025-05-03 13:05:00 +07:00
tiennm99 386c74e6f9 feat: camera follow player 2025-04-27 23:18:18 +07:00
tiennm99 00f4415236 feat: remove instruction on start 2025-04-27 22:04:57 +07:00
tiennm99 3f1da352f1 feat: guide scrollable 2025-04-27 21:50:43 +07:00
tiennm99 eb64fd4859 feat: instruction 2025-04-27 20:14:42 +07:00
tiennm99 f70a9246f7 feat: split localize in to files 2025-04-27 20:02:29 +07:00
tiennm99 f7c504219a feat: localize 2025-04-27 19:57:25 +07:00
tiennm99 f766f7e3b8 feat: change guard to circle 2025-04-27 19:41:01 +07:00
tiennm99 f189c5f10c fix: triangle in grid (wip) 2025-04-27 19:16:34 +07:00
tiennm99 a062ade3c7 fix: close poup after replay 2025-04-27 19:08:03 +07:00
tiennm99 67cc6d64b7 fix: can not work through wall 2025-04-27 18:58:12 +07:00
tiennm99 4e82dc0264 feat: popup when caught 2025-04-27 18:52:58 +07:00
tiennm99 5b75abdd88 fix: bug when get into level 2025-04-27 18:44:27 +07:00
tiennm99 93f59a65ab feat: game generated from Manus (with some manual tweaks) 2025-04-27 18:38:32 +07:00
tiennm99 d851d43504 ci(pages): add workflows 2025-04-27 11:16:13 +07:00
tiennm99 1731863ec0 feat: init again with phaser vite webbundler 2025-04-27 11:03:20 +07:00