| 2026-09-07 |
engine(save): метаданные слотов сейва
...
- SaveSlotMeta { title, savedAt, version, extras } в параллельном ключе
meta:<slot> — формат сейвов не меняется, старые остаются читаемыми
(slotMeta -> null -> игра падает на полный load).
- save(slot, data, meta?), slotMeta(), list(); delete чистит оба ключа;
listSlots() не включает meta:* (главный подводный камень).
- Тесты 3 -> 6; доки assets-audio-save.md (мета + оси версий).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
12 hours ago
|
Аудио: стерео-музыка, динамические темы (бой/настороженность), room tone интерьеров
...
- Движок: renderMusicStereo (interleaved L,R, equal-power pan треков,
нормализация по общему пику каналов), createBuffer(channels 1|2);
моно renderMusic бит-в-бит прежним сэмплам
- Игра: темы боя и tension-стем в data/music.ts; threat-тик
LocationScene.updateMusic — chase → тема боя, wary → тихий стем
(setVolume с флагом stemPending против шторма перезапусков)
- Room tone интерьеров: ROOM_TONES (hum-спеки, шина ambience),
запуск в enter, стоп в exit, validate-тест ключей
- checks/music.mjs: инвариант «тема лугов не перезапускается»
(динамические темы/стем — легитимная реакция на врага)
- Доки: assets-audio-save.md (стерео), practices.md (динамическая
музыка, pending-флаг), plan.md (Работа G — сделано)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
| 2026-09-06 |
audio: палитра спеков (tone/wobble/sweep/layers) — все sfx на спек-синтезе (E4)
...
- SoundSpec: kind 'tone' (чистый тон + свип freqTo), параметры w/attack/
fadeTo/wobbleHz|Depth|Base|Phase, доп. голоса layers (SpecVoice с delay);
без модификаторов бит-в-бит прежним формулам
- data/sfxSpecs.ts: 16 спеков — все бывшие файловые sfx, включая шаги
(StepVariants: варианты renderSpec с сидами base+i·10, fallback — базовый
спек); ui_click во всех сценах через playSfx
- gen.mjs остался только амбиенту; assets/audio/sfx/ удалён; формулы
бывших sfx экспортированы для парити-теста (bit-в-бит / eps 1e-5)
- мост: scene:synthesize принимает kind tone; доки: agent.md,
assets-audio-save.md, practices.md, plan.md (E4 ✅)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
audio: миграция bell_hit/whoosh на спек-синтез (E3), мёртвый door.wav удалён
...
- SoundSpec: флаг swell (огибающая «0 → 1 → 0» у hit/scrape), у chime 4-й
партиал и константная амплитуда клика — формулы совпали с gen.mjs дословно
- data/sfxSpecs.ts: реестр SPEC_SFX + playSfx — единая точка проигрывания
sfx (AudioSystem, useTransition, collectFlower); ключи в AUDIO_KEYS
- gen.mjs: CLI-гвард (WAV при импорте не пишутся), формулы bellHit/whoosh
экспортированы для парити-теста sfxSpecs.test.ts (бит-в-бит равенство)
- доки: plan.md (E1–E3 ✅, F/G ✅), practices.md, assets-audio-save.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Движок: секвенсор renderMusic + playLoopBuffer; игра — тема лугов (работа G)
...
Партитура MusicSpec (bpm, beats, партии-стемы: pluck/bell/pad) чисто
компилируется в луп; playLoopBuffer играет буфер памяти на любой шине.
Тема лугов — правило-базовый генератор в data/music.ts (сид, ля-минорная
пентатоника), компиляция в рантайме — WAV для музыки не нужен; у области
поле theme, у Game — playTheme с guard-ом и кроссфейдом. Проба
checks/music.mjs в agent:check. Секвенция тем (бой) — до боевой темы.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Движок: auto-mute по visibilitychange, bus в PlayOptions, exponential-фейд
...
Свернул таб — ctx.suspend, вернулся — resume (опция pauseOnHide, без
DOM listener не ставится). Разовый sfx можно направить в любую шину
(bus, по умолчанию sfx). Затухания лупов — экспоненциальные (линейный
спад слышен ступенькой); нарастание осталось линейным — экспонента не
определена от нуля. Доки и план (работа F ✅) в том же коммите.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Движок: 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>
|
Движок: 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>
|
Движок: 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>
|
Игра: DEV-лог аудио, агентная проба audio, практики «Добавляю звук»
...
- DEV-шпион window.__gameAudioLog (кольцо 24): sfx через onPlayed, амбиент через playAmbience
- checks/audio.mjs: амбиент запущен один раз, шаги без боя, bell_hit, guard амбиента, кольцо;
зарегистрирована в agent.mjs (8 проб)
- Доки: practices.md — ситуация «добавляю звук»; assets-audio-save.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>
|
Реестр размеров спрайтов: 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>
|

feat(tools): батч 3 — тулзы кадров + animations в атласах
...
- engine/tools/frames.mjs: производные кадры из опорных — shiftFrame,
bobFrame (парение), squashFrame (приседание), swingFrame (nearest-
поворот вокруг опоры), mirrorFrame, deriveCycle (дескрипторы)
- buildAtlas(..., animations) — Record<имя, number[]> → JSON.animations
(формат Pixi); assets.animation() оживает
- gen.mjs: вода двумя кадрами (tiles/water_1/2, блики сдвинуты на 1px),
атласы героя/фауны/сгустков собираются через buildAtlas с animations,
новый chars/npcs_sheet (idle-кадры NPC через bobFrame); сгустки в
ячейке 20×20 теперь по центру (было прижато влево — спрайты врагов
центрируются точнее)
- aiart/atlas.mjs: инлайн-бобинг → squashFrame (вывод идентичен),
animations из frameSets
- игра: ключи воды water_1/water_2 (старый tiles/water удалён)
- ассеты перегенерированы вместе с генераторами (npm run art, art:lint ok)
- доки: art-pipeline.md (frames.mjs, animations), assets-audio-save.md
- тесты: frames (8), buildAtlas animations (2) — итого 369
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
| 2026-09-05 |
Миграция игры на новые 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
|