351251d652
feat(quantik-game): фаза 1 — оболочка игры + физ-уровень + прогресс (MVP) Страница /quantik монтирует уровень-спеку в SimEngine (игровой режим: HUD из Ф0 + слайдеры закона + play/reset), на победу шлёт результат и показывает экран успеха (звёзды/время/попытки, inline SVG). Уровень phys-artillery-1 как данные (levels.js): гравитация + запуск тела из угла/скорости, портал, бонус-звезда. Бэкенд: миграция 076 game_progress (UNIQUE user+level), /api/game/progress (GET свой / POST upsert best time/stars, attempts++, auth-only, валидация входа), клиент LS.gameProgress*, пункт сайдбара. game.test.js 13/13; npm test 251 pass/8 baseline; lint:routes 0. Уровень проверен на реальном интеграторе (311 выигрышных комбо, 31 на 3★). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
7.9 KiB
7.9 KiB
Feature Context: Квантик — Законы Мира
Current State
- Ветка
feature/quantik-gameответвлена отfeature/sim-builder(движок P1–P3 там, не в master). - При ответвлении унаследован чужой uncommitted WIP sim-builder:
frontend/js/sim-builder.js,frontend/sim-builder.html,.claude/settings.json+ множество untrackedtmp_*/мусорных файлов. ⛔ НЕ трогать и НЕ коммитить этот WIP — стейджить только свои файлы поимённо. - Phase 0 реализован (pending review): слой целей в движке
_sim_engine.js(блокgoal, компиляция when/fail/stars через SimExpr, состояние результата, HUD-оверлей, APIonGoal/getResult/resetResult) + серверный гейтvalidateSpecпропускаетgoal/game. Изменены:frontend/js/labs/_sim_engine.js,backend/src/controllers/customSimController.js. Аддитивно: спека безgoalведёт себя ровно как раньше (HUD не создаётся, побед не считается). Смоук 40/40;npm test238 pass / 8 baseline fail; lint:routes 0. - Phase 1 реализован (pending review): сквозной играбельный срез. Страница
/quantik(frontend/quantik.html+frontend/js/game/quantik-game.js) монтирует уровень-спеку черезSimEngine.mount; «игровой режим» = HUD из Ф0 (сам по наличиюgoal) + слайдеры params + play/reset. Уровеньphys-artillery-1— данные вfrontend/js/game/levels.js(window.QuantikLevels): physics-гравитация + body-запуск под углом θ/скоростью v, портал-цель, бонус-звезда. На победуonGoal→LS.gameProgressSubmit+ DOM-оверлей успеха (звёзды/время/попытки). Прогресс: таблицаgame_progress(мигр.076), API/api/game/progress(GET/POST,gameController.js+routes/game.js, смонтировано вserver.jsпосле/api/custom-sims), клиентLS.gameProgressList/Submit. Сайдбар:/quantik(iconrocket) виден всем. Новые:076_game_progress.sql,gameController.js,routes/game.js,quantik.html,js/game/levels.js,js/game/quantik-game.js,tests/game.test.js. Изменены:server.js,js/api.js,js/sidebar.js.npm test251 pass / 8 baseline fail (game.test.js 13/13); lint:routes 0; миграция применяется чисто.
Key Architecture Decisions
- «Атом» = блок
goalв спеке (булево SimExpr). Любой уровень = спека SimForge +goal. Движок вычисляетgoal.whenкаждый кадр; победа → result + callback. Нетgoal→ no-op. - Уровни хранятся в
custom_sims(cat='game'), а не в новой таблице. Реюз авторинга/шаринга/embed. Новые таблицы — только под ПРОГРЕСС игрока и лидерборд (мигр.).- Уточнение Ф1: для MVP уровни — ВСТРОЕННЫЕ ДАННЫЕ в
frontend/js/game/levels.js(window.QuantikLevels, форма{ id, title, subject?, hint?, spec }), а не записиcustom_sims.custom_simscat='game' остаётся целевым хранилищем для авторённых уровней (Ф5); реестр тогда станет асинхронным (загрузка опубликованных + слияние со встроенными той же формы записи).
- Уточнение Ф1: для MVP уровни — ВСТРОЕННЫЕ ДАННЫЕ в
- Герой Квантик: в уровне = engine point с
body+ glow + trail (визуал P2). На карте/в диалогах =PetSprite.render(level, mood, accessories, colorKey, streak, pattern)(DOM SVG). - Управление = чинить закон, а не WASD: игрок крутит
params-слайдеры движка (угол/скорость/ гравитация) или собираетf(x); затем «Запуск» — симуляция проигрывается к цели. - Безопасность: цвета — только в canvas-стоки; текст спеки — escape (
& < >); выражения — только длина на сервере, исполняет безопасный SimExpr на клиенте.
Engine touch-points (Phase 0)
- Спека v1 формат — в шапке
_sim_engine.js. Добавитьgoal/gameСЮДА (документировать). - rAF-цикл
_renderFrame(вычисляет env). Добавить_evalGoal()после построения env. mount()возвращает инстанс — добавитьonGoal,getResult,resetResult.- HUD — DOM-оверлей
_labelLayer/новый слой (как readout-бейджи). Без эмодзи, inline SVG. - Серверный гейт
customSimController.validateSpec(:93) — разрешитьgoal/stars/hint/game.
Cross-Phase Dependencies
- Phase 1+ зависят от
goal/getResult/onGoalиз Phase 0. - Phase 2 (XP/скины) зависит от прогресса Phase 1.
- Phase 4 (туннелирование) зависит от флешкарт-SR API.
- Phase 5 (авторинг) трогает sim-builder — к этому моменту чужой P4-WIP должен быть смержен в sim-builder; свериться перед стартом фазы (возможен мерж base-ветки).
- Phase 6 (живая гонка) зависит от моста
sim_state(Ф7 sim-builder) — он на base-ветке.
Temporary Workarounds
(пока нет)
Phase 0 — API/гочи (для следующих фаз)
- Движковое API цели:
inst.onGoal(cb)(1 раз при победе, cb получаетgetResult()),inst.getResult()→{won,failed,timeMs,attempts,stars:{got,total}}(без goal →null),inst.resetResult()(сброс результата, НЕ считается попыткой).inst.reset()= полный перезапуск уровня +attempts++(пользовательская попытка; первый авто-reset при mount НЕ считается). - HUD появляется автоматически при наличии
goalв спеке (отдельного флага «game mode» нет). timeMs= мировое времяtот старта (max(1, round(t*1000))), детерминизм; не wallclock.- Env цели = весь env кадра + единственный доп.идентификатор
tries(= attempts). Других не вводить. - Серверный
validateSpecпринимаетgoal{when,title,hint,hold,fail,stars≤3}иgame{...}(резерв Ф1/5); выражения не исполняются (только длина ≤500), текст escape+обрезка. - Победа делает
pause()в кадре; следующий queued-rAF выходит рано →onGoalне задвоится.
Open Questions / Notes
- Категория
cat='game'— проверить списокCATSв customSimController.js, расширить при необходимости. - Ассеты: разрешены CC0/открытые из интернета (выбор пользователя) — фиксировать источник+лицензию в коммите/доке; визуальная база остаётся in-house (PetSprite/canvas/FLUX).
- Маршрут страницы игры: clean URL
/quantik(паттерн/sim-builder,/lab).