| 2026-09-07 |
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
19 hours ago
|
| 2026-09-06 |
Батч 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>
root
committed
23 hours ago
|
Батч 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>
root
committed
23 hours ago
|
Реестр размеров спрайтов: 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>
|

Крупные объекты: 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>
|

Разграничение: жанронезависимые тулзы переехали в packages/engine/tools
...
Правило: тулза, знающая контент игры (палитру, тайлы, локации, сценарии
акта), живёт в apps/game/tools как «сценарий применения»; машинерия без
знаний об игре переезжает к движку.
- packages/engine/tools/: png.mjs (encode+decode), canvas.mjs (палитра —
параметр), imaging.mjs (кроп/квантизация/обзорный лист), wav.mjs
(WAV-энкодер и примитивы синтеза), agent-lib.mjs (маяк — параметр
openGame), boundary.mjs (правила гварда, корни/публичное API — опции)
+ юнит-тесты boundary.
- exports движка: "./tools/*" — игровые сценарии импортируют
@rpg/engine/tools/* вместо относительных путей; maps/gen.test.ts
больше не лезет в src движка (encodeMap/parseMap из @rpg/engine).
- Игра остаётся сценарным слоем: palette.mjs, gen.mjs (арт/звуки),
aiart (промпты/манифест/тонкий post.mjs), checks/, smoke*, agent.mjs,
новый lib.mjs (маяк загрузки игры поверх движкового каркаса).
- Артефакты генераторов (арт, карты, WAV, processed) бит-в-бит прежние.
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>
|