Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

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

В этом уроке вы напишете свой первый скрипт для вращения иконки Godot кругами, используя GDScript. Как мы упоминали во Введении, этот урок рассчитан на тех, кто обладает базовыми знаниями в программировании. Для удобства, в другой вкладке приведен код C#.

../../_images/scripting_first_script_rotating_godot.gif

См.также

Подробнее о GDScript, его ключевых словах и синтаксисе, читайте в Основы GDScript.

См.также

За дополнительно информацией по C#, обратитесь к странице: Основы C#.

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

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

Нам нужно создать узел 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 нужна текстура для отображения. В Инспекторе справа вы можете увидеть, что в свойстве текстуры указано "[пусто]". Чтобы отобразить иноку Godot, кликните и перетащите файл ``icon.png``из файловой системы панели на слот текстуры.

../../_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 (Шаблон) с Default на Empty, чтобы начать с чистого файла. Оставьте остальные параметры по умолчанию и нажмите кнопку Create (Создать), чтобы создать скрипт.

../../_images/scripting_first_script_attach_node_script.webp

Примечание

C# script names need to match their class name. In this case, you should name the file MySprite2D.cs.

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

extends Sprite2D

Каждый файл GDScript неявно является классом. Ключевое слово extends определяет класс, который наследует или расширяет данный скрипт. В этом случае Sprite2D означает, что наш скрипт получит доступ к свойствам и функциям узла Sprite2D, включая классы, которые он расширяет, такие как Node2D, CanvasItem и Node.

Примечание

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

К унаследованным свойствам относятся те, которые вы можете видеть в инспекторе, например, texture узла.

Примечание

По умолчанию, Инспектор отображает свойства узла в "Title Case", с заглавными буквами вначале, разделенные пробелом. В GDScript эти свойства записываются в "snake_case", строчными буквами, разделенными подчёркиванием.

You can hover over any property's name in the Inspector to see a description and its identifier in code.

Привет, мир!

Наш скрипт ничего не делает. Давайте заставим его вывести "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 (например, Sprite), Godot будет вызывать её каждый кадр и передавать в аргументе delta время, прошедшее от предыдущего кадра.

Примечание

Игры работают в цикле, отображая множество изображений в секунду, каждое из которых называется кадром. Скорость, с которой игра создаёт эти изображения, измеряется в кадрах в секунду (Frame Per Second). Большинство игр нацелены на 60 FPS, хотя вы можете найти такие цифры, как 30 кадров в секунду на более медленных мобильных устройствах или от 90 до 240 для игр виртуальной реальности.

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

В нижней части скрипта определите функцию:

func _process(delta):
    rotation += angular_speed * delta

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

Примечание

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

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

Совет

В редакторе кода вы можете нажать Ctrl+ЛКМ на любом встроенном свойстве или функции, таких как position, rotation, или _process, чтобы открыть соответствующую документацию в новой вкладке.

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

../../_images/scripting_first_script_godot_turning_in_place.gif

Примечание

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

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

Let's now make the node move. Add the following two lines inside of the _process() function, ensuring the new lines are indented the same way as the rotation += angular_speed * delta line before them.

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 игра вы узнаете другой подход к перемещению объектов с обнаруженем столкновений.

Our node currently moves by itself. In the next part, Отслеживание ввода игрока, we'll use player input to control it.

Готовый скрипт

Here is the complete sprite_2d.gd file for reference.

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