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.

Создание вашего первого скрипта

В этом уроке вы напишете свой первый скрипт для вращения иконки Godot кругами. Как мы упоминали in the introduction, мы предпологаем, что у вас есть основы программирования.

Этот учебник написан для GDScript, а эквивалентный код C# включен в другую вкладку каждого блока кода для удобства.

../../_images/scripting_first_script_rotating_godot.gif

См. также

Чтобы узнать больше о GDScript, его ключевых словах и синтаксисе, перейдите в раздел GDScript. Чтобы узнать больше о C#, перейдите в раздел C#/.NET.

Настройка проекта

Пожалуйста, создайте новый проект, чтобы начать с чистого листа. Ваш проект должен содержать одно изображение: иконку Godot, которую мы в сообществе часто используем для прототипирования.

../../_images/scripting_first_script_icon.svg

Нам нужно создать узел Sprite2D для отображения в игре. В доке Scene нажмите кнопку Other Node.

../../_images/scripting_first_script_click_other_node.webp

Наберите "Sprite2D" в поисковой строке, чтобы отобразились нужные узлы, затем дважды кликните на Sprite2D, чтобы создать узел.

../../_images/scripting_first_script_add_sprite_node.webp

Вкладка Сцена Scene теперь должна содержать только узел Sprite2D.

../../_images/scripting_first_script_scene_tree.webp

Для отображения узла Sprite2D требуется текстура. В Inspector справа вы видите, что свойство Texture имеет значение <empty>. Чтобы отобразить значок Godot, щёлкните и перетащите файл icon.svg из дока FileSystem в слот Texture.

../../_images/scripting_first_script_setting_texture.webp

Примечание

Также вы можете создавать узлы Sprite2D автоматически, перетаскивая изображения в окно просмотра.

Затем нажмите и перетащите значок в окне просмотра, чтобы отцентрировать его в игровом представлении.

../../_images/scripting_first_script_centering_sprite.webp

Создание нового скрипта

Чтобы создать и прикрепить новый скрипт к нашему узлу, щелкните правой кнопкой мыши Sprite2D в доке сцены и выберите Attach Script.

../../_images/scripting_first_script_attach_script.webp

Откроется окно Attach Node Script. В нём можно выбрать язык скрипта и путь к файлу, а также другие параметры.

Измените значение поля Template с Node: Default на Object: Empty, чтобы начать с чистого файла. Оставьте остальные параметры по умолчанию и нажмите кнопку Create, чтобы создать скрипт.

../../_images/scripting_first_script_attach_node_script.webp

Примечание

Названия скриптов C# должны совпадать с названием класса. В этом случае, вы должны назвать файл MySprite2D.cs.

В рабочей области Script должен появиться новый файл sprite_2d.gd и следующая строка кода:

extends 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!")

Давайте разберём это. Слово func объявляет новую функцию _init. Это конструктор нашего класса. Движок вызывает _init при создании объекта в памяти, если вы определили эту функцию.

Примечание

GDScript - язык с отступами. Отступ (табуляция) в начале строки print() обязателен для работы кода. Если вы пропустите отступ или отступите неправильно, редактор выделит строку красным и выведет сообщение:"Indented block expected" ("Блок отступа пропущен").

Сохраните сцену как sprite_2d.tscn, если ещё не сделали этого, затем нажмите F6 (Cmd + R на macOS) для запуска. Посмотрите в окно Output в панели внизу. Там должно отобразится "Hello, world!".

../../_images/scripting_first_script_print_hello_world.webp

Удалите функцию _init(), оставив только строку extends Sprite2D.

Поворот вокруг

Пришло время заставить наш узел двигаться и вращаться. Для этого добавим в скрипт две переменные-члены: скорость движения в пикселях в секунду и угловую скорость в радианах в секунду. Добавьте следующее после строки extends Sprite2D.

var speed = 400
var angular_speed = 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

Ключевое слово func определяет (создаёт) новую функцию. После него нужно написать имя функции и в скобках аргументы, которые она принимает. Двоеточие завершает определение, а следующие за ним блоки с отступом представляют собой содержимое или инструкции функции.

Примечание

Обратите внимание, что _process(), как и _init(), начинается с символа подчёркивания. По соглашению, виртуальные функции, то есть встроенные функции Godot, которые вы можете переопределить - начинаются с символа подчёркивания.

Строка внутри функции, rotation += angular_speed * delta, увеличивает угол поворота нашего спрайта каждый кадр. Здесь rotation — это свойство, унаследованное от класса Node2D, который расширяет класс Sprite2D. Он контролирует поворот нашего узла и работает с радианами.

Совет

В редакторе кода вы можете нажать Ctrl + Click (Cmd + Click в macOS) на любом встроенном свойстве или функции, например position, rotation или _process, чтобы открыть соответствующую документацию в новой вкладке.

Запустите сцену, чтобы увидеть, что иконка Godot крутится на месте.

../../_images/scripting_first_script_godot_turning_in_place.gif

Примечание

Заметьте, что в C# аргумент delta, принимаемый _Process() – это double. Поэтому нам нужно конвертировать его в float, когда мы применяем его к углу вращения.

Движение вперёд

Теперь давайте заставим узел двигаться. Добавьте следующие две строки в функцию _process(), убедившись, что новые строки имеют такой же отступ, как и строка rotation += angular_speed * delta.

var velocity = Vector2.UP.rotated(rotation) * speed

position += velocity * delta

Как мы уже видели, ключевое слово var определяет новую переменную. Если вы поместите его в верхней части скрипта, оно определит свойство класса. Внутри функции оно определяет локальную переменную: данная переменная существует только в области действия функции.

Мы определяем локальную переменную velocity, 2D-вектор, представляющий собой направление и скорость. Чтобы заставить узел двигаться вперёд, мы берём константу Vector2.UP класса Vector2, вектор, указывающий вверх, и вращаем его, вызывая метод rotated(). Данное выражение Vector2.UP.rotated(rotation) - вектор, указывающий вперёд относительно нашей иконки. Умноженное на наше свойство speed, это выражение даёт нам скорость, которую мы можем использовать для перемещения узла вперёд.

Мы добавляем velocity * delta к узлу position, чтобы переместить его. Сама позиция имеет тип Vector2, встроенный тип в Godot, представляющий двумерный вектор.

Запустите сцену, чтобы увидеть, что голова Godot движется по кругу.

../../_images/scripting_first_script_rotating_godot.gif

Примечание

При таком перемещении узла не учитываются столкновения со стенами или полом. В Ваша первая 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