Геймпад Xbox, меню паузы с настройками, новый хаб с музыкой

- Геймпад: раскладка под паркур и гонки, обзор правым стиком, навигация по меню (A/B/крестовина)
- Меню паузы (Esc/Start): выход в хаб, настройки (мышь, стик, FOV, громкость, инверсия), справка по управлению
- Хаб 48x32x10 м: колонны, окна с городом, голограмма, лавки; музыка «Local Forecast - Elevator» (Kevin MacLeod, CC-BY)
- Тесты: pause_test, pad_menu_test, hub_tour; README обновлён

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 18:36:50 +05:00
co-authored by Claude Sonnet 5.5
parent 0ffba7311f
commit 2d347d132b
27 changed files with 1220 additions and 41 deletions
+42 -10
View File
@@ -32,10 +32,10 @@
| ✅ | Паркур: спринт, рывок, подкат, **присед (C)**, бег по стенам, прыжок от стены, двойной прыжок, подтягивание на уступ, зум (ЛКМ) |
| ✅ | Управление **не зависит от раскладки** (русская и любая другая): действия `InputMap` на физические клавиши |
| ✅ | Деплой: CI из `grid-world` на сайт; скрипты экспорта, dev-сервера, тестов без окна, выкладки сервера |
| ❌ | Управление с помощью геймпада |
| ✅ | **Геймпад Xbox** (раскладка под паркур и гонки, обзор правым стиком), **меню паузы** по Esc/Start (выход в хаб, настройки, справка), **настройки** (мышь, стик, FOV, громкость, инверсия) — разделы «Управление», «Меню паузы и настройки». В браузере с живым геймпадом не проверялось (только тест без окна) |
| ✅ | **Ники** (панель по N, подпись над игроками, в итогах гонки) и **общий рейтинг** лучших времён на сервере (топ-10 на Race/Parkour, таблица по Tab, доски в хабе, таймер и итоги Parkour, сдача в гонке на G) — раздел «Ники и рейтинг» |
| ❌ | Текстовый чат — **запланирован**, не сделан (план в «Дорожная карта → Ближайшее») |
| ❌ | Настроек (чувствительность мыши, громкость), меню паузы |
| ✅ | Хаб увеличен (48×32×10 м) и оформлен, в нём играет музыка «как в лифте» — раздел «Карты и порталы», «Лицензии» |
| ❌ | Серверных проверок (антиспуфинг позиций, античит): сервер только пересылает |
| ❌ | Сохранения прогресса, аккаунтов |
| ❌ | Автоматических тестов в CI (есть боты для ручного прогона, см. «Тесты без окна») |
@@ -58,7 +58,7 @@ godot --path . # можно запустить несколько ок
## Управление
Клавиши привязаны к **физическому расположению** (так работает и на русской раскладке). Действия лежат в
`project.godot → [input]`: `move_forward/back/left/right`, `jump`, `sprint`, `crouch`, `dash`, `ready` (R — «готов» в гонке, перезапуск забега в Parkour), `nick` (N), `leaderboard` (Tab), `giveup` (G).
`project.godot → [input]`: `move_forward/back/left/right`, `jump`, `sprint`, `crouch`, `dash`, `ready` (R — «готов» в гонке, перезапуск забега в Parkour), `nick` (N), `leaderboard` (Tab), `giveup` (G). Действия, которых нет в `project.godot`, добавляет `core/settings.gd` кодом при старте: `pause` (Esc, Start), `zoom` (LT, R3), `look_left/right/up/down` (правый стик) и все кнопки геймпада.
| Клавиша | Действие |
|---|---|
@@ -73,9 +73,25 @@ godot --path . # можно запустить несколько ок
| N | ввод/смена ника (панель по центру; Enter — подтвердить, Esc — пропустить/отмена); на время ввода игрок стоит |
| Tab | таблица лидеров текущей карты (топ-10 и «Вы: N-й»); в хабе и на картах без рейтинга — вкладки по картам, A/D или стрелки; повторный Tab или Esc закрывают |
| ЛКМ (зажать) | зум |
| Esc / клик | отпустить / захватить мышь |
| Esc | **меню паузы** (мышь освобождается); «Продолжить» или повторный Esc — назад в игру и захват мыши |
| клик по игре | захватить мышь |
Бег по стене — в воздухе у стены с зажатым «вперёд» на скорости. Ctrl не используется: в браузере `Ctrl+W` закрывает вкладку.
**Геймпад Xbox** (правый большой палец всегда на стике обзора, поэтому прыжок продублирован на LB, а рывок на RB):
| Кнопка | Действие |
|---|---|
| Левый стик / правый стик | движение / обзор (кривая 1,6: точно у центра, быстро на краю; скорость — в настройках) |
| A или LB | прыжок (у уступа — подтянуться, у стены — от стены, в воздухе — двойной) |
| RT или L3 | спринт (держать) |
| X или RB | рывок |
| B (держать) | присед; **RT + B на бегу** — подкат |
| LT или R3 | зум |
| Y | «готов» в Race; забег заново в Parkour |
| Back | таблица лидеров (Tab) |
| Крестовина вниз (держать 1,5 с) | сдаться в гонке |
| Start | меню паузы (в меню: крестовина/левый стик, A — выбрать, B — назад) |
Ник по геймпаду меняется в меню паузы. Бег по стене — в воздухе у стены с зажатым «вперёд» на скорости. Ctrl не используется: в браузере `Ctrl+W` закрывает вкладку.
## Структура проекта
@@ -88,6 +104,8 @@ net/ сеть. Net — автолоад: и клиент, и
server.tscn пустая сцена для запуска выделенного сервера
core/
map_loader.gd автолоад MapLoader: скачивает пакет карты и подключает его (см. «Загрузка карт»)
settings.gd автолоад Settings: настройки (user://settings.cfg) и раскладка геймпада в InputMap
pause_menu.gd автолоад PauseMenu: меню паузы Esc/Start (см. «Меню паузы и настройки»)
overlay.gd автолоад Overlay: панель ника (N) и таблица лидеров (Tab) поверх любой карты
lb_view.gd LbView: таблица рейтинга карты (панель Tab, итоги Race/Parkour) и общий стиль панелей
player/
@@ -102,7 +120,7 @@ chasers/
rock/ камень: rock.tscn, Rock.glb (+ извлечённая текстура), Guitar.ogg
verity/ Верити: verity.tscn, verity2.glb (+ текстура), verity.ogg (звук из видео)
maps/ у каждой карты своя папка — она самодостаточна и экспортируется отдельным пакетом
hub/ стартовая комната: hub.tscn, hub.gd (порталы строятся из списка PORTALS)
hub/ стартовая комната: hub.tscn, hub.gd (порталы из списка PORTALS, музыка), hub_decor.gd (оформление), audio/music.ogg + CREDITS.md
sandbox/ песочница: sandbox.tscn, forest.gd, birds.gd, levitate.gd, nav_bake.gd,
floor/ sky/ audio/ models/ (здания, башня, обелиск, деревья, Эмпайр-стейт…)
race/ race.tscn, race.gd, race_rules.gd (правила гонки, сдача, итоги, рейтинг — **общие с Race 2**), race_data.gd (генерируется), baked.gdshader, race.glb, sky.png, audio/music.ogg
@@ -130,7 +148,7 @@ tools/ export_all.sh, serve_web.py, deploy_server.sh, test/ (
| Карта | Сцена | Пакет | Что там |
|---|---|---|---|
| Хаб | `maps/hub/hub.tscn` | в основном пакете | Комната 28×18×7 м, строится кодом (пол-грид, стены, свет). Порталы в ряд по центру, влезает 6. Над порталами карт «на время» — доски с топ-3 (см. «Ники и рейтинг»). Безопасна, преследователей нет |
| Хаб | `maps/hub/hub.tscn` | в основном пакете | «Лобби»: зал 48×32×10 м, строится кодом (`hub.gd` — стены, порталы, доски, музыка; `hub_decor.gd` — оформление). Порталы в ряд у северной стены с шагом 6 м (влезает 7; SANDBOX `x=-12`, RACE 2 `x=12`, `z=-15`), игрок появляется на `(0, 1.2, 11)`. В центре платформа с вращающейся голограммой, пол с латунными кольцами и дорожкой к порталам, 6 колонн с неоновыми прорезями, потолочные светильники (свечение — `glow`), в боковых стенах шесть окон с ночным городом (шейдер), лавки (на них можно запрыгнуть), пылинки в воздухе, табло «ЛОББИ» на южной стене. Над порталами карт «на время» — доски с топ-3 (см. «Ники и рейтинг»). Музыка `maps/hub/audio/music.ogg` («Local Forecast - Elevator», Kevin MacLeod, CC-BY) играет по кругу, плавно нарастая за 3 с, −9 дБ. Безопасна, преследователей нет |
| Песочница | `maps/sandbox/sandbox.tscn` | `world.pck` | Киберпанк-мир: пол-шахматка, здания, 60 деревьев (MultiMesh), птицы, парящий обелиск, звук `tron_01`. Преследователи: **камень** и **Верити**. Портал «HUB» возвращает в хаб |
| Backrooms | `maps/backrooms/backrooms.tscn` | `backrooms.pck` | Модель «Backrooms VR» (×1,4). Преследователь: **Верити** (масштаб 0,5). Выход «EXIT» в дальнем конце ведёт в хаб. Гул ламп генерируется кодом |
| Parkour | `maps/parkour/parkour.tscn` | `parkour.pck` (7,4 МБ: небо 3,5 + модель 3,4 + музыка 1,1) | Мрачная антиутопия в духе Ghostrunner: дождь, дымный воздух, грязный мокрый бетон, натриевый оранжевый, тревожный красный и больной зелёный свет, надписи-приказы (COMPLY, CURFEW 22:00, RESTRICTED). **Забег на время** (старт — линия на краю стартовой платформы, финиш — вершина; рейтинг на сервере; R — заново). Подъём по мегабашне, ~700 м, 9 чекпоинтов (светящиеся ворота), без преследователей. Секции: крыши (одинарный/двойной прыжок, подтягивание) → каньон из четырёх стен для бега → башня из 9 уступов (двойной прыжок + подтягивание) → лазерный зал (подкат, прыжок, тайминг, рывок) → пропасть из 6 контейнеров (зазоры 16–24 м) → спираль вокруг светящегося ядра (+24 м) → вершина с порталом в хаб. Срыв ниже последнего чекпоинта на 32 м или касание лазера = «СОРВАЛСЯ!» и возрождение на чекпоинте. Музыка: `maps/parkour/audio/music.ogg` (Ogg Vorbis, моно 32 кГц, ~1 МБ; делается `ffmpeg -i исходник.mp3 -ac 1 -ar 32000 -c:a libvorbis -q:a 0 music.ogg`), играет по кругу |
@@ -263,6 +281,16 @@ const MAX_RECORD_TIME := 3600.0
- `parkour_run_test.py` — забег: линия, таймер, смерть, финиш, отказ слишком быстрому времени, R, запись в рейтинге.
- `ui_tour.tscn --mode=hub|race|parkour` — кадры (`--write-movie`; рейтинг подставлен, сервер не нужен; добавляйте `--server-url=ws://127.0.0.1:1`, иначе окно подключится к реальному серверу и затрёт подставленное).
## Меню паузы и настройки
`core/pause_menu.gd` (автолоад `PauseMenu`) + `core/settings.gd` (автолоад `Settings`, объявлен раньше `Overlay`). Меню открывается по **Esc / Start** (действие `pause`), игра при этом идёт дальше (мультиплеер), а игрок стоит: `Net.input_blocked = true`, как при вводе ника; игровые клавиши за меню не работают (меню забирает событие раньше `Overlay`). Закрывается кнопкой «Продолжить», повторным Esc/Start или B; мышь снова захватывается.
- **Главная:** Продолжить · **Выйти в хаб** (только если карта не хаб: `MapLoader.enter("hub", …)`, хаб в основном пакете) · Таблица лидеров · Сменить ник · Настройки · Управление.
- **Настройки** (`user://settings.cfg`, пишется при закрытии меню; кнопка «По умолчанию»): чувствительность мыши ×0,2–3 (к `player.MOUSE_SENSITIVITY`), чувствительность стика ×0,3–2,5 (`Settings.STICK_LOOK_SPEED` = 3,6 рад/с), поле зрения 60–100° (`player.base_fov` берётся из `Settings.fov` каждый кадр), громкость (шина Master), инверсия вертикали (мышь и стик). Слайдеры и кнопки управляются геймпадом через стандартные `ui_*`.
- **Управление:** таблица «клавиатура / геймпад».
- **Esc в браузере:** при захваченной мыши браузер сам снимает захват и событие Esc до игры **не доходит**. Поэтому `PauseMenu._process` открывает меню и по факту «мышь была захвачена ≥ 0,5 с и перестала быть» (если не открыт ввод ника и не идёт загрузка карты); после закрытия 0,6 с это не срабатывает (браузер мог отказать в повторном захвате без клика — тогда клик по игре захватит мышь, как раньше). **В живом браузере не проверялось.**
- Геймпад: обзор правым стиком — `player._process` (кадр за кадром, не в физике), мышь — `player._mouse_look`. Движение стиком аналоговое по направлению, но скорость по-прежнему «шаг/спринт» (`direction` нормализуется), как и раньше с клавиатурой.
- Проверка: `godot --headless --path . res://tools/test/pause_test.tscn -- --client --server-url=ws://127.0.0.1:1` — раскладка геймпада в InputMap, открытие/закрытие, блокировка, чувствительность и инверсия, FOV, обзор стиком, A и RT, сохранение, «Выйти в хаб». Кадры меню и хаба: `hub_tour.tscn` (`--menu=main|settings|controls`).
## Преследователи
`chasers/chaser.gd` — один скрипт для всех. Сцены (`rock.tscn`, `verity.tscn`) — это просто модель + звук + `NavigationAgent3D`.
@@ -314,7 +342,7 @@ const MAX_RECORD_TIME := 3600.0
## Загрузка карт пакетами (веб)
Основной пакет игры (`index.pck`) — только хаб, игрок, сеть и порталы (около 70 КБ). Движок — `index.wasm` (39,5 МБ, ~10 МБ с gzip).
Основной пакет игры (`index.pck`) — только хаб (с музыкой), игрок, сеть, меню и порталы (около 1,6 МБ, из них 1,2 МБ — музыка хаба). Движок — `index.wasm` (39,5 МБ, ~10 МБ с gzip).
Карты — отдельные `.pck`: `world.pck` (13,6 МБ), `backrooms.pck` (21,3 МБ). Портал вызывает `MapLoader.enter(map, scene, pack, title)`:
1. если сцена уже есть в проекте (редактор, десктоп, пакет уже скачан) — переход сразу;
@@ -359,15 +387,16 @@ python3 tools/serve_web.py ../grid-world 8080 # nginx-подобно: COOP/C
godot --headless --path /tmp/ts & # сервер
godot --headless --path /tmp/tp res://maps/sandbox/sandbox.tscn -- --client --name=A &
godot --headless --path /tmp/tp res://maps/sandbox/sandbox.tscn -- --client --name=B
# цепочка карт на реальных пакетах (портал SANDBOX в хабе на (-2.25, -7.5), BACKROOMS на (2.25, -7.5)):
# цепочка карт на реальных пакетах (порталы хаба в ряд на z=-15 с шагом 6 м: SANDBOX x=-12, BACKROOMS x=-6; в `--tp` ниже — SANDBOX):
/tmp/tp/tools/export_all.sh /tmp/site && (cd /tmp/site && python3 -m http.server 8777 --bind 127.0.0.1 &)
godot --headless --main-pack /tmp/site/index.pck -- --client --name=T --pack-url=http://127.0.0.1:8777/ --tp=2:-2.25,1,-7.5
godot --headless --main-pack /tmp/site/index.pck -- --client --name=T --pack-url=http://127.0.0.1:8777/ --tp=2:-12,1,-15
```
Для картинок: `godot --path . --resolution 1152x648 --fixed-fps 10 --write-movie /tmp/shots/a.png --quit-after 25 res://maps/hub/hub.tscn` (окно мелькнёт; кадры — `a00000020.png`).
В браузере: Chrome (flatpak `com.google.Chrome`) `--headless=new --enable-logging=stderr --v=0 http://127.0.0.1:8080` — вывод Godot виден в строках `CONSOLE`.
**Готовые проверки** (`tools/test/`, запускаются как сцены: в режиме `--script` автозагрузки недоступны при компиляции, поэтому только `res://…tscn`; `-- --client`, иначе headless поднимет сервер на порту 9080):
- Race 2: `MAP=race2 tools/test/race_game_test.sh` (правила, см. «Карта Race 2»); боты проходимости — `Blender models/race_02/tests/` (`run.sh`, `run_all.sh`, `compare.sh`, `frames.sh`); пакет через портал хаба — `tools/test/race2_check.txt`.
- `pad_menu_test.tscn` — геймпад в меню (фокус, крестовина, A); `pause_test.tscn` — меню паузы, настройки, геймпад (см. «Меню паузы и настройки»); `hub_tour.tscn` — кадры хаба и меню паузы.
- `measure_movement.tscn` — замеры мувсета (прыжки, рывок, стена); `mantle_test.tscn` — подтягивание на 40 вариантах уступов; `parkour_gaps.tscn` — проходимость контейнеров; `parkour_tour.tscn` — облёт карты со снимками (см. заголовок файла).
- **Проверяй по существу, а не по имени сцены.** Для карт из пакетов: собери тестовый проект (`make_test_project.sh`), в его `bot.gd` добавь печать фактов (есть ли у `current_scene` скрипт, подменён ли материал, есть ли `PanoramaSkyMaterial`, играет ли музыка, сколько лазеров) и пройди портал с `--pack-url`. Готовый код проверки — `tools/test/parkour_check.txt` (ловит пропавшие `sky.png`/шейдер/музыку/логику).
- Ввод ботом: `Input.action_press("jump")` работает для зажатия и `is_action_pressed`; рывок и подкат ловятся в `_unhandled_input`, поэтому для них нужно `Input.parse_input_event(InputEventAction)` с `pressed=true`.
@@ -520,6 +549,8 @@ ssh root@192.168.10.110 'journalctl -u my-world -f' # лог: «+ игрок
## Журнал изменений (окт 2026)
Последнее (31 окт 2026): геймпад Xbox, меню паузы с выходом в хаб и настройками, увеличенный и оформленный хаб с музыкой. Подробности — «Управление», «Меню паузы и настройки», «Карты и порталы». Выкладка сервера **не нужна** (`net/*` не менялся).
Сделано одной серией работ (хронологически):
1. **Персонаж:** модель киберниндзя со скелетом (752 треугольника, 14 анимаций, IK ног) вместо капсул; цвет свечения от id игрока; свой персонаж спрятан от своей камеры. Сальто камеры при двойном прыжке делалось и убрано по просьбе.
2. **Подтягивание на уступы** починено (не работало от ~2 м на всех картах), замеры мувсета и тестовые сцены в `tools/test/`.
@@ -536,4 +567,5 @@ ssh root@192.168.10.110 'journalctl -u my-world -f' # лог: «+ игрок
- Модель карты Backrooms — «Backrooms VR», автор VTX (https://sketchfab.com/VTX_car), **CC-BY 4.0** (`maps/backrooms/model/CREDITS.md`).
При публикации нужно указывать автора.
- Музыка хаба — «Local Forecast - Elevator», Kevin MacLeod (https://incompetech.com), **CC-BY 4.0** (`maps/hub/audio/CREDITS.md`). При публикации нужно указывать автора.
- Остальные модели и звуки — материалы владельца проекта.