Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Создание вашего первого скрипта
В этом уроке вы напишете свой первый скрипт для вращения иконки 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 узла.
Примечание
По умолчанию, Inspector отображает свойства узла в "Title Case", т.е. заглавными буквами, а слова разделяются пробелами. В GDScript эти свойства записываются в "snake_case", строчными буквами, а слова разделяются подчеркиваниями.
Вы можете навести курсор на имя любого свойства в 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;
}
}