| 2026-09-07 |

feat(game): вечер после сдачи квеста, виньетка, световые импульсы в бою
...
- ids.ts: флаг FLAGS.evening; граф elder_hand_in.json ставит его узлом accept
(«вернусь до темноты» — контент-driven, валидатор держит флаг упомянутым)
- LightingDef.nightAmbient: GameLighting.update ведёт ночную цель ambient
(guard по последней цели, фейд 6 c); лампа героя — в тёмной области или вечером
- тёмные ауры зон наката: пятно на каждый тайл HazardDef (multiply под светом)
- виньетка: низкий hp (0.3) / накат без полотна (0.35), фейд 0.5 c
- импульсы: combat:hurt → тёплая вспышка в точке врага, резонанс → вспышка
у героя + подъём ambient, урон герою → красная вспышка на весь экран
- LocationScene: maxLights: MAX_LIGHTS (движковый пул больше не теряет
источники), setTileTracked — индекс layerTilePos живой при смене тайлов
- мост: scene:damagePlayer (полный боевой путь), снапшот lighting.vignette,
инвариант lighting-bounded расширен виньеткой 0..1
- доки: agent.md (vignette/scene:damagePlayer), practices.md (ночь = флаг,
импульсы = тот же пул)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
8 hours ago
|
feat(game): контент освещения + сценарий проверки lighting
...
- locations.ts: ambient областей (луга/пруды/Звенец/интерьеры), окна трёх
домов Звенца, очаг дома Ирвина (hearth_low -> hearth_high по флагу квеста),
лампа прилавка лавки, холодный отсвет башни после звонка
- LocationScene: вызов lightView.update(dt) — время/лерп ambient/кадры
к спрайтам (сценарий поймал замороженное мерцание)
- tools/checks/lighting.mjs: 6 шагов (ambient областей, окна, тёмный интерьер,
мерцание с допуском, лампа следует за героем, очаг ярче после сдачи),
регистрация в agent.mjs
- доки: demo.md (матрица), plan.md (задача 10 + точки расширения day/night),
art-style.md (свет — оверлей, цвет из гаммы жизни, интенсивность ≤ 1.1)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
9 hours ago
|
feat(game): интеграция освещения — статика областей, лампа героя, слой снапшота
...
- data/locations.ts: LightSourceDef/LightingDef (ambient + источники at/tiles,
радиус в юнитах, цвет/интенсивность/мерцание, whenFlag/notFlag), поле lighting в AreaDef
- systems/Lighting.ts: GameLighting — сборка активных источников (статика +
runtime add/remove + лампа героя в тёмных областях), проекция camera.toScreen
каждый тик, детерминированный seed мерцания по id, снапшот для моста
- LocationScene: lightView в renderer.lightRoot, тик света до ранних выходов
(свет живёт в диалогах/катсценах), зачистка в exit()
- агентный мост: слой lighting {ambient, sources}, инвариант lighting-bounded
- движок: Lighting.destroy принимает опции (делегирует в Container)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
9 hours ago
|
feat(game): агентный мост — pickChoiceByText, path/mood/tags в снапшоте, сценарий quest-bells
...
- DialogueSystem.pickChoiceByText(text) — выбор варианта по тексту реплики
(реплики героя в графе — выборы по библии мира; elder_first теперь ветвится)
- DialogueSnapshot += mood/tags/path — снапшот показывает настроение и путь
прохождения графа
- мост: команда сцены scene:pickChoiceByText, GameAgent.pickChoiceByText
(ждёт waitingForChoice, берёт по тексту), прокси AgentClient (+timeout
у runDialogue)
- новый checks/quest-bells.mjs — полный цикл квеста «Три цветка»: взятие
у Ирвина выбором по тексту -> сдача (кат-сцена посадки, цветы списаны)
-> Мила (полотно из do[] в сумке) -> эпилог trader_after; входит в agent:check
- доки: agent.md (снапшот диалога, команды, API), practices.md (typewriter
и выбор в сценариях; метод моста = 3 места), в том же коммите
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|
feat(game): диалоги в JSON + dialogueRules (чистый анализ графов) + CLI dry-run
...
- графы диалогов — 6 JSON-файлов в data/dialogues/ (4 пробела + \n),
реестр dialogues.ts собирается JSON-импортами
- новый data/dialogueRules.ts: чистые checkGraph/analyzeGraph — реестры
параметрами, одна истина для валидатора, CLI и будущего редактора
- validate.ts делегирует графы в checkGraph; новые инварианты:
textless-cycle (error), silent-end (warn), string-unknown, item-unknown,
do-item/do-custom-unknown, quest-stage-unreachable (error)
- CLI npm run dialogues:dry [<id>] — прогон графов через DialogueRunner
на пресетах состояния (fresh / quest-taken+flowers / quest-done)
- доки: ui-and-dialogue.md (раздел «Графы в JSON и dry-run»), practices.md,
CLAUDE.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|

