Создание вашего первого скрипта
В этом уроке вы напишете свой первый скрипт для вращения иконки Godot кругами. Как мы упоминали in the introduction, мы предпологаем, что у вас есть основы программирования.
Этот учебник написан для GDScript, а эквивалентный код C# включен в другую вкладку каждого блока кода для удобства.
См. также
Чтобы узнать больше о GDScript, его ключевых словах и синтаксисе, перейдите в раздел GDScript. Чтобы узнать больше о C#, перейдите в раздел C#/.NET.
Настройка проекта
Пожалуйста, создайте новый проект, чтобы начать с чистого листа. Ваш проект должен содержать одно изображение: иконку Godot, которую мы в сообществе часто используем для прототипирования.
Нам нужно создать узел Sprite2D для отображения в игре. В доке Scene нажмите кнопку .
Наберите "Sprite2D" в поисковой строке, чтобы отобразились нужные узлы, затем дважды кликните на Sprite2D, чтобы создать узел.
Вкладка Сцена Scene теперь должна содержать только узел Sprite2D.
Для отображения узла Sprite2D требуется текстура. В Inspector справа вы видите, что свойство Texture имеет значение <empty>. Чтобы отобразить значок Godot, щёлкните и перетащите файл icon.svg из дока FileSystem в слот Texture.
Примечание
Также вы можете создавать узлы Sprite2D автоматически, перетаскивая изображения в окно просмотра.
Затем нажмите и перетащите значок в окне просмотра, чтобы отцентрировать его в игровом представлении.
Создание нового скрипта
Чтобы создать и прикрепить новый скрипт к нашему узлу, щелкните правой кнопкой мыши Sprite2D в доке сцены и выберите .
Откроется окно Attach Node Script. В нём можно выбрать язык скрипта и путь к файлу, а также другие параметры.
Измените значение поля Template с Node: Default на Object: Empty, чтобы начать с чистого файла. Оставьте остальные параметры по умолчанию и нажмите кнопку , чтобы создать скрипт.
Примечание
Названия скриптов C# должны совпадать с названием класса. В этом случае, вы должны назвать файл MySprite2D.cs.
В рабочей области Script должен появиться новый файл sprite_2d.gd и следующая строка кода:
extends Sprite2D
using Godot;
using System;
public partial class MySprite2D : Sprite2D
{
}
Каждый файл GDScript неявно является классом. Ключевое слово extends определяет класс, который наследует или расширяет данный скрипт. В этом случае Sprite2D означает, что наш скрипт получит доступ к свойствам и функциям узла Sprite2D, включая классы, которые он расширяет, такие, как Node2D, CanvasItem и Node.
Примечание
В GDScript, если вы опустите строку с ключевым словом extends, ваш класс будет неявно наследоваться от RefCounted, который Godot использует для управления памятью вашего приложения.
К унаследованным свойствам относятся те, которые вы можете видеть в Inspector, например, texture узла.
Примечание
By default, the Inspector displays a node's properties in "Title Case", with capitalized words separated by a space. In GDScript code, these properties are in "snake_case", which is lowercase with each word separated by an underscore.
Вы можете навести курсор на имя любого свойства в Inspector, и увидеть его описание и идентификатор в коде.
Привет, мир!
Наш скрипт ничего не делает. Давайте заставим его вывести "Hello, world!" в панель вывода в нижней части экрана.
Добавьте следующий код в ваш скрипт:
func _init():
print("Hello, world!")
public MySprite2D()
{
GD.Print("Hello, world!");
}
Давайте разберём это. Слово func объявляет новую функцию _init. Это конструктор нашего класса. Движок вызывает _init при создании объекта в памяти, если вы определили эту функцию.
Примечание
GDScript - язык с отступами. Отступ (табуляция) в начале строки print() обязателен для работы кода. Если вы пропустите отступ или отступите неправильно, редактор выделит строку красным и выведет сообщение:"Indented block expected" ("Блок отступа пропущен").
Сохраните сцену как sprite_2d.tscn, если ещё не сделали этого, затем нажмите F6 (Cmd + R на macOS) для запуска. Посмотрите в окно Output в панели внизу. Там должно отобразится "Hello, world!".
Удалите функцию _init(), оставив только строку extends Sprite2D.
Поворот вокруг
Пришло время заставить наш узел двигаться и вращаться. Для этого добавим в скрипт две переменные-члены: скорость движения в пикселях в секунду и угловую скорость в радианах в секунду. Добавьте следующее после строки extends Sprite2D.
var speed = 400
var angular_speed = PI
private int _speed = 400;
private float _angularSpeed = Mathf.Pi;
Переменные располагаются в начале скрипта, после всех строк "extends", но перед функциями. Каждый экземпляр узла с прикреплённым к нему скриптом имеет собственную копию свойств speed и angular_speed.
Примечание
Углы в Godot по умолчанию задаются в радианах, как и в некоторых других движках, но вы можете использовать встроенные функции и свойства для работы с градусами.
Для перемещения иконки мы должны обновлять её позицию и вращение каждый кадр игрового цикла. Для этого используем виртуальную функцию _process() класса Node. При объявлении этой функции в любом классе, наследуемом от Node (например, Sprite2D), Godot будет вызывать её каждый кадр и передавать в аргументе delta время, прошедшее с предыдущего кадра.
Примечание
Игры работают в цикле, отображая множество изображений в секунду, каждое из которых называется кадром. Скорость, с которой игра создаёт эти изображения, измеряется в кадрах в секунду (Frame Per Second). Большинство игр нацелены на 60 FPS, хотя вы можете найти игры, с тридцатью кадрами в секунду на более медленных мобильных устройствах или от 90 до 240 для игр виртуальной реальности.
Движок и разработчики игры делают все возможное, чтобы обновлять игровой мир и отрисовывать изображения с постоянным интервалом времени, но всегда существуют небольшие отклонения во времени рендеринга кадров. Поэтому движок предоставляет нам переменную delta, делая наше движение независимым от частоты кадров.
В нижней части скрипта определите функцию:
func _process(delta):
rotation += angular_speed * delta
public override void _Process(double delta)
{
Rotation += _angularSpeed * (float)delta;
}
Ключевое слово func определяет (создаёт) новую функцию. После него нужно написать имя функции и в скобках аргументы, которые она принимает. Двоеточие завершает определение, а следующие за ним блоки с отступом представляют собой содержимое или инструкции функции.
Примечание
Обратите внимание, что _process(), как и _init(), начинается с символа подчёркивания. По соглашению, виртуальные функции, то есть встроенные функции Godot, которые вы можете переопределить - начинаются с символа подчёркивания.
Строка внутри функции, rotation += angular_speed * delta, увеличивает угол поворота нашего спрайта каждый кадр. Здесь rotation — это свойство, унаследованное от класса Node2D, который расширяет класс Sprite2D. Он контролирует поворот нашего узла и работает с радианами.
Совет
В редакторе кода вы можете нажать Ctrl + Click (Cmd + Click в macOS) на любом встроенном свойстве или функции, например position, rotation или _process, чтобы открыть соответствующую документацию в новой вкладке.
Запустите сцену, чтобы увидеть, что иконка Godot крутится на месте.
Примечание
Заметьте, что в C# аргумент delta, принимаемый _Process() – это double. Поэтому нам нужно конвертировать его в float, когда мы применяем его к углу вращения.
Движение вперёд
Теперь давайте заставим узел двигаться. Добавьте следующие две строки в функцию _process(), убедившись, что новые строки имеют такой же отступ, как и строка rotation += angular_speed * delta.
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
var velocity = Vector2.Up.Rotated(Rotation) * _speed;
Position += velocity * (float)delta;
Как мы уже видели, ключевое слово var определяет новую переменную. Если вы поместите его в верхней части скрипта, оно определит свойство класса. Внутри функции оно определяет локальную переменную: данная переменная существует только в области действия функции.
Мы определяем локальную переменную velocity, 2D-вектор, представляющий собой направление и скорость. Чтобы заставить узел двигаться вперёд, мы берём константу Vector2.UP класса Vector2, вектор, указывающий вверх, и вращаем его, вызывая метод rotated(). Данное выражение Vector2.UP.rotated(rotation) - вектор, указывающий вперёд относительно нашей иконки. Умноженное на наше свойство speed, это выражение даёт нам скорость, которую мы можем использовать для перемещения узла вперёд.
Мы добавляем velocity * delta к узлу position, чтобы переместить его. Сама позиция имеет тип Vector2, встроенный тип в Godot, представляющий двумерный вектор.
Запустите сцену, чтобы увидеть, что голова Godot движется по кругу.
Примечание
При таком перемещении узла не учитываются столкновения со стенами или полом. В Ваша первая 2D игра вы узнаете другой подход к перемещению объектов с обнаруженем столкновений.
Наш узел сейчас движется самостоятельно. В следующей части Отслеживание ввода игрока мы будем использовать пользовательский ввод, чтобы контролировать его.
Готовый скрипт
Это полный файл sprite_2d.gd для справки.
extends Sprite2D
var speed = 400
var angular_speed = PI
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
using System;
public partial class MySprite2D : Sprite2D
{
private int _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
Rotation += _angularSpeed * (float)delta;
var velocity = Vector2.Up.Rotated(Rotation) * _speed;
Position += velocity * (float)delta;
}
}