rpg / docs / engine /
@root root authored 14 hours ago
..
README.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
art-pipeline.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
assets-audio-save.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
core.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
getting-started.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
input.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
maps.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
recipes.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
render.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
ui-and-dialogue.md Миграция игры на новые API движка + документация docs/engine 14 hours ago
README.md

Документация движка @rpg/engine

Движок — переиспользуемая основа для 2D-пиксельных игр в браузере. Первая игра на нём — «Пепельные луга» (apps/game), она же живой пример использования всех API.

Карта документации

Файл О чём
getting-started.md Новая игра с нуля: bootstrap, сцены, ассеты
core.md Engine, GameLoop, EventBus, Tween, GameState, StateMachine, Settings
render.md Renderer, pixel-perfect, камера, IsoDepthLayer, частицы
input.md Действия, клавиатура, мышь/тач, геймпад, виртуальный джойстик
maps.md Изометрия, A*, формат карт, импорт из Tiled
ui-and-dialogue.md UI-кит, PixelText, диалоговые графы
assets-audio-save.md AssetLoader, атласы, AudioManager, сейвы
art-pipeline.md Генератор пиксель-арта, палитра, замена на рисованный арт
recipes.md «Как сделать…»: готовые решения типовых задач

Принципы

1. Жёсткая граница API

Игра импортирует движок только через @rpg/engine (весь API реэкспортирован из packages/engine/src/index.ts). Прямые импорты pixi.js в игре — нарушение границы: нужные типы реэкспортируются движком (Container, Graphics, Text, Sprite, Texture). Это позволяет менять внутренности движка, не трогая игры.

2. Fixed timestep

Логика обновляется фиксированным шагом 60 Гц (GameLoop, аккумулятор, максимум 5 шагов за кадр). dt в Scene.update всегда одинаковый — физика и таймеры детерминированы. Рендер происходит после каждого шага.

3. Pixel-perfect

  • Виртуальное разрешение (по умолчанию 480×270) растягивается целым числом на экран (computeScale), image-rendering: pixelated, roundPixels: true.
  • Камера округляет позицию до целого пикселя — арт не «дрожит».
  • Пиксельный шрифт (VT323) рисуется в тех же виртуальных пикселях.

4. Движок жанронезависим

В packages/engine нет ни одного упоминания контента конкретной игры: GameState — механика флагов и переменных, DialogueRunner — механика графов. Всё содержимое (тексты, флаги сюжета, карты) живёт в приложении.

5. Инъекция вместо окружения

Всё, что зависит от браузера, инъецируется или изолируется: StorageLike для сейвов, resolveUrl для ассетов, parent для канваса. Чистые модули (математика, A*, диалоги, формат карт) тестируются в Node без браузера — Vitest.

Структура пакетов

packages/engine/src/
  core/       Engine, GameLoop, EventBus, Tween+easing, GameState, StateMachine, Settings
  scene/      SceneManager (стек сцен + fade-переходы)
  render/     Renderer, Camera, IsoDepthLayer, Particles, computeScale
  input/      InputManager (клавиатура/мышь/тач/геймпад), VirtualJoystick
  map/        IsometricTileMap, pathfinding (A*), mapFormat (JSON+RLE), tiled-импортёр
  math/       Vec2, изометрия, seeded RNG
  dialogue/   DialogueRunner (графы диалогов, view-агностик)
  ui/         DialogueBox, Panel, Button, MenuList, PixelText
  anim/       FrameAnimation
  audio/      AudioManager (шины master/music/sfx, кроссфейд)
  assets/     AssetLoader (текстуры, атласы)
  save/       SaveManager (JSON-слоты)
  ecs/        World/createEntity/query/addSystem
  debug/      DebugOverlay

Известные грабли (важно!)

Подробности — в корневом CLAUDE.md; краткий список:

  • Assets.load без предварительного Assets.init({}) висит навсегда без ошибок — AssetLoader делает это сам, но если грузите напрямую через Pixi, не забудьте.
  • app.renderer недоступен до завершения app.init()Renderer.setup() это учитывает.
  • Изометрический ромб уходит в минус по X: границы камеры начинаются от западного угла карты ({x: -size.width/2, ...}).
  • document.fonts — шрифт загружается асинхронно; ensurePixelFont() вызывается до создания текста, но фолбэк monospace всегда безопасен.