ci / release (push) Successful in 5m5s
ci-platforms / build (amd64, windows, windows-2022) (push) Skipped
ci-platforms / build (arm64, darwin, macos-15) (push) Skipped
ci-platforms / build (amd64, darwin, macos-15-intel) (push) Skipped
ci / checks (push) Successful in 4m41s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 7m14s
The remaining editor strings and undo step names; component, field, enum, setting, diagnostic and Script API texts under schema.*, enum.*, setting.*, diag.* and api.*; the launcher, the in-game Settings View with a Language setting, the CLI and aego schema show --lang. Every documentation page has a .ru.md translation; the site has a full Russian tree with hreflang, a language switch and ru/llms.txt; aego docs check --lang ru. New doc.tutorial and doc.recipe icons. Fix: an animator restored by a rewind prepares its controller before the replayed step.
138 lines
8.4 KiB
Markdown
138 lines
8.4 KiB
Markdown
---
|
||
id: input
|
||
title: Ввод
|
||
---
|
||
# Ввод
|
||
|
||

|
||
|
||
Игры читают **действия**, а не клавиши. У действия есть имя, тип и привязки; один и тот же скрипт работает с клавиатурой и с геймпадом.
|
||
|
||
## Действия
|
||
|
||
input version=2 {
|
||
stack=[Gameplay]
|
||
action {
|
||
name=Move
|
||
type=axis1
|
||
bind=["Key.A/Key.D", "Key.Left/Key.Right", "Pad.LeftX"]
|
||
}
|
||
action {
|
||
name=Jump
|
||
type=button
|
||
buffer=0.1
|
||
bind=["Key.Space", "Pad.A"]
|
||
}
|
||
context {
|
||
name=Gameplay
|
||
actions=[Move, Jump]
|
||
}
|
||
}
|
||
|
||
Типы: `button`, `axis1`, `axis2`, `pointer`, `pointerDelta`.
|
||
|
||
Привязка — это один элемент управления или составная привязка:
|
||
|
||
| Форма | Пример |
|
||
|---|---|
|
||
| один элемент | `Key.Space`, `Mouse.Left`, `Pad.A`, `Pad.LT` |
|
||
| минус/плюс | `Key.A/Key.D` |
|
||
| вверх/вниз/влево/вправо | `Key.W/Key.S/Key.A/Key.D` |
|
||
| стик | `Pad.LeftStick` |
|
||
| аккорд | `Key.Z+Key.S` |
|
||
|
||
Параметры идут после элемента: `invert`, `scale=2`, `deadzone=0.3`.
|
||
|
||
- Кнопки геймпада: `A B X Y Back Guide Start L3 R3 LB RB DPadUp DPadDown DPadLeft DPadRight`.
|
||
- Оси геймпада: `LeftX LeftY RightX RightY LT RT`.
|
||
- У `axis2` ось Y направлена вниз, как в 2D-мире.
|
||
- У стика мёртвая зона радиальная, у одиночной оси — осевая. По умолчанию `deadzone=0.2`.
|
||
|
||
`interaction` меняет момент срабатывания кнопки: `press` (по умолчанию), `release`, `hold`, `tap`, `doubleTap`, `toggle`. `time` задаёт окно в секундах.
|
||
|
||
## Контексты
|
||
|
||
Контекст — именованный набор действий. Стек решает, что читается: сначала больший `priority`, затем последний добавленный.
|
||
|
||
- Контекст с `consume=true` перехватывает ввод: прячет свои элементы управления от контекстов ниже. Меню с `Back` на Escape не даёт сработать `Pause` на Escape.
|
||
- Переключение контекстов не посылает ложных Pressed или Released. `release=true` у контекста посылает Released для его удерживаемых действий, когда он уходит со стека.
|
||
|
||
## Кадры и фиксированные шаги
|
||
|
||
`Pressed` в `Update` истинно один кадр. В `FixedUpdate` оно истинно в первом фиксированном шаге после нажатия.
|
||
|
||
- Короткое нажатие между двумя фиксированными шагами всё равно даёт ровно один `Pressed`, а за ним один `Released`.
|
||
- `Held` истинно в каждом шаге кадра.
|
||
- Потеря фокуса окна или геймпада отпускает все удерживаемые действия в том же шаге. `input.DeviceChanged()` истинно в этом кадре.
|
||
|
||
## Скрипты
|
||
|
||
import "aego/input"
|
||
|
||
func FixedUpdate(dt float) {
|
||
x := input.Axis("Move")
|
||
if grounded && input.Buffered("Jump", 0) {
|
||
input.Consume("Jump")
|
||
jump()
|
||
}
|
||
}
|
||
|
||
| Функция | |
|
||
|---|---|
|
||
| `Pressed Released Held(action) bool` | состояние действия |
|
||
| `Axis(action) float` | значение оси |
|
||
| `Axis2(action) Vec2` | значение 2D-действия |
|
||
| `Buffered(action, window) bool`, `Consume(action)` | буфер нажатий |
|
||
| `PushContext PopContext SetContext` | стек контекстов |
|
||
| `PressedP ReleasedP HeldP AxisP Axis2P(player, action)` | для каждого игрока |
|
||
| `ActiveDevice() int`, `DeviceChanged() bool`, `Glyph(action) string` | устройства и подсказки |
|
||
| `BeginRebind(action, slot) bool`, `Rebinding()`, `RebindConflict()`, `ResetBinding`, `ResetBindings`, `SaveBindings` | меню |
|
||
|
||
Переназначения и настройки обзора — настройки игрока: они сохраняются в профиле игрока; старый `user://input.aetext` импортируется один раз.
|
||
|
||
Прямые клавиши (`Down`, `KeyPressed`, `KeyReleased`, `MouseDown`, `MousePressed`, `MousePos`, `MouseWorld`) остаются для прототипов. Не выпускайте игру с ними.
|
||
|
||
## Игроки
|
||
|
||
`players=2` даёт каждому игроку своё состояние действий.
|
||
|
||
- Клавиатура и мышь принадлежат игроку 0.
|
||
- Геймпад при первом нажатии достаётся первому игроку без устройства.
|
||
- В Go `Assign(player, device)` закрепляет соответствие.
|
||
|
||
## Запись и тесты
|
||
|
||
s := sdk.Actions(world)
|
||
s.Inject(40, "Jump", 1)
|
||
s.Inject(43, "Jump", 0)
|
||
s.Record(input.RecordMeta{Project: "mygame", FixedHz: 60})
|
||
data := s.StopRecording()
|
||
s.Replay(data)
|
||
|
||
Повтор заменяет все устройства. С той же сценой, зерном, настройками физики и фиксированным шагом повтор воспроизводит запуск бит в бит.
|
||
|
||
## Действия из модулей
|
||
|
||
Модуль добавляет свои действия и контексты, не импортируя модуль ввода:
|
||
|
||
sdk.ProvideInputActions(r, sdk.InputActionSet{
|
||
Actions: []sdk.InputAction{{Name: "Kick", Type: "button", Bindings: []string{"Key.K", "Pad.Y"}}},
|
||
Contexts: []sdk.InputContext{{Name: "Combat", Actions: []string{"Kick"}, Default: true}},
|
||
})
|
||
|
||
Как действия модулей сочетаются с проектом:
|
||
|
||
- Действие или контекст проекта с тем же именем побеждает.
|
||
- Контекст с пометкой `Default` входит в стартовый стек.
|
||
- Действия модулей не появляются на странице настроек; файл проекта показывает только то, что объявляет сам.
|
||
|
||
## Редактор
|
||
|
||
- **Настройки проекта → Ввод** редактирует действия, привязки, контексты и стартовый стек. Чтобы назначить элемент управления, щёлкните по нему, затем нажмите клавишу, кнопку мыши (не левую), кнопку геймпада или сдвиньте стик; Escape отменяет. Элементы, привязанные к двум действиям одного контекста, красные, а подсказка называет другое действие.
|
||
- **Устройства ввода** перечисляет клавиатуру, мышь и геймпады, показывает живые значения действий во время игры и содержит виртуальный геймпад: кнопки и два стика, которые вы двигаете мышью.
|
||
- **Фокус ввода** показывает стек контекстов и для каждого действия — контекст, через который оно прочитано, и перехвативший контекст, который его заблокировал.
|
||
|
||
В редакторе Escape уходит в игру, поэтому меню паузы работают в игре. **Shift+Esc** или щелчок вне панели «Игра» возвращают ввод редактору; это команда «Отпустить ввод игры», её привязку можно изменить в «Сочетаниях клавиш».
|
||
|
||
`Inject(0, action, v)` действует со следующего кадра. Используйте его, пока игровое время на паузе или его масштаб равен 0, когда фиксированные шаги не идут.
|