Files
Binding-Fignyaac/CLAUDE.md
T
mayatnikovandClaude Opus 4.8 0684368ac7 refactor: рабочая база на three.js + меню/правила уровней + доки
Полный рефакторинг проекта в стабильную расширяемую базу рогалика.

Почему: после разнесения single-file на модули потерялся вызов генерации
карты (RoomMap не генерировал комнаты) → игра падала на старте; баг скрывался
тем, что Bun-бандлер не проверяет типы.

Архитектура:
- Логика игры (src/core/) полностью отделена от рендера: без three.js и DOM,
  тестируется без браузера.
- Рендер мира на three.js с ортокамерой (2D-вид); HUD/миникарта — 2D-канвас поверх.
- Фиксированный игровой цикл 60 Гц + интерполяция (раньше скорость зависела
  от частоты кадров).
- Seeded-RNG, ввод через абстрактные «намерения» (InputState).

Возможности:
- Стартовое меню с выбором уровня (Esc → меню).
- Конфигуратор уровней: LevelRules + 5 пресетов (размер карты, плотность/сила
  врагов, HP, фиксированный seed).
- Тема внешнего вида (render/theme.ts) — задел под кастомные ассеты.

Качество:
- 27 юнит-тестов ядра (генерация, симметрия дверей, коллизии, спавн, правила).
- Два круга adversarial-ревью; исправлено 6 реальных багов
  (кнокбэк сквозь стены → софт-лок; незакрываемая сокровищница; фикс-сид после
  рестарта; перенос ввода между забегами; нет source maps; неточности в доках).
- Документация: README, docs/ARCHITECTURE.md, CLAUDE.md, docs/HOWTO.md.
- dist/ исключён из гита; bun.lock зафиксирован.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:07:06 +03:00

7.7 KiB
Raw Blame History

CLAUDE.md — как работать с этим проектом

Инструкции для ИИ-агентов и разработчика. Прочитай целиком перед правками. Цель проекта — держать рабочую, расширяемую базу рогалика. Не ломать то, что работает; добавлять — по правилам ниже.

Что это

Top-down рогалик (в духе Binding of Isaac). Логика — чистый TypeScript (src/core/), рендер — three.js с ортокамерой (src/render/), сборка/тесты — Bun. Обзор — README.md, детали — docs/ARCHITECTURE.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. Комментарии и текст для игрока — по-русски, как в существующем коде.

Команды

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
как рисуется мир src/render/ThreeRenderer.ts
цвета/внешний вид/ассеты мира 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.

Грабли, на которые уже наступали (не повторять)

  • Пустая карта. new RoomMap(rng) ДОЛЖЕН генерировать карту в конструкторе. Если карта пустая — curRoom будет undefined и всё упадёт на старте.
  • OPP направлений. Противоположное к up — это down, к leftright. Любая другая раскладка ломает встречные двери и связность карты.
  • Чёрный экран при работающем рендере. Ортокамера инвертирует Y → нужен DoubleSide на материалах, иначе грани отсекаются.
  • Canvas вылезает за рамки. Холстам нужен CSS-размер (width/height:100%), иначе они показываются в размер HiDPI-буфера.
  • Комната без врагов не открывается. Если в комнате 0 врагов (сокровищница) — она должна стать cleared сразу при входе, иначе двери не появятся.

Стиль кода

  • TypeScript strict, без any (кроме узких мест вроде window as … в main.ts).
  • Маленькие чистые функции для логики; классы — для сущностей/состояния.
  • Имена и комментарии осмысленные, по-русски. Комментарий объясняет «почему», а не «что».
  • Перед коммитом — bun run check.

Чего НЕ делать без явной просьбы

  • Не добавлять тяжёлые зависимости (физдвижки, фреймворки). База намеренно лёгкая.
  • Не переписывать архитектуру «ядро ↔ рендер».
  • Не коммитить dist/ и node_modules/ (см. .gitignore).
  • Не превращать игру в полноценное 3D, пока этого не попросили (рендер для этого готов — он изолирован, — но это отдельная большая задача).