Files
Learn_System/plans/quantik-game/CONTEXT.md
T
Maxim Dolgolyov 0f3e12426a @
feat(quantik-game): фаза 2 — карта-созвездие + мир + XP/скины (MVP-мир)

Одиночный уровень → играбельный мир: карта-созвездие из 6 физ-уровней
(2 главы, нарастающая сложность), разблокировка по звёздам, клиентский
XP/уровень игрока, пикер из 8 скинов (тинт героя+нарратора), нарратор
PetSprite на интро/победе (mood по звёздам). Навигация карта→интро→игра→
успех→карта/дальше; кнопка «Дальше» пересчитывает nextPlayable после
дозагрузки прогресса (фикс stale-hasNext). Логика прогресса — чистый
модуль progress-logic.js (unlock/XP/группировка). Только фронт, без
бэкенда: XP агрегируется из game_progress (Ф1). Каждый уровень проверен
на реальном движке (выигрываем + обе звезды достижимы); цепочка
разблокировки доказуемо проходима. npm test 251/8 baseline; lint:routes 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-06-13 16:24:31 +03:00

9.7 KiB
Raw Blame History

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 + множество untracked tmp_*/мусорных файлов. НЕ трогать и НЕ коммитить этот WIP — стейджить только свои файлы поимённо.
  • Phase 0 реализован (pending review): слой целей в движке _sim_engine.js (блок goal, компиляция when/fail/stars через SimExpr, состояние результата, HUD-оверлей, API onGoal/getResult/resetResult) + серверный гейт validateSpec пропускает goal/game. Изменены: frontend/js/labs/_sim_engine.js, backend/src/controllers/customSimController.js. Аддитивно: спека без goal ведёт себя ровно как раньше (HUD не создаётся, побед не считается). Смоук 40/40; npm test 238 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, портал-цель, бонус-звезда. На победу onGoalLS.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 (icon rocket) виден всем. Новые: 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 test 251 pass / 8 baseline fail (game.test.js 13/13); lint:routes 0; миграция применяется чисто.
  • Phase 2 реализован (pending review): одиночный уровень превращён в играбельный мир. Карта-созвездие (frontend/js/game/map.js, window.QuantikMap) на звёздном фоне: 6 физ-уровней в 2 главах (Кинематика 1–3, Динамика 4–6), узлы-«звёзды» со статусом (locked/available/completed+ звёзды), линии-связи, поэтапное появление. Шапка: нарратор-Квантик (PetSprite), XP-бар + «уровень Квантика», всего звёзд, скин-пикер (8 скинов, часть за XP/звёзды). Контент уровней расширен в levels.js (метаданные chapter/order/par_ms/unlockStars, по 2 звезды: кристалл + норматив времени). Разблокировка/XP/группировка — ЧИСТЫЕ функции в новом frontend/js/game/progress-logic.js (window.QuantikProgress), покрыты тестом. Навигация: карта→интро(нарратор)→уровень→успех (нарратор по звёздам)→карта; «Дальше» активирована (nextPlayable); скин тинтует героя+нарратора (localStorage quantik-skin). Backend НЕ тронут — XP клиентская агрегация из game_progress. Новые: js/game/map.js, js/game/progress-logic.js. Изменены: quantik.html, js/game/levels.js, js/game/quantik-game.js. node --check все OK; смоуки (логика 16/16, рендер 7/7, winnability 6/6 на реальном движке) зелёные и удалены; npm test 259/251 pass / 8 baseline fail (без изменений); 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_sims cat='game' остаётся целевым хранилищем для авторённых уровней (Ф5); реестр тогда станет асинхронным (загрузка опубликованных + слияние со встроенными той же формы записи).
  • Герой Квантик: в уровне = 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).