- Рендер переведён в псевдо-3D: наклонная PerspectiveCamera, пол лежит плашмя, персонажи/враги — вертикальные спрайты-биллборды, стены с высотой. Починен баг: пол создавался без поворота и стоял вертикально → «вывернутая» перспектива. - Двери видны всегда: закрыты (засов) во время боя, открытый проём после зачистки. - render/assets.ts: процедурные текстуры (спрайты персонажей/врагов, пол, стены, двери, снаряд, тень) + эффекты оружия (вспышка из дула, искры, облачко гибели). - Светлее палитра — исправлено «тёмное на тёмном». - Игра переименована в «Биндим Фигняшку»; полная русификация UI (ДАЛЬНИЙ/БЛИЖНИЙ, ИГРА ОКОНЧЕНА, ПОБЕДА); клавиши-подсказки оставлены латиницей. - Ввод по event.code → WASD/Q/R работают в любой раскладке (вкл. русскую). - theme.ts урезан до реально используемых тинтов (bg/swing/flash). - docs/ASSET_BRIEF.md — бриф и промпт на полную художку; доки синхронизированы. - Ядро (src/core) не тронуто — раунд чисто render/UI. 27 тестов + типы зелёные. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
106 lines
8.0 KiB
Markdown
106 lines
8.0 KiB
Markdown
# CLAUDE.md — как работать с этим проектом
|
||
|
||
Инструкции для ИИ-агентов **и** разработчика. Прочитай целиком перед правками.
|
||
Цель проекта — держать **рабочую, расширяемую базу** рогалика. Не ломать то, что
|
||
работает; добавлять — по правилам ниже.
|
||
|
||
## Что это
|
||
|
||
Top-down рогалик (в духе Binding of Isaac). Логика — чистый TypeScript
|
||
(`src/core/`), рендер — three.js в псевдо-3D (наклонная `PerspectiveCamera`, `src/render/`), сборка/тесты — Bun.
|
||
Обзор — [`README.md`](./README.md), детали — [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md),
|
||
рецепты доработки — [`docs/HOWTO.md`](./docs/HOWTO.md).
|
||
|
||
## 🔑 Золотые правила (нарушать = ломать архитектуру)
|
||
|
||
1. **Ядро без рендера и DOM.** В `src/core/**` НЕЛЬЗЯ импортировать `three`,
|
||
обращаться к `window`/`document`/`canvas`. Логика общается с миром только через
|
||
`InputState` (вход) и публичные поля `Game` (для чтения рендером).
|
||
2. **Рендер ничего не меняет в игре.** `src/render/**` только ЧИТАЕТ `Game` и
|
||
рисует. Любая мутация состояния из рендера — баг.
|
||
3. **Случайность только через `Rng`.** Никаких `Math.random()` в `core/`. Это
|
||
сохраняет детерминизм (тесты, отладка по seed).
|
||
4. **Время — в «шагах» (1/60 c), а не в кадрах.** Скорости — «пиксели/шаг»,
|
||
перезарядки — «шаги». Не двигай ничего в коде рендера или прямо в rAF.
|
||
5. **Числа — не в коде.** Константы движка (размеры, геометрия дверей, базовый
|
||
баланс) — в `src/config.ts`; параметры конкретного забега (размер карты, сила
|
||
врагов, HP игрока, seed) — в правилах уровня `src/core/rules.ts`. Не раскидывай
|
||
«магические числа» по логике.
|
||
6. **Освобождай ресурсы three.js.** Создаёшь геометрию/материал на сущность —
|
||
обеспечь `dispose()` при её удалении (см. `sync*`/`sweep` в `ThreeRenderer`).
|
||
7. **Комментарии и текст для игрока — по-русски**, как в существующем коде.
|
||
|
||
## Команды
|
||
|
||
```bash
|
||
bun run dev # дев-сервер + watch → http://localhost:3000
|
||
bun run build # прод-сборка в dist/
|
||
bun run typecheck # tsc --noEmit (строгий) — НЕ ловится при bun build!
|
||
bun test # юнит-тесты ядра
|
||
bun run check # typecheck + test
|
||
```
|
||
|
||
> ⚠️ `bun build` **не проверяет типы**. Поэтому `bun run typecheck` обязателен —
|
||
> именно отсутствие тайп-чека когда-то скрыло рантайм-регрессию.
|
||
|
||
## Definition of Done (для любой правки)
|
||
|
||
1. `bun run check` зелёный (типы + тесты).
|
||
2. Если менял логику — **добавил/обновил тест** в `tests/`.
|
||
3. Если менял геймплей/рендер — **проверил в браузере** (`bun run dev`, открыть
|
||
страницу, увидеть, что играется, в консоли нет ошибок). Юнит-тесты не видят
|
||
рендер — визуальную проверку не пропускать.
|
||
4. Обновил доки, если поменялось поведение или структура.
|
||
|
||
## Где что лежит (карта для навигации)
|
||
|
||
| Хочешь поменять… | Иди в… |
|
||
|---|---|
|
||
| константы движка (размер тайла/комнаты, геометрия дверей, базовый баланс) | `src/config.ts` |
|
||
| правила уровня / пресеты в меню (размер карты, сила врагов, HP, seed) | `src/core/rules.ts` |
|
||
| поведение за один шаг (движение, атака, ИИ, переходы) | `src/core/Game.ts` |
|
||
| данные сущности | `src/core/entities/*` |
|
||
| генерацию карты | `src/core/world/RoomMap.ts` |
|
||
| форму комнаты/тайлы | `src/core/world/tiles.ts`, `Room.ts` |
|
||
| коллизии | `src/core/systems/collision.ts` |
|
||
| расстановку врагов | `src/core/systems/spawner.ts` |
|
||
| как рисуется мир (псевдо-3D) | `src/render/ThreeRenderer.ts` |
|
||
| спрайты/текстуры (графика) | `src/render/assets.ts` (бриф на художку — `docs/ASSET_BRIEF.md`) |
|
||
| цвета/тинты/фон | `src/render/theme.ts` |
|
||
| HUD/миникарту | `src/render/HudOverlay.ts` |
|
||
| стартовое меню | `src/ui/StartMenu.ts` |
|
||
| раскладку клавиш | `src/input/KeyboardController.ts` |
|
||
| тайминг/цикл, поток меню↔игра | `src/engine/GameLoop.ts`, `src/main.ts` |
|
||
|
||
Пошаговые рецепты («добавить врага», «новое оружие», «тип комнаты», «сменить
|
||
рендер») — в [`docs/HOWTO.md`](./docs/HOWTO.md).
|
||
|
||
## Грабли, на которые уже наступали (не повторять)
|
||
|
||
- **Пустая карта.** `new RoomMap(rng)` ДОЛЖЕН генерировать карту в конструкторе.
|
||
Если карта пустая — `curRoom` будет `undefined` и всё упадёт на старте.
|
||
- **`OPP` направлений.** Противоположное к `up` — это `down`, к `left` — `right`.
|
||
Любая другая раскладка ломает встречные двери и связность карты.
|
||
- **Пол «выворачивает» перспективу.** Пол в псевдо-3D надо класть ПЛАШМЯ
|
||
(`flatMesh`, поворот −90° вокруг X). Без поворота он встаёт вертикально и вид
|
||
ломается. Спрайты/стены — `DoubleSide` (камера переворачивает Y, иначе грани отсекаются).
|
||
- **Canvas вылезает за рамки.** Холстам нужен CSS-размер (`width/height:100%`),
|
||
иначе они показываются в размер HiDPI-буфера.
|
||
- **Комната без врагов не открывается.** Если в комнате 0 врагов (сокровищница) —
|
||
она должна стать `cleared` сразу при входе, иначе двери не появятся.
|
||
|
||
## Стиль кода
|
||
|
||
- TypeScript strict, без `any` (кроме узких мест вроде `window as …` в `main.ts`).
|
||
- Маленькие чистые функции для логики; классы — для сущностей/состояния.
|
||
- Имена и комментарии осмысленные, по-русски. Комментарий объясняет «почему», а не «что».
|
||
- Перед коммитом — `bun run check`.
|
||
|
||
## Чего НЕ делать без явной просьбы
|
||
|
||
- Не добавлять тяжёлые зависимости (физдвижки, фреймворки). База намеренно лёгкая.
|
||
- Не переписывать архитектуру «ядро ↔ рендер».
|
||
- Не коммитить `dist/` и `node_modules/` (см. `.gitignore`).
|
||
- Не превращать игру в полноценное 3D, пока этого не попросили (рендер для этого
|
||
готов — он изолирован, — но это отдельная большая задача).
|