Отслеживание ввода игрока
Основываясь на предыдущем уроке Создание вашего первого скрипта, давайте рассмотрим еще одну важную особенность любой игры: предоставление контроля игроку. Чтобы добавить это, нам нужно изменить наш код sprite_2d.gd.
У вас есть два важных инструмента для обработки пользовательского ввода в Godot:
Встроенные обратные вызовы ввода, в основном
_unhandled_input(). Подобно функции_process()функция_unhandled_input()— это встроенная виртуальная функция, которую Godot вызывает каждый раз, когда игрок нажимает клавишу. Это инструмент, который вы захотите использовать, чтобы реагировать на события, которые не происходят каждый кадр, например, нажатие Space для прыжка. Чтобы узнать больше об обратных вызовах ввода, посмотрите Использование InputEvent.Синглтон
Input. Синглтон - это глобально доступный объект. Godot предоставляет доступ к нескольким из них в скриптах. Это подходящий инструмент для проверки ввода в каждом кадре.
Здесь мы будем использовать синглтон Input, поскольку нам нужно знать в каждом кадре, хочет ли игрок поворачиваться или двигаться.
Для поворота нам стоит использовать новую переменную: direction. В нашей функции _process() замените строку rotation += angular_speed * delta на приведенный ниже код.
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
Наша локальная переменная direction - это множитель, представляющий собой направление, в котором игрок хочет повернуть. Значение 0 означает, что игрок не нажимает ни стрелку влево, ни стрелку вправо. Значение 1 говорит, что игрок хочет повернуть вправо, а -1 - что игрок хочет повернуть влево.
To produce these values, we introduce conditional statements and the use of Input.
A conditional statement starts with the if keyword in GDScript and ends with a colon. The
condition is specifically the expression between the keyword and the colon at
the end of the line.
Чтобы проверить, была ли нажата клавиша в этом кадре, мы вызываем Input.is_action_pressed(). Метод принимает текстовую строку, представляющую действие ввода, и возвращает true, если клавиша нажата, и false в противном случае.
Два действия, которые мы использовали выше, «ui_left» и «ui_right», предопределены в каждом проекте Godot. Они соответственно срабатывают, когда игрок нажимает стрелки влево и вправо на клавиатуре или же влево и вправо на крестовине геймпада.
Примечание
Вы можете просматривать и редактировать действия ввода в своем проекте, перейдя в Проект -> Настройки проекта и щелкнув вкладку Список действий.
Наконец, мы используем direction как множитель, когда обновляем rotation узла: rotation += angular_speed * direction * delta.
Закомментируйте строки var velocity = Vector2.UP.rotated(rotation) * speed и position += velocity * delta следующим образом:
#var velocity = Vector2.UP.rotated(rotation) * speed
#position += velocity * delta
//var velocity = Vector2.Up.Rotated(Rotation) * _speed;
//Position += velocity * (float)delta;
Это игнорирует код, который перемещал иконку по кругу без ввода пользователя из предыдущего упражнения.
Если запустить сцену с этим кодом, иконка должна вращаться при нажатии Влево и Вправо.
Перемещение при нажатии "вверх"
Чтобы двигаться только при нажатии клавиши, нам нужно изменить код, который вычисляет скорость. Замените строку, начинающуюся с var velocity, на приведенный ниже код.
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Мы инициализируем velocity со значением Vector2.ZERO, еще одной константой встроенного типа Vector, представляющей двумерный вектор нулевой длины.
Когда игрок выполняет действие "ui_up", мы обновляем значение скорости, заставляя спрайт двигаться вперёд.
Готовый скрипт
Это полный файл sprite_2d.gd для справки.
extends Sprite2D
var speed = 400
var angular_speed = PI
func _process(delta):
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
public partial class MySprite2D : Sprite2D
{
private float _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Position += velocity * (float)delta;
}
}
Если вы запустите сцену, вы должны иметь возможность вращаться с помощью стрелок влево и вправо, а также двигаться нажатием Вверх.
Подведение итогов
В общем, каждый скрипт в Godot представляет собой класс и расширяет один из встроенных классов движка. Типы узлов, от которых наследуются ваши классы, дают вам доступ к таким свойствам, как rotation и position в случае нашего спрайта. Вы также наследуете множество функций, которые мы не использовали в этом примере.
В GDScript переменные, которые вы помещаете в верхней части файла, являются свойствами вашего класса, также называемыми переменными класса. Кроме переменных, вы можете определять функции, которые, по сути, являются методами ваших классов.
Godot предоставляет несколько виртуальных функций, которые вы можете определить для связи вашего класса с движком. К ним относятся _process(), применяющая изменения к узлу каждый кадр, и _unhandled_input(), получающая события ввода, такие как нажатие клавиш и кнопок от пользователей. Есть еще множество других функций.
Синглтон Input позволяет вам реагировать на ввод от игрока в любом месте вашего кода. В первую очередь вы сможете применить его в цикле _process().
В следующем уроке Использование сигналов мы будем изучать на отношения между скриптами и узлами, наблюдая за тем как код приводит в действие узлы.