mirror of
https://github.com/tiennm99/sokoban.git
synced 2026-10-11 12:29:05 +00:00
8.3 KiB
8.3 KiB
Project Changelog
2026-04-28 — Mobile Mistouch & Layout Fix
Fixed
- Footer mistouch during gameplay:
miti99.comlink in the global footer was overlapping the D-pad/action-stack tap zones at the bottom of the screen. Footer now hidden onview === 'game'(App.svelte), visible only on Menu + Level Select. - D-pad/board overlap on small viewports:
MobileControlsno longer usesposition: fixed. The dock-left + D-pad live in a single in-flow flex row at the bottom ofGameView's flex column. Board-wrap is nowflex: 1 1 auto; min-height: 0so puzzles scroll within their wrapper, never under the controls. Magicmax-height: calc(100vh - 260px)removed. - Footer safe-area: Added
env(safe-area-inset-bottom)to.site-footeroffset so it sits above the iPhone home-indicator gesture bar. - WCAG-AA contrast: Armed RESET button uses white text (4.85:1 on
--danger) instead of--bgtext (failed AA at 3.1:1).
Added
- Reset two-tap arming (
MobileControls.svelte): First tap on RESET arms (label flips "RESET" → "TAP AGAIN", red background, 2s timeout); second tap within the window restarts. Prevents mid-puzzle wipe-outs from a stray thumb. KeyboardRunchanged (immediate reset). - D-pad press-and-hold repeat: Holding any arrow continuously moves the player at 130 ms cadence (parity with keyboard
REPEAT_MS). Implemented via Pointer Events (pointerdown/pointerup/pointercancel/pointerleave) + sharedsetInterval.e.preventDefault()onpointerdownsuppresses the synthesized click double-fire.
Changed
App.svelte: Conditional footer render; safe-area offset on.site-footer.GameView.svelte:.gameis nowalign-self: stretch; display: flex; flex-direction: column;so it fills#app's inner area without forcing page-scroll..board-wrapbecomes the flex-grow child.computeTileSizemargin reduced from 260→220 (coarse) and 140→120 (fine) since the dock is no longer fixed-positioned.MobileControls.svelte: Rewritten — drops fixed positioning + z-index, wraps dock-left + D-pad in.mobile-dockflex row, gains arming + hold-repeat state with$effectcleanup on unmount.
Notes
- Bundle: 70.02 kB JS / 24.68 kB gzipped (no meaningful change).
- Build clean. Manual smoke test pending on real iOS/Android.
- Plan:
plans/260428-1004-mobile-mistouch-fix/.
2026-04-27 — Mobile Comfort & PWA
Added
- On-screen D-pad + action stack (
MobileControls.svelte, ~90 LOC): Hidden on desktop via@media (pointer: coarse), visible on touch devices. D-pad bottom-right, actions (Undo/Restart/Levels) bottom-left. Tap-only, no auto-repeat. - Haptics module (
lib/core/haptics.js, ~13 LOC): Wrapsnavigator.vibrate. Pulses 10 ms on box push, 60 ms on win. Silent no-op where unsupported. - Safe-area insets: MobileControls and Board respect
env(safe-area-inset-*)for notch/Home-indicator safety on iPhone and Android. - Gesture blocking: Board sets
touch-action: noneglobally to block browser pull-to-refresh, double-tap zoom, and long-press selection. - PWA (Progressive Web App): Full offline support via
vite-plugin-pwa. Includes Web Manifest (standalone display, theme color #5e81ac), Workbox service worker (auto-update, asset caching), and adaptive icons (192/512/maskable PNG). Installable via "Add to Home Screen" on iOS/Android.
Changed
GameView.svelte: Now importspulse()from haptics module; callspulse(10)when a box moves,pulse(60)on level win.Board.svelte: Added globaltouch-action: noneto prevent browser interference with touch interactions.vite/config.prod.mjs: IntegratedVitePWAplugin with manifest, workbox caching, and icon definitions.
Removed
- No breaking changes. Keyboard input, desktop layout, and win flow unchanged. Mobile features degrade gracefully on non-touch devices.
Notes
- Testing: Manual smoke test on iOS Safari + Android Chrome confirmed D-pad reachable one-handed, browser quirks blocked, offline play works, installable.
- Bundle impact: PWA metadata adds ~2 kB; total bundle remains ≈ 65 kB JS / 23 kB gzipped.
- Desktop regression: Keyboard (arrows/WASD), undo (U/Z), restart (R), menu (Esc), move counter, win overlay all unchanged.
2026-04-12 — Svelte rewrite
Changed
- Replaced Phaser 3 with Svelte 5 as the rendering and UI layer. The game is now a static DOM app — native
<button>elements, CSS grid board,transformanimations with CSS transitions. - Bundle shrinks from ~1.5 MB Phaser to 65 kB JS / 23 kB gzipped (about 60× smaller).
- New layout:
src/App.svelte,src/views/*.svelte,src/lib/core/,src/lib/data/. Framework-agnostic core modules (level-parser,board-model,progress-store,microban-levels) moved fromsrc/game/core→src/lib/corewith zero code changes. - Theme moved from a JS
theme.jsmodule into CSS custom properties insrc/app.css. - Native buttons replace the bespoke Phaser button factory — click reliability is now a browser concern, not ours.
- Vite configs cleaned up: removed Phaser-specific
manualChunks, the terser block, and thephasermsgplugin. npm run dev/npm run buildno longer wrapnode log.js(Phaser analytics ping removed).
Added
src/views/AppButton.svelte— shared themed button, wraps native<button>with hover, focus-visible, and disabled styles.src/views/Board.svelte— presentational DOM renderer: floor, walls, targets, boxes, player, each via absolute positioning inside a sized container.- Live
resizelistener inGameView.svelteso tile size re-computes when the window changes.
Removed
phaserdependency,terserdevDependency.src/game/(oldmain.js,scenes/,ui/,core/theme.js).log.js(Phaser analytics ping).
2026-04-11 — Full Microban set
Changed
- Level data expanded from the first 100 Microban puzzles to the complete 155-level set, including the oversized finale mazes ("Take the long way home", "The Dungeon"). Credit language updated everywhere to match.
2026-04-11 — Overhaul
Added
- 100 Microban levels (David W. Skinner) as the new stock level set, replacing the 3 hand-crafted puzzles. Stored as XSB text in
src/game/data/microban-levels.js. - XSB level parser (
core/level-parser.js) with flood-fill floor detection. - BoardModel (
core/board-model.js) — pure state, undo history, win detection. - Progress store (
core/progress-store.js) — localStorage persistence of completion + best move count, fails gracefully if unavailable. - BoardRenderer (
ui/board-renderer.js) — floor/wall/target/box/player drawing with animated moves. - Button factory (
ui/button-factory.js) — one rounded-button implementation shared by every scene. - Nord theme (
core/theme.js) — palette, fonts, and responsive tile-size helper. - Paginated level select: 5×4 grid × 5 pages, shows ✓ + best move count per completed level.
- WASD controls, U/Z undo, R restart, Esc to menu, move counter, win overlay with NEXT / LEVELS buttons.
docs/— PDR, codebase summary, code standards, system architecture, roadmap, this changelog.
Changed
- Scenes renamed to kebab-case (
menu-scene.js,level-scene.js,game-scene.js) and rebuilt against the new core/ui modules. main.jsnow imports a shared theme and registers only the three new scenes.public/style.cssnow uses a radial gradient background and rounds the game container.index.htmltitle updated.
Removed
MenuScene.js,LevelScene.js,MainScene.js(old PascalCase versions).public/assets/levels/level1.json,level2.json,level3.json.- Arcade Physics setup inside
MainScene— it was configured but never actually drove movement (moves were all tween-based on a grid). Colliders,physics.world.shutdown()call, and the hand-rolledshutdown/destroylifecycle overrides are gone. - Unused
import game from '../main.js'in the oldMainScene. - Hardcoded
totalLevels: 3and 3-elementlevelCompletedarray in the game registry — replaced with dynamic lookup viaprogressStore.
Fixed
- Scene restart no longer leaves dangling event listeners (Phaser handles this itself; the previous manual
removeAllListenerswas both redundant and fragile). - Level select now scales to 100 puzzles via pagination instead of a single-row layout.