Files
Binding-Fignyaac/CLAUDE.md
mayatnikovandClaude Opus 4.8 3bb46e2f6b feat(render): псевдо-3D, всегда видимые двери, ассеты+эффекты, русификация
- Рендер переведён в псевдо-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>
2026-06-18 15:16:57 +03:00

8.0 KiB
Raw Permalink Blame History

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

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

Что это

Top-down рогалик (в духе Binding of Isaac). Логика — чистый TypeScript (src/core/), рендер — three.js в псевдо-3D (наклонная PerspectiveCamera, 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
как рисуется мир (псевдо-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.

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

  • Пустая карта. new RoomMap(rng) ДОЛЖЕН генерировать карту в конструкторе. Если карта пустая — curRoom будет undefined и всё упадёт на старте.
  • OPP направлений. Противоположное к up — это down, к leftright. Любая другая раскладка ломает встречные двери и связность карты.
  • Пол «выворачивает» перспективу. Пол в псевдо-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, пока этого не попросили (рендер для этого готов — он изолирован, — но это отдельная большая задача).