| 2026-09-07 |

refactor(engine): глубокий рефакторинг К2 — расшивка аудио, FadeState, контракт fx, Engine.destroy
...
Расшивка переростков:
- AudioManager (479→279) → AudioManager (фасад) + Voices (полифония sfx,
pan в полёте в шине голоса) + Loops (слоты музыки/амбиента, кроссфейд)
+ decode.ts (BufferCache с in-flight дедупом) + types.ts;
load() → register()
- IsometricTileMap: проходимость делегирует новому StaticGrid
(map/collision.ts) — единый источник blocked/пропы/тени; headless-потребители
берут через gridOf(data), setTile виден сразу
- core/fade.ts (FadeState): вместо ручных fadeLeft/fadeTotal в Lighting
(ambient+виньетка) и SceneManager; повторный to() в середине фейда
стартует от текущего значения — без прыжка
Контракт fx-эффектов: cancel() = остановить + вернуть базовое + погасить
свою вьюху (FxFade без keep теперь гасит, FxTrail получил cancel,
SpriteFlash.cancel через TintFlash.finish); конец жизни — destroyed
везде. FxLayer: один реестр тикающихся (items), flashes — только индекс
перезапуска.
Прочее:
- Engine.destroy() — полная зачистка (exit сцены, fx/tweens/events,
ввод, FPS-метр, app.destroy) для HMR; stop() — только цикл
- FpsMeter считает всегда, отдаёт геттером fps; DebugOverlay принимает
FpsMeter и перерисовывает Text не чаще 0,5 с
- Lighting: кэши текстур на инстансе (модульный переживал destroy
рендерера), чинен двойной destroy darkFree/darkLayer
- InputManager: DOM-обработчики и инъекции идут через общие примитивы
press/release (клавиши, указатель)
- SpriteAnimator: xorshift → math/rng.createRng (единый ГПСЧ)
- Мёртвый код: FrameAnimation (файл+экспорт+тест), vec2(), pxToUnits,
screenToIsoExact, pushOutOfWalls
Тесты: +fade, +SceneManager (стек/фазы/глотание), +EventBus, +Engine
(stepTicks, мок pixi.js), +SpriteAnimator, +computeScale. Доки движка
обновлены в том же коммите (core.md: FadeState/Engine.destroy;
render.md: контракт fx, кэш Lighting; anim.md/maps.md/README.md — без
FrameAnimation; practices.md: тест ядра без WebGL, поле-метод).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
5 hours ago
|
engine(inventory): лимиты, богатые события, генерик id
...
- InventoryOptions { maxSlots, maxPerStack }: add обрезает и возвращает,
сколько влезло; spaceFor/size/slotLimit/stackLimit; load клампит.
- InventoryChange { kind, id, count, after } вместо () => void
(подписчиков в игре нет — миграции не нужны).
- Inventory<TId extends string> — задел типобезопасности; мёртвый
InventoryState удалён; формат serialize/load не меняется (сейвы v3).
- Тесты 6 → 11; новый док docs/engine/inventory.md, карта модулей
README.md, llms.txt.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|
| 2026-09-06 |
Движок: AudioManager v2 — шина ambience, playLoop, опции pan/rate
...
- 4-я шина ambience → master (лупы областей и локальные слои отдельно от музыки)
- PlayOptions {volume, rate, pan}: rate 0.5..2, |pan|<0.01 — без StereoPanner;
число в play() — сахар для {volume} (30+ старых вызовов не мигрируем)
- playLoop — луп без слота (база локальных амбиент-слоёв); playMusic/playAmbience —
независимые слоты с кроссфейдом, негодный ключ не глушит текущий трек
- ctxFactory инъекцией (фейк в тестах), шпионский хук onPlayed
- Settings.ambience (дефолт 1, старые настройки накрываются спредом)
- 10 тестов на фейковом AudioContext; доки assets-audio-save.md + README
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|

