| 2026-09-06 |
Движок: playSpec — спек-синтез звука по описанию (работа E1)
...
SoundSpec (kind hit/chime/scrape/hum + параметры) детерминированно
компилируется renderSpec в сэмплы; AudioManager.playSpec кэширует
буфер по ключу. Путь «звук по запросу» для ИИ-агента без слуха.
Типы synth.mjs — декларацией рядом (synth.d.mts): TS резолвит
specifier к реальному файлу и игнорирует ambient declare module.
План работ E/F/G (спек-синтез, хвосты аудио-инфраструктуры, музыка)
— в docs/plan.md; доки движка обновлены в том же коммите.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Движок: лок кадров (maxFps) и FPS-счётчик по F3
...
GameLoop: опция maxFps — срезанные rAF-кадры не делают ни шагов, ни рендера,
но время копится в аккумулятор (шаги идут пачкой на отрисованном кадре).
Engine: опция maxFps, FpsMeter — дебаг-плашка FPS в углу (среднее за ~0.5 с),
скрыта по умолчанию, переключается по F3 (движок слушает сам, preventDefault
против поиска Firefox; в игре F3 уже занята дебаг-оверлеем сцены — toggl'ятся
вместе). Игра: maxFps 30. Доки core.md/getting-started.md обновлены.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Движок: playBuffer/createBuffer (sfx из памяти); игра — вариативные шаги
...
D2 работы D. AudioManager: общий запуск голоса вынесен в startSfx,
playBuffer(key, buffer, opts) играет буфер из памяти в шину sfx,
createBuffer(Float32Array, rate=22050) строит AudioBuffer (null до unlock).
Чистые примитивы синтеза вынесены в @rpg/engine/tools/synth.mjs (без
node-импортов — wav.mjs тянет node:fs и в браузере не соберётся); wav.mjs
реэкспортирует их для тулз, WAV-файлы побайтно не изменились.
Игра: systems/StepVariants.ts — 3 процедурных варианта шага на поверхность
(сиды 253–256, полосы как в gen.mjs), AudioSystem.playStep(surface) вместо
ключа+джиттера rate, LocationScene отдаёт поверхность. До unlock — файловый
шаг. Гвард: @rpg/engine/tools/* — публичное API. Доки и план обновлены.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Движок: onPlayed для лупов, onEnded, duration(key); игра без ручного лога амбиента
...
- onPlayed зовётся и на стартах лупов (нормализованные опции) — DEV-лог игры
собирается целиком шпионом, ручной push в Game.playAmbience удалён
- onEnded(key): естественный конец sfx; заглушенные голосом (stop/вор/restart)
событие не поднимают
- duration(key): длительность декодированного буфера (null до preload)
- Тесты: +5 в AudioManager.test.ts (440 всего); доки в том же коммите
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Движок: SfxHandle из play(), опция restart, лимит полифонии maxVoices
...
- play() возвращает SfxHandle | null: setVolume/setPan/setRate в полёте + stop;
после stop и естественного конца хендл no-op (учёт голосов через onended)
- restart: true — прежние экземпляры ключа глушатся коротким фейдом
- maxVoices (3-й аргумент конструктора, дефолт 24): при переполнении
воруется самый тихий играющий голос
- Тесты: 6 новых в AudioManager.test.ts (436 всего); доки assets-audio-save.md,
practices.md — в том же коммите
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Игра: AudioSystem — позиционный звук мира, бой на событийной шине
...
- systems/AudioSystem.ts: playAt (затухание 1.5 степени + pan по экранному
смещению от слушателя), playStep (джиттер rate), attach (подписки combat:*),
setLayer (локальный амбиент, тик-фейд через новый MusicHandle.setVolume)
- CombatWorld освобождён от deps.audio: 5 play-вызовов -> события
(новое combat:spit {pos}, combat:awake дополнен pos) — симуляция снова чистая
- combat:playerHit -> sfx/hurt подпиской; sink интерактивов через playAt
- MusicHandle.setVolume в движке (cancel+setValueAtTime — без борьбы с ramp)
- 11 тестов AudioSystem; agent:check зелёный
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Движок: 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>
|
Батч 7: декор-слой (микро-кусты, камни, проплешины)
...
- engine: DecorData + TileMapData.decor; decorLayer между землёй и объектами;
addDecor (возвращает спрайт, один на тайл, повторный заменяет) / clearDecor;
setTile декор не трогает
- engine: MapFileV1.decor + validateDecor (границы, целые, dx/dy — числа)
- game: DECOR-реестр (tuft/stone/bald, id 15-17), buildDecor на createRng(seed+7919)
(~10% наземных тайлов, только GRASS/ASH, смещение не по сетке);
mulberry32 заменён на движковый createRng
- art: decor_tuft/stone/bald 16×16 (рисунок в ромб 16×8, палитра G/P)
- фикс fresh-теста: Math.round -> -0 теряется в JSON, нормализация +0
- тесты: порядок слоёв, addDecor/clearDecor, границы, round-trip + валидация decor
- доки: maps.md (раздел «Декор»), art-style.md, practices.md (ситуация
«меняю генераторы арта или карт», грабля -0)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Батч 6: варианты текстур тайлов (микс по хэшу координат)
...
- engine: hashTile(x,y,seed) — чистый хэш координат (math/rng.ts)
- engine: TileMapData.variants + setTileVariants + публичный variantOf;
анимация сильнее вариантов (setTileAnimation снимает их)
- engine: MapFileV1.variants (строковые ключи) + validateVariants в parseMap
- game: GRASS_V1/V2, ASH_V1, PATH_V1 (id 11-14), GROUND_VARIANTS в трёх
генераторах карт, новые текстуры в ASSET_KEYS и tileTextures()
- art: grass_2/grass_3/path_2/ash_2 (32×16, та же палитра, другой seed)
- тесты: hashTile (детерминизм/разброс), выбор варианта стабилен при setTile,
анимация vs варианты, round-trip + валидация variants
- доки: maps.md (раздел «Варианты текстур»), art-style.md, art-pipeline.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

Движковые коллизии: круг поверх сетки + 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>
|
Реестр размеров спрайтов: sizes.mjs + AssetLoader.frameSize
...
Единый источник номиналов для тулз (gen.mjs, lint-art.mjs), рантайм
читает размер кадра из атласного JSON. Захардкоженные 16×24/16×16
заменены ссылками на реестр; VIRTUAL-дубли 480/270 в сценах — на
Game.VIRTUAL_W/H; маркер NPC считается от реальной высоты кадра.
- tools/pixelart/sizes.mjs: SIZES (tile/tall/prop/char/fauna/clump/decor)
+ SLOTS для линтера; тест sizes.test.ts
- gen.mjs, lint-art.mjs: импорт из реестра вместо локальных констант
- AssetLoader.frameSize(key, frameName?) — sourceSize из атласного JSON
- IsoLayout как параметр игры — отложено (docs/plan.md)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

Анимация 4/4: шоукейс в игре — все акторы на SpriteAnimator, статика оживает
...
Унификация акторов на движковые аниматоры (три ручных таймера кадров больше не дублируются):
- PlayerController: SpriteAnimator с клипами walk_*/idle_* — ушёл «застыл на произвольном кадре ходьбы»;
- CombatViews: SpriteAnimator (спящим pause), hit/death-бёрсты — oneShot через engine.fx
(закрыт баг «частицы стоят на месте»), новые опции drag/spin/scaleOverLife/colors;
- FaunaSystem: SpriteAnimator (на ходу walk, в покое стоп-кадр).
Оживление статики в LocationScene (всё тикается engine.fx, без ручного update):
- вода — setTileAnimation (2 кадра, один таймлайн на все клетки);
- мигание героя — SpriteMotion blink с живым duty (вместо ручного alpha);
- NPC idle — кадры npcs_sheet (randomPhase по тайлу), атлас добавлен в BootScene,
отдельные PNG NPC из списка ассетов убраны;
- искры pickup-объектов — SpriteMotion pulse;
- тёплые мотыльки — эмиттер blend:'add' + wobble + fadeIn;
- кадры героя/фауны — через assets.animation() (анимации атласов из батча 3).
Ограничение: sway для цветов/башни не вводился — это тайлы карты (спрайты
внутри IsometricTileMap), SpriteMotion на них неприменим.
Движок, попутные фиксы:
- Updatables: разрушенные записи не тикаются (Pixi обнуляет transform —
тик разрушенного SpriteMotion ронял весь тик и молча убивал игру после
перехода между локациями) + тесты;
- Engine.stepTicks: setManual(false)/resetTiming в finally — исключение в шаге
больше не оставляет цикл в ручном режиме навсегда;
- EmitterOptions.velocity опционален (в oneShot с radialSpeed не нужен);
- SpriteAnimator/SpriteMotion: геттер destroyed — самозачистка из engine.fx.
Доки: core.md (fx), anim.md (самозачистка), render.md (velocity), agent.md +
practices.md (грабля «мост глотает throw шага» и приём диагностики).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

