README.md 5,2 КБ
Newer Older
Nikitos's avatar
Nikitos включено в состав коммита
1
# Демо «Типичная ночь в Мытищинском лесу» — ночной лес, свет, волны, апгрейды
Nikitos's avatar
ф  
Nikitos включено в состав коммита
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Самый крупный пример игры на `$`: зомби-шутер в духе Vampire Survivors.
Игрок сам стреляет по ближайшему врагу, игрок только уворачивается и собирает
добычу. В темноте видно ровно столько, сколько светит фонарь.

```bash
./build/russiano2d --game demos --scene shooter_witch   # сам бой
./build/russiano2d --game demos --scene witch_menu      # меню-интро
```

| Управление | Что делает |
|---|---|
| `WASD` / стрелки | идти |
| `1` / `2` / `3` или мышь | выбрать карту апгрейда |
| `F` | переключить камерный пресет вручную |
| `R` | заново после смерти |
| `Esc` | в меню демо |

---

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

| Слой | Чем сделан | Где смотреть |
|---|---|---|
| лес | `<tilemap>` из ASCII, **автотайл** тропы по соседям | `buildForest()` |
| деревья | спрайты с коллизиями и подсказками для акустики | `buildForest()` |
| свет | `<light>` (мягкое свечение) + `engine.light.visibility` для теней от стволов | `buildLights()`, `drawVisibility()` |
| звук | `$.audio.zone/obstacles/damping`, реверберация поляны, панорама выстрелов | `installAudio()` |
| VFX | кровь, лужи, трассеры (`$.fx.ribbon`), молнии, ударные волны, hit-stop, тряска | `tickGore()`, `$.fx.*` |
| камера | пресеты кадра: «ночной лес», «кровавая луна» | `tickPresets()`, `$.gfx.postPreset` |
| апгрейды | пауза + три карты, выбранное меняет оружие и статы | `openUpgrade()`, `tickWeapons()` |
| меню и смерть | отдельные сцены `witch_menu` и экран проигрыша | `createMenuScene()` |

## 2. Как это устроено

Nikitos's avatar
Nikitos включено в состав коммита
37
Две сцены в одном демо: `witch_menu` — интро-меню (кнопка «Типичная ночь в Мытищинском лесу» в лаунчере
Nikitos's avatar
ф  
Nikitos включено в состав коммита
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
ведёт именно сюда), `shooter_witch` — сам забег. Обе живут в одном файле и
делят общие данные, но мир строится заново на входе в каждую — так видно, что
`$.scene` меняет и музыку, и весь мир.

```js
// земля: автотайл сам подбирает тайлы тропы по соседям
const ground = $.tilemap.fromASCII(rows, { '.': 1, ',': 2, 'p': PATH_MARK });
ground.autotile({ mode: 'terrain', terrain: 'path' });

// фонарь: свет — обычный узел, платится одним свечением на кадр
$('<light>', { radius: 235, intensity: 1, color: '#ffbe73', falloff: 2.2 })
    .at(lamp.x, lamp.y).appendTo($.world);
```

## 3. Своё такое демо

1. **Мир.** `<tilemap>` + `autotile` для органичной земли, спрайты для
   объектов — `docs/highlevel/tilemap.md`.
2. **Свет.** `<light>` на фонарях; если нужны тени от препятствий —
   `engine.light.visibility(...)` и рисование полигона из `$.render`
   (демо `light` больше нет, рабочий пример остался здесь).
3. **Волны.** Таймер + спавн за экраном: `$.time.every(ms, …)` и проверка,
   что враг вне кадра.
4. **Прогресс.** Кристаллы как `<pickup>`, уровень — свой счётчик,
   карты апгрейдов — пауза `$.time.pause()` и три кнопки.
5. **Проверка без рук.** `python3 tests/agent/demos_test.py shooter_witch` —
   тест гоняет 900 кадров боя и требует, чтобы враги гибли и в журнале не было
   ошибок игрового кода.

## 4. Производительность

Демо сознательно тяжёлое: тысячи тайлов, десятки врагов, кровь и частицы.
Ориентиры, на которые смотрели при написании: список узлов мира
переиспользуется, свет — узлы `<light>` вместо ручных полигонов на каждого
врага, кровь — пул объектов (`$.pool`). Если своё демо тормозит, начните с
`$.debug.profiler.on(true)` и `F1` — разбор в
[`docs/HIGH_LEVEL_API_PERF.md`](../../docs/HIGH_LEVEL_API_PERF.md).

## 5. Ассеты

Лес — CC0 Kenney RPG/Urban, персонаж — лист из `demos/assets/art/characters`,
музыка и звуки — CC0 Juhani Junkala. Полный список с лицензиями:
[`demos/assets/CREDITS.md`](../assets/CREDITS.md).