# Демо «Re2D · мир-коробка» — 2.5D от первого лица над плоским миром

Комната 1280×1280 с кирпичными стенами, каменным полом и потолком. Игрок ходит
от первого лица, мышь крутит взгляд куда угодно, а в комнате стоят три добрых
маскота — три экземпляра базовой модели Руси из одного
описания `demos/rotsprite/russi.character.json`.

```bash
./build/russiano2d --game demos --scene re2d_world
./build/russiano2d --game demos                       # кнопка «Re2D · мир-коробка»
```

| Управление | Что делает |
|---|---|
| `W` `A` `S` `D` | ходить: вперёд — туда, куда смотрят глаза; `A`/`D` — боком |
| мышь | смотреть во все стороны (захват мыши: курсор скрыт, движение относительное) |
| `Esc` | назад в меню (камера и мышь возвращаются в 2D) |

Подойдите к маскоту: на расстоянии около 4 м он **замечает** вас (удивляется и
поворачивается), ближе 2,3 м — **улыбается** и говорит реплику (панель RmlUi
внизу), отойдёте — возвращается в исходную стойку. При обходе вокруг маскота его
модель плавно поворачивается вместе с вашим ракурсом.

---

## 1. Что показывает

| Слой | Чем сделан | Где в `index.js` |
|---|---|---|
| вид от первого лица | `$.camera.kind(Re2D)`, `.eye()`, `.fov()`, `.fog()`, `.mouseLook()` | `enter()` |
| комната | `$.re2d.room({...})`: пол, потолок и четыре стены-плиты с текстурами | `ROOM`, `enter()` |
| игрок | обычный `<player>` с `.controls('wasd')` и `.kind(Re2D)`; идёт по взгляду камеры | `enter()` |
| физика | обычные 2D-тела: стены статические, игрок упирается как в любой 2D-игре | — |
| маскоты | `$.re2dSprite.from(...)`, `.re2dStyle('pixel')`, `.kind(Re2D)` | `enter()` |
| реакция маскотов | обычная игровая логика: расстояние → поворот к игроку, эмоция, `state` | `update()`, `reaction()`, `turnToward()` |
| интерфейс | документ RmlUi `demos/ui/re2d-hud.rml` (прицел, реплика, подсказка) | `HUD_DOC` |
| агент | `$.agent.expose('re2dWorld', …)`: игрок, камера, состояние маскотов | `install()` |

Мир остаётся плоским: те же `x`, `y`, размеры, тела и события, что в 2D. Re2D — вид
на него, поэтому тот же код без `.kind(Re2D)` и без `$.camera.kind(Re2D)` — обычная
2D-сцена вида сверху.

## 2. Стоимость кадра

Три маскота в `pixel`-стиле с idle-анимацией: `JS: логика` около 11 мс, `сборка
батча` около 1.6 мс на 60-кадровом шаге (замер `$.debug.profile()`, headless).
Основная часть — синтез картинки анимированных персонажей в C (около 3 мс на
персонажа), а не перспектива. Об этом и о том, как держать в сцене больше
маскотов, — [highlevel/re2d.md](highlevel/re2d) §3.

## 3. Как сделать своё

1. Скопируйте `index.js`, поменяйте `ROOM`, `NPCS`, реплики и тексты.
2. Свои стены и перегородки — обычные `<wall>` с `.kind(Re2D)` и `attr('top', …)`.
3. Свои спрайты (предметы, враги) — `<sprite>`/`<enemy>`/`<pickup>` с `.kind(Re2D)`:
   картинка стоит на полу и повёрнута к камере.
4. Проверка без рук: `python3 tests/agent/highlevel_re2d_world_test.py`.

Полное описание — [docs/RE2D.md](RE2D).