feat(engine): батч 2 — оживители статики + партиклы v2 + тайл-анимации
...
- anim/motion.ts: чистая sampleMotion — bob/sway/pulse/blink, композиция,
округление bob до целого px; anim/SpriteMotion.ts — Pixi-адаптер
(база снимается в конструкторе, живые params, detach, seed→фаза)
- render/particleSim.ts (breaking): stepParticle → ParticleVisual
(alpha/scale/rotation/tint); drag, wobble, fadeIn/fadeOut-хвост,
scaleOverLife, colorOverLife; mergeEmitterOptions — чистое слияние
(burst больше не мутирует опции); fix: rng.int инклюзивен — выход
за границы colors
- render/Particles.ts: текстурные частицы, colors/colorOverLife, spin,
size-диапазон, max-лимит + пул спрайтов, blend 'add', setOptions,
onFinish у oneShot
- IsoDepthLayer.addFx(view, tx, ty, bias=0.5) — эффекты поверх актёра
- IsometricTileMap.setTileAnimation(id, frames, fps) + update(dt) —
один общий таймлайн на все клетки id (вода)
- engine.fx (батч 1) — рецепт авто-тика в доке вместо ручного update
- доки: render.md (частицы, addFx), anim.md (SpriteMotion, тайлы),
recipes.md (ходьба/атмосфера/статика/вода/удар), maps.md
- тесты: motion (9), particleSim переписан под v2 (итого 360)
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>
|