Движковые коллизии: круг поверх сетки + LOS по пропам
...
Новый чистый модуль map/collision.ts в движке: gridOf (Grid из
TileMapData с footprint пропов), точная проверка круга circleFits
(ближайшая точка квадрата Blocked-тайла — ловит угловой прокол по
диагонали), moveCircle со скольжением по осям, pushOutOfWalls для
телепортов, separateCircles для будущего расталкивания тел.
Дедупликация четырёх копий worldToTile+isWalkable: движение героя
(moveFree), шаги врагов, фауна и валидатор контента теперь на одних
функциях. IsometricTileMap.isPropBlocked публичен.
Бой против стен: конус удара требует прямой видимости (hasLineOfSight
по tall + пропам), снаряды гасятся о стены и дома (вода прозрачна —
плевок летит над прудом). Отброс героя — только если тело помещается
(circleFits): прищёлкивание к центру тайла после отброса меняло
динамику погонь у прудов и валило пробу interact-world.
14 юнит-тестов на коллизии (скольжение, угловой прокол, совместимость
с A*-маршрутом, push-out, separateCircles). Доки: maps.md (раздел
«Коллизии»), README.md, llms.txt.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
SceneRegistry: реестр объектов сцены с индексом по тайлам
...
Жанронезависимый примитив «что-то стоит на карте»: позиция в юнитах,
радиус тела, footprint в тайлах, непрозрачная ссылка на контент игры.
Запросы at/atWorld/near/byKind без перебора сцены; дубликат id — throw.
Фундамент для унификации NPC/интерактивов/врагов и телесных коллизий.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
engine: ядро анимации — SpriteAnimator, клипы, реестр тика engine.fx
...
- anim/clip.ts: чистый степпер клипов (loop/once/pingpong, время в
шагах, speedScale, dt>периода проматывает).
- anim/SpriteAnimator.ts: именованные клипы, play/pause/showStep,
onFrame/onFinish, randomPhase (seed), текстура только при смене шага.
- anim/FrameAnimation.ts → @deprecated-обёртка, API байт-в-байт.
- core/Updatables.ts + Engine.fx: движок тикает эффекты сам (между
tween-ами и сценами), самозачистка по destroyed; clear() в stop().
- Тесты: clip (7), Updatables (5), FrameAnimation (4) — пробел покрытия
закрыт (было 0). Доки: новый docs/engine/anim.md, core.md, README.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Архитектура: гвард границы движок/игра + перенос тулз в apps/game/tools
...
- Гвард границы (apps/game/tools/guards/boundary.mjs, npm run guard):
движок не импортирует игру и не выходит из пакета, игра импортирует
движок только через @rpg/engine и @rpg/engine/assets/*. Чистое ядро
покрыто тестами (8 кейсов); проба guard:boundary в agent check.
- tools/ -> apps/game/tools/ (git mv, история сохранена): правка
корне-относительных путей в генераторах и CLI, ROOT-константы
'../../..', npm-скрипты обновлены.
- Доки: CLAUDE.md, llms.txt, docs/engine/*, README — новые пути,
практика «меняю границу движок/игра» и грабля про ROOT тулз.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
| 2026-09-05 |

Батч 0: агентный набор инструментов (мост, валидация, CLI, доки)
...
Движок (packages/engine/src/agent/):
- types.ts: SceneAgent/AgentHost/Invariant/SnapshotLayer — каркас жанронезависим
- EngineAgent: снапшот+инварианты, step/waitFor, атомарные tapVirtual/press/key
- invariants.ts: checkFinite/checkRange/checkBounds/checkWalkable
- Engine.stepTick/stepTicks/tickCount; GameLoop.setManual/resetTiming
- InputManager.inject*: инъекция через те же структуры ввода
- DialogueRunner: nodeId/choices/waitingForChoice раскрыты для снапшота
Игра (apps/game):
- agent/GameAgent.ts: window.__agent (DEV): snapshot/step/waitFor/walkTo/runDialogue
- agent/snapshot.ts: чистые слои hero/enemies/npcs/dialogue/game
- data/validate.ts: runtime-валидация контента → Invariant[] (нашла 4 врага на воде)
- сцены реализуют SceneAgent: whitelist-команды, lastToast в снапшоте
Инструменты и доки:
- tools/agent-lib.mjs (openGame/AgentClient/Checks), tools/agent.mjs (CLI check/run/snapshot/screenshot/dev)
- tools/checks/agent-invariants.mjs; смоуки переписаны на мост; maps:fresh в gen.test.ts
- docs/llms.txt, docs/engine/agent.md, docs/engine/practices.md (живой документ)
- CLAUDE.md, docs/engine/README.md, docs/demo.md обновлены
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Батч 6: CutsceneRunner + кат-сцена сдачи квеста
...
- Движок: packages/engine/src/cutscene/CutsceneRunner.ts — view-агностичный
раннер шагов (call/cameraMove/burst/wait/setFlag); шаг с seconds: 0 —
параллельный; 5 тестов.
- Демо: кат-сцена сдачи «Трёх цветков» — посадка → камера к башне →
удар колокола (звон, shake, кольцо) → зелень → финальный тост.
- Смоук tools/smoke-act1.mjs: полный прогон акта 1 от «Новой игры»
до кат-сцены (сцелиться в тайл триггера, диалог через Space).
- Доки: docs/engine/cutscene.md, README (карта + структура),
docs/demo.md (матрица, дорожная карта — следующий срез: телепортация,
интерьеры, взаимодействие, ИИ врагов), CLAUDE.md (грабля клика вне экрана).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Фаза 5: документация и смоуки мировых юнитов
...
- docs/engine/render.md: преамбула «мир в юнитах, экран в px», Camera
в юнитах, deadZonePx, правило display-слоя для частиц;
- docs/engine/maps.md: секция мировых юнитов (worldToScreen/screenToWorld/
unitsToPx), TallSpec.height в юнитах, worldBounds вместо screenSize;
- docs/engine/recipes.md: скелет локации и click-to-move в юнитах;
- docs/engine/README.md: принцип №3 «мир в юнитах, UI в пикселях»;
- docs/demo.md: боевая модель в юнитах;
- CLAUDE.md: правило №4 (две линейки), грабли (ромб/указатель/facing);
- смоуки и пробы пройдены (smoke, smoke-ponds, smoke-quest, walk-probe,
cam-probe, far-test) — рендер, переходы, квест и камера в норме.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
Миграция игры на новые API движка + документация docs/engine
...
Игра:
- диалоги переписаны на графы DialogueRunner + GameState (тексты сохранены)
- меню на MenuList, шрифт VT323 через PixelText во всех сценах
- герой из атласа hero_sheet (gen.mjs), акторы в IsoDepthLayer
- пепел через ParticleEmitter, fade-переходы сцен, сейв с GameState
- Vite: publicDir: 'assets', алиас regex, шрифт через ?url-импорт
Документация: docs/engine/ — 10 файлов (архитектура, подсистемы, рецепты).
CLAUDE.md и README.md обновлены под новые модули и грабли.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|