# Сцены — `$.scene`

Сцена — описание того, что живёт на экране: функции `enter`/`exit`/`update`.
Переход **отложенный**: `$.scene.load()` только ставит запрос, а смена
происходит в начале следующего кадра. Поэтому сцену можно менять прямо из
обработчика клика, не разрушая объект посреди его вызова.

```js
$.scene.add('menu', {
    enter() { buildMenu(); },
    update(dt) { animateMenu(dt); },
    exit() { clearMenu(); },
});
$.scene.load('menu');
```

---

## 1. Методы

| Вызов | Смысл |
|---|---|
| `add(name, scene)` / `remove(name)` / `has(name)` / `names()` | реестр сцен |
| `load(name, opts?)` | переключиться на сцену (в начале кадра) |
| `loadAsync(name, opts?)` | то же, с ожиданием загрузки |
| `push(name)` / `pop()` / `stack()` | стек сцен (меню поверх уровня) |
| `restart()` / `current()` / `busy()` | перезапуск / текущая / идёт переход |
| `transition(opts)` | затухание между сценами (`duration`, `color`) |
| `preload(names)` | предварительная подготовка (сейчас — только звуки) |

`busy()` возвращает `true`, пока переход не завершился — на это удобно вешать
экран загрузки.

## 2. Ограничения

* **`preload` — заглушка**: греет только звуки ([scene.js](https://github.com/Nikide/russiano2d/blob/main/src/highlevel/scene.js)),
  текстуры и сцены не готовит; для честной загрузки — `$.loading.run`;
* **нет подгрузки частями**: сцена целиком в памяти, стриминга нет;
* **переход — только затухание**: слайдов, шейдеров и «кругов» нет; сложное
  делается своим `$.gfx.post`;
* **сцена не владеет узлами**: `exit` должен сам удалить свои узлы
  (`node.remove()`), иначе они останутся в реестре.

## 3. Порядок кадра

`tickScene()` вызывается движком после игровой логики: `update` идёт по сценам
сверху стека вниз, `enter`/`exit` — в начале кадра, до `$.update`.