Крупные объекты: props с footprint в движке, слоты арта, проба дома кодом
...
Работа C из docs/plan.md — подготовка к зданиям акта 2.
Движок:
- TileMapData.props: крупный объект с footprint w×h от СЗ-угла — коллизия
по всему прямоугольнику, земля под ним (ground), спрайт якорем низ-центр
footprint'а; без текстуры — колонна-плейсхолдер (общий с tall хелпер).
- IsoDepthLayer.addRect: глубина по диагонали юго-восточного угла
footprint'а — герой у южной стены перекрывается домом, перед южным
углом рисуется поверх.
- mapFormat: props в файловом формате + валидация (целые w/h ≥ 1,
footprint внутри карты, высота в юнитах).
- LocationScene вставляет map.propViews в общий depth-слой.
- Доки движка: maps.md (секция props), render.md (addRect).
Арт (проба C2):
- Арт-библия: слоты крупных спрайтов (дом 2×2 — 64×80, 3×3 — 96×96,
4×4 — 128×112); плотность пикселя как у тайлов.
- gen.mjs: tiles/house_big.png (64×80) — композит: модули щитов + крыша
из шпал + козырёк + окна. Сравнение с AI-апскейлом 24→48 —
tools/aiart/probe-c2.png: код-композит заметно чище, апскейл — мыло с
чужой плотностью пикселя. Вывод: крупные объекты — код-композит;
апскейл только как болванка (см. docs/plan.md, работа C).
Тесты: 318 (+9: footprint, depth-rect, валидация пропов).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Фабрика тестовых фикстур + fail-fast предикатов waitFor
...
- testing/ (только для *.test.ts, в бандл не попадает):
combatWorld.ts (fakeMap/fakeWorld/run/far), gameState.ts (fakeState),
maps.ts (mapWithWall). EnemyAI/los/Interactables тесты переведены —
бойлерплейт фейковых карт/стейтов выведен из трёх файлов.
- GameAgent.waitFor: top-level обращения s.<ключ> сверяются с
AGENT_SNAPSHOT_KEYS до компиляции предиката; неизвестный ключ ->
{ ok: false, error: 'неизвестный ключ s.X', ticks: 0 } — опечатка
больше не тихий false на весь таймаут. predKeys — чистая функция,
тестируется в snapshot.test.ts.
- Список ключей: ENGINE_SNAPSHOT_KEYS (движок) + сценические + слой игры;
анти-дрейф тесты держат список согласованным со слоями снапшота.
Проверки: typecheck, 307 тестов (+6), agent check 45/45 (ни один чек
валидация не отторгла), smoke-act1. Доки: agent.md (поведение waitFor),
practices.md (проверка сценариев).
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>
root
committed
2 days ago
|
сейвы v2 + предметы + инвентарь
...
- движок: Inventory — контейнер Map<id, count> (add/remove/count/has/all,
onChange), inventoryFromData; тесты;
- Game.inventory: сумка героя, сброс в новой игре;
- SaveData v2: поле version + items, normalizeSave дополняет сейвы v1;
- data/items.ts: реестр предметов (cloth, bellflower, salt, water_flask);
- сбор цветка кладёт bellflower в сумку; полотно выдаётся предметом
после диалога Милы (флаг got_cloth остаётся меткой);
- InventoryScene: строки сумки из инвентаря (имя + ×N);
- тесты: 192/192.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
Фаза 4: TallSpec.height в мировых юнитах
...
- плейсхолдер-колонна: h = tall.height * iso.tileW (вместо px);
- удалён устаревший map.screenSize (остался worldBounds в юнитах);
- data/map.ts: высота дерева 1.5 юнита (те же 48 px на экране);
- .map-файлы перегенерированы (diff — только height: 48 -> 1.5);
- parseMap отвергает tall.height > 16 как высоту в px (защита от
протухших карт-файлов);
- тесты: 186/186.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
камера: позиция и границы в мировых юнитах
...
- Camera.x/y и bounds в юнитах (1 юнит = 1 тайл); клэмп по экранному
bbox мирового прямоугольника; deadZone -> deadZonePx (окно на экране)
- IsometricTileMap.worldBounds; LocationScene использует его
- camera.test.ts переписан в юнитах (проверка проекций)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
движок: мост мировых юнитов (worldToScreen, unitsToPx, метрика проекции)
...
- math/iso.ts: проекция мир↔экран (float, без округления), линейка
скаляров (tileW px на юнит), метрика проекции (worldLen/worldNorm/
worldDist/moveTowardsW), тайлы (tileToWorld/worldToTile), bbox
прямоугольника (worldRectToScreen)
- shapes.ts: inCircleW/inConeW — метризованные варианты
- тесты: world.test.ts (18) + эквивалентность W-вариантов
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
камера: dead zone (окно следования) + дебаг-просмотр спрайта
...
- Camera.deadZone: цель двигает камеру только у границ окна,
внутри окна камера неподвижна; Camera.snap — мгновенная постановка
минуя окно (спавн/респаун)
- SpriteDebugView: текущий кадр героя с целым zoom (nearest) и сеткой
по границам пикселей (KeyP в локации)
- PlayerController: followPath для готовых путей, currentTexture
- фикс сборки hero_sheet: Buffer.set принимает offset в байтах —
кадры затирали друг друга, атлас был перемешанным мусором
(отсюда «сжатый» герой)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
движок: дистанция взаимодействия + findPathToNeighbor
...
- pathfinding.findPathToNeighbor(grid, start, goal): путь к ближайшей
проходимой клетке рядом с goal (8-соседство) — цель может быть занята
NPC/объектом или непроходима; тесты (3 новых)
- PlayerController.followPath: пойти по готовому пути тайлов
- LocationScene: клик по NPC/цветку срабатывает только в радиусе 44px;
издалека герой подходит к краю тайла и взаимодействие срабатывает
на месте; исключение — force у requestTalk (сюжетные триггеры)
- доки: maps.md (findPathToNeighbor), demo.md (новое в движке)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
рендер: резкий UI при пиксельном мире + тайлы без обводки
...
- Renderer: бэкинг-стор канваса в пикселях устройства (scale × dpr) —
UI и текст рендерятся 1:1 с экраном, без «мыльного» апскейла на HiDPI;
CSS-размер канваса не изменился (виртуальное × целое)
- PixelText: setPixelTextResolution — глифы растеризуются с resolution
канваса (синхронизирует Renderer при смене масштаба)
- AssetLoader: текстуры мира (и кадры атласов) сэмплируются nearest —
пиксель-арт остаётся чётким квадратным
- тайлы без обводки граней (fillDiamond без light/dark линий):
смежные тайлы сливаются в поля, сетка больше не «шумит»
- доки: render.md (двухслойный пайплайн), ui-and-dialogue.md (resolution
текста), CLAUDE.md (правило №2)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
полировка: читаемость шрифтов (кегль VT323 ≥ 10) + перерисовка героя
...
- DialogueBox: минимум 10px, панель расширена (8–9px у VT323 нечитаемы);
проба tools/font-probe.mjs подтвердила на честном конвейере игры
- подсказка локации укорочена и опущена под сердечки (налезала на HUD)
- кегли в сценах: меню/настройки/сейвы/сумка/boot 9→10, тосты 11
- герой перерисован (все направления): крупнее лицо, два симметричных
глаза, плечи/пояс/сапоги — без «кляксы», читается как человек;
размер 16×24, имена кадров и якорь не тронуты
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
игра: квест «Три цветка» — сбор, журнал, сумка, сдача и крючок акта 1
...
- движок: IsometricTileMap.setTile — изменение тайла с перерисовкой ячейки (+тест);
InputManager: одна клавиша маппится на несколько действий (Space = advance+attack)
- data/quests.ts: журнал квестов и предметы из флагов/варов GameState
- сбор лунных колокольчиков кликом на прудах (тайл зеленеет, прогресс flowers)
- сдача квеста Ирвину (elder_hand_in) — посадка цветов у тропы, крючок «Машина дышит»
- повторные реплики Милы (trader_repeat/trader_after)
- InventoryScene: сумка и журнал на Panel (клавиша I / геймпад Y)
- tools/smoke-quest.mjs: смоук диалога и сумки
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
игра: звук и настройки — WAV-генератор, AudioManager, SettingsScene
...
- tools/audio/gen.mjs: генератор WAV из кода (моно 22050, 16-бит, без зависимостей):
bell_hit, bell_low, ash_hiss, ash_die, spit, hurt, step, ui_click, chime
+ зацикленные амбиенты meadows/ponds (кроссфейд краёв лупа)
- engine: AudioManager.preload — декодирование до первого play
- Game.audio + связка settings.onChange -> setBusVolume
- unlock аудио на первом жесте (main.ts), preload в BootScene
- SettingsScene (Panel+MenuList): громкости master/music/sfx, вход из главного меню
- музыка локаций через Game.playMusic (защита от перезапуска того же трека)
- sfx: шаги героя (PlayerController.onStep), колокольчик реплик (DialogueSystem.onLineShown)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
engine: примитивы боя — Shake+Camera, shapes, Cooldown, TintFlash, particleSim, burst/oneShot, justReleased, transitionAny
...
- render/shake.ts + Camera.addShake/clearShake/update (Engine.tick тикает камеру)
- math/shapes.ts: inCircle, inCone, angleBetween, nearest
- core/Cooldown.ts: кулдаун на фиксированном шаге
- anim/flash.ts (TintFlash, lerpColor) + render/spriteFx.ts (SpriteFlash)
- render/particleSim.ts: чистая интеграция частиц; Particles.burst/oneShot + radialSpeed
- InputManager: isActionJustReleased, wasKeyReleased, pointer.downTicks
- StateMachine.transitionAny — переход из любого состояния
- Тесты: shapes, Cooldown, shake, flash, particleSim, InputManager (фейковый canvas), transitionAny (130 всего)
- docs/engine: core.md, render.md, input.md обновлены
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|