feat(game): квест-стадии на DialogueConditions; чистка флагов знакомств + миграция v2
...
- QuestStage.ready — данные (DialogueConditions) вместо замыкания; стадия
сдачи — whenVars flowers >= 3. questDialogueFor(state, npc, world?)
фильтрует через движковый evalConditions.
- Двойной учёт знакомств устранён: npcs.flagKey → FLAGS.met_elder/met_mila,
графы уже ставят их сами — talkTo перестал ставить флаг вручную;
camelCase-ключи metElder/metTrader удалены из ids.ts.
- data/migrations.ts: registerStateMigrations + migrateV1toV2
(metElder→met_elder, metTrader→met_mila); Game регистрирует при старте.
- Движок: фикс цикла миграций в GameState.load — выход при достижении
dataVersion (миграция, забывшая повысить version, не портит данные);
контракт задокументирован в core.md, оси версий — в assets-audio-save.md.
- Тесты: две миграции по порядку, незабампленная миграция не применяется
дважды, старый сейв v1 читается, готовность стадии через whenVars.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|
feat(game): do[]-эффекты в контенте через EffectSink; QuestEffect-свитч удалён
...
- data/effects.ts: реестр DIALOGUE_CUSTOM (plant_flowers) — имена сюжетных
эффектов, как FLAGS/VARS.
- systems/DialogueEffects.ts: DialogueEffectSink + applyDialogueEffect
(give/take в сумку, sound, toast, custom; unknown kind — тихий игнор,
валидатор = error).
- DialogueSystem: registerSink + runner.onEffect → sink.
- Контент на do[]: elder_hand_in.accept → custom plant_flowers;
trader_first.give_cloth → giveItem cloth. Удалены QuestEffect,
EXTRA_EFFECTS, questEffectFor, поле QuestStage.effect и ручной switch
в onDialogueFinished (custom откладывается до конца диалога — кат-сцена
не рвёт реплику).
- Валидатор: do[].id give/take ∈ ITEMS, custom ∈ DIALOGUE_CUSTOM (error).
- Сценарий interact-world: первый advance теперь догоняет печать —
двойное нажатие.
- Тесты: give/take в Inventory, custom до sink, unknown игнор.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|
feat(engine): презентация диалогов — mood/tags/textKey, typewriter, клавиатурный выбор
...
- DialogueNode/Choice: mood, tags, textKey (+speakerKey у узла); view
получает mood/tags, текст резолвится hooks.resolve (fallback — ключ,
inline-текст первичен). Узел с одним textKey — реплика.
- ui/reveal.ts: чистый revealText(full, elapsedMs, cps) — тесты в node.
- DialogueBox v2: typewriter (update/skipReveal/revealing), moodColors,
клавиатурный курсор выбора (ListCursor: moveCursor/activate/cursorIndex),
высота панели растёт от контента.
- Игра: DialogueSystem.advance — сначала догнать печать, при выборе
активировать курсор; up/down листают варианты; typewriter 40 cps +
moodColors в LocationScene.
- Тесты: revealText, mood/tags в view, textKey/speakerKey; доки
ui-and-dialogue.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 hours ago
|
game(scenes): 4 сцены меню на движковом каркасе MenuSceneBase
...
- MenuScene/SettingsScene/SaveSlotsScene/InventoryScene — наследники
MenuSceneBase: скопированная навигация (up/down/advance/menu + гард
перехода) уехала в движок; у каждой сцены только build() и хуки.
- SaveSlotsScene: слоты из data/saves.ts, подписи из slotMeta с фолбэком
на полный load (старые сейвы), пустые слоты disabled (курсор их
пропускает), autosave защищён canDelete.
- Меню сейвов пишет мету (title/savedAt/version/extras.area).
- MenuList.setItems сохраняет фокус при пересборке (громкость больше не
сбрасывает курсор на первую строку).
- Агентный мост не тронут: снапшот из inventory.all, команды те же.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
11 hours ago
|
game: формат сейва — в saveData.ts, слоты конфигом, дефолт хазарда в контент
...
- scenes/saveData.ts: SAVE_VERSION/ReturnToData/SaveData/normalizeSave вынесены
из MenuScene (формат сейва больше не живёт в файле меню); MenuScene
реэкспортирует для совместимости.
- data/saves.ts: SAVE_SLOTS/slotTitle/canDelete вместо хардкода
['autosave','slot1'...] в SaveSlotsScene (дважды).
- HazardDef.requiresItem стал обязательным — контент уже задаёт 'cloth',
мёртвый фолбэк ?? 'cloth' в LocationScene снят (дефолт — в контенте).
- Тест: слоты/подписи/canDelete (510 всего).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
11 hours ago
|
UX-пачка: подсказки, клик-зоны, моты, коллизия домов, сундук, тихая вода
...
- Тосты держатся по длине текста (до 6 с) + подсказка сбора колокольчиков
при первом входе в пруды (флаг hint_bells).
- Клик по «телу» объекта: RouterDeps.pixelTile как фолбэк на голом клике —
bbox тел NPC/интерактивов (без подписей) + ремап на высокий тайл (дома).
- Моты: заметная насыпь с пульсирующей искрой, HUD-счётчик, вьюха
растворяется с искрами при поднятии (InteractSink.onConsumed).
- Движок: TallSpec.shadow — тайл (tx-1,ty-1) за домом блокируется
(shadowTilesOf в collision.ts + isWalkable карты, тесты).
- Интерьеры: бронзовый контур проёма + подпись «выход».
- Спрайт сундука (tiles/chest.png) вместо ящика-плейсхолдера.
- Вода прудов: radius 2.5, volume 0.22 — только вплотную и тихо.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 hours ago
|
Фикс десинка вью героя (SpriteMotion не двигает blink-view) + звук: ветер, шорохи, тише вода
...
- Движок: SpriteMotion перезаписывает позицию/поворот только при bob/sway —
view с чистым blink/pulse можно двигать извне (герой прибивало к точке
спавна, ходьба выглядела камерным скроллом, по прибытии спрайт
«возвращался»); detach симметричен; тесты SpriteMotion
- PlayerController: syncView на точном прибытии в waypoint (кадр не отстаёт)
- Звук: ambience/wind — глобальный слой (AmbienceLayerDef.radius опционален,
нет at/tiles — константная громкость) на лугах и прудах; вода прудов
тише (0.6→0.35, радиус 6→5); sfx/rustle — редкие дальние шорохи пепла
из тика сцены (rng сцены, случайные pan/rate). Птиц в мире нет по лору
- Доки: anim.md (правило позиционирования), practices.md (глобальные
слои, шорохи, «птицы молчат»)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
22 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
22 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
22 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
22 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>
root
committed
23 hours ago
|
Мост: scene:synthesize — звук по спеку из агентных проверок (работа E2)
...
Агент без слуха описывает звук параметрами (SoundSpec), движок
компилирует его в буфер (playSpec), факт запуска наблюдаем в
__gameAudioLog. Проба checks/synth.mjs в agent:check: удар/звон/
скрип/гул по спекам, громкость доезжает до голоса, повторный синтез
играет, негодные спеки возвращают null, гул не глушит амбиент.
Формы спеков — в docs/engine/agent.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Движок: 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>
root
committed
23 hours ago
|
Игра: 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>
|
Игра: шаги по поверхностям, звуки предметов, локальные амбиент-слои
...
- Шаги: sfx/step_grass|ash|water|floor по тайлу под ногами (stepKey), старый sfx/step удалён
- Предметы: моты → mote_pickup, сундук → chest_open, знаки/записка → note, whoosh на переходах
- Фауна: событие fauna:startle (FaunaSystem слышит combat:attack) → sfx/deer_startle
- AudioSystem.setLayers: несколько амбиент-слоёв сразу, синхронный дедуп, тик-фейд громкости
- AreaDef.ambienceLayers: вода прудов, гул башни (точка), скрипы домов (тайлы)
- validate-тест покрывает новые ключи через AUDIO_KEYS
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>
|
Игра: амбиент на шину ambience вместо music, слайдер «Амбиент»
...
- gen.mjs: ключи ambience/meadows|ponds|zvenets -> assets/audio/ambience/ (music/ удалён)
- AUDIO_KEYS вынесен в data/audio.ts (валидатор в node-тестах без ?url-импортов Game)
- Game.playAmbience(key, 0.7) c guard ключа; '' — stopAmbience; шина ambience в settings
- AreaDef: визуальное ambience -> atmosphere, аудио ambience?: string (интерьеры — тишина)
- SettingsScene: Общая / Амбиент / Звуки (ползунок music не показываем — треков нет)
- validate-тест: area.ambience и Interactables.responses[].sound ∈ AUDIO_KEYS
- хвосты music/ в доках вычищены; agent:check зелёный
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>
|

Тела не проходят друг сквозь друга + карта коллизий агенту
...
Расталкивание через реестр сцены: герой выталкивает себя из NPC
(PlayerController), враг — из героя, NPC и своих (EnemySystem); каждый
актор двигает только себя (separateCircles). attackStop (0.85) больше
суммы радиусов — авто-атака не дрожит.
A* не ведёт героя сквозь тело: SceneObjects.walkGrid() считает тайлы
NPC занятыми (герой застревал «на носу» у Ирвина — звон в верёвку
не поднимал флаг). Проводка: клик по миру, авто-подход к цели,
scene:route моста.
Карта коллизий агенту: слой s.collision {width, height, blocked (0/1
с footprint пропов), props} + команды scene:walkable {x, y} и
scene:raycast {from, to} (прямая видимость, вода прозрачна). Новый
сценарий checks/collision.mjs: слой валиден, walkable/raycast на
конкретных тайлах, клик в дерево — герой в проходимом, телепорт в
тело спящего ползуна — враг выталкивает себя.
Доки: agent.md (слой + 2 команды), practices.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: NPC/интерактивы/пропы/фауна/враги в одном реестре
...
- дефы получают юниты: NpcDef.pos + atlas?, InteractableDef.pos + view?
(tile вычисляется при загрузке модуля — сейвы/снапшот/валидатор без миграций)
- SceneObjects: фасад реестра области (npc/int/prop с footprint)
- клик-роутинг: npcAt/interactableAt/enemyAt через реестр; чистый
resolveClick и приоритеты не тронуты (пробы transitions/interact зелёные)
- шов врагов ECS: запись с pos по ссылке, move после шага, remove при смерти
- фауна регистрируется (kind 'fauna'), вьюхи NPC — def.atlas, интерактивов —
def.view.tex
- инвариант registry-consistent (реестр согласован с ECS)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|