Чтение ввода с клавиатуры
Чтобы персонаж слушался игрока, движок должен превратить нажатые клавиши в понятное направление.
Суть: ты задаёшь действия (вроде move_right) в карте ввода, а в коде спрашиваешь движок, нажаты ли они.
Игра без управления — это мультик. Чтобы персонаж реагировал на игрока, нужно читать ввод. В Godot не принято завязываться на конкретные клавиши прямо в коде. Вместо этого создают действия (actions) в карте ввода (Input Map): например, действие move_right, к которому привязаны и стрелка вправо, и клавиша D, и стик геймпада. В коде ты спрашиваешь не «нажата ли D», а «выполняется ли действие move_right». Это гибко: захотел переназначить клавиши — поправил карту, код трогать не надо.
func _physics_process(delta: float) -> void:
if Input.is_action_pressed("move_right"):
print("идём вправо")
if Input.is_action_pressed("move_left"):
print("идём влево")
# Удобный способ сразу получить вектор направления:
var direction: Vector2 = Input.get_vector(
"move_left", "move_right", "move_up", "move_down")
print(direction)Функция Input.get_vector — настоящая находка. Ты передаёшь ей четыре действия (влево, вправо, вверх, вниз), а она возвращает готовый Vector2 направления. Нажата только вправо — получишь (1, 0). Нажаты вправо и вниз — получишь диагональ. Причём диагональ она уже нормализует, чтобы по диагонали персонаж не бежал быстрее, чем прямо.
Стоит запомнить и про разные виды устройств. Через действия один и тот же код одинаково работает с клавиатурой, мышью, геймпадом и даже сенсорным экраном: ты лишь привязываешь к действию move_right разные входы. Игроку это даёт привычное управление на его устройстве, а тебе — единый код без ветвлений «если клавиатура, то так, а если геймпад, то иначе». Поэтому почти все профессиональные проекты строят управление именно на абстракции действий, а не на конкретных кнопках. Привыкай к этому с самого начала — переучиваться потом будет лень.
Как работает под капотом
Каждый кадр движок собирает состояние всех клавиш и кнопок. Когда ты спрашиваешь is_action_pressed("move_right"), он смотрит, какие физические клавиши привязаны к этому действию, и возвращает true, если хоть одна нажата. get_vector делает это для четырёх действий сразу и собирает из них вектор: правое минус левое по x, нижнее минус верхнее по y.
Смоделируем get_vector на Python. Из четырёх «нажато/не нажато» получаем вектор и нормализуем диагональ.
import math
def get_vector(left, right, up, down):
x = (1 if right else 0) - (1 if left else 0)
y = (1 if down else 0) - (1 if up else 0)
length = math.hypot(x, y)
if length > 0:
x, y = x / length, y / length # нормализация
return (round(x, 2), round(y, 2))
print("Только вправо:", get_vector(False, True, False, False))
print("Вправо + вниз:", get_vector(False, True, False, True))
print("Никуда:", get_vector(False, False, False, False))Та же логика на Python ▶. Обрати внимание на диагональ: без нормализации её длина была бы 1.41, и персонаж летел бы по диагонали быстрее. Нормализация приводит длину к 1.
Стоит держать в уме и игроков с разными привычками. Кто-то ходит на стрелках, кто-то на WASD, кто-то берёт геймпад. Если ты с самого начала привязал к каждому действию несколько входов, все эти игроки получат удобное управление бесплатно, а возможность переназначить клавиши в настройках игры добавляется почти даром. Это часть уважения к игроку: не навязывать ему одну-единственную раскладку, а позволить играть так, как ему привычно. Карта ввода — маленький, но важный шаг к тому, чтобы в твою игру было приятно играть самым разным людям.
Частые ошибки
Самая частая ошибка — забыть создать действия в карте ввода и потом удивляться, что Input.is_action_pressed("move_right") ничего не делает: имя действия должно точно совпадать с тем, что в карте. Вторая — путать is_action_pressed (срабатывает, пока клавиша удержана) и is_action_just_pressed (срабатывает один раз в момент нажатия). Для прыжка нужен второй, для бега — первый. Третья — забывать про нормализацию диагонали, если читаешь клавиши вручную, а не через get_vector.
Best practices
Всегда работай через действия в карте ввода, а не через коды конкретных клавиш — это даёт переназначение и поддержку геймпада бесплатно. Для непрерывных действий (движение) бери is_action_pressed, для одноразовых (прыжок, выстрел) — is_action_just_pressed. Если можешь — используй get_vector: он короче и сам нормализует диагональ.
Итоги: ввод читают через действия в карте ввода, а не через конкретные клавиши. is_action_pressed — для удержания, is_action_just_pressed — для одного нажатия. Input.get_vector сразу даёт нормализованный Vector2 направления из четырёх действий — это лучший способ получить движение в 2D.