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#.
См.также
Подробнее о GDScript, его ключевых словах и синтаксисе, читайте в Основы GDScript.
См.также
За дополнительно информацией по C#, обратитесь к странице: Основы C#.
Настройка проекта¶
Пожалуйста, создайте новый проект, чтобы начать с чистого листа. Ваш проект должен содержать одно изображение: иконку Godot, которую мы в сообществе часто используем для прототипирования.
Нам нужно создать узел Sprite2D для отображения в игре. В панели Сцена (Scene), кликните на кнопку Другой Узел (Other Node).
Наберите "Sprite2D" в поисковой строке, чтобы отобразились нужные узлы, затем дважды кликните на Sprite2D, чтобы создать узел.
Вкладка Сцена (Scene) теперь должна содержать только узел Sprite2D.
Узлу Sprite2D нужна текстура для отображения. В Инспекторе справа вы можете увидеть, что в свойстве текстуры указано "[пусто]". Чтобы отобразить иноку Godot, кликните и перетащите файл ``icon.png``из файловой системы панели на слот текстуры.
Примечание
Также вы можете создавать узлы Sprite2D автоматически, перетаскивая изображения в Окно просмотра.
Затем нажмите и перетащите значок в окне просмотра, чтобы отцентрировать его в игровом представлении.
Создание нового скрипта¶
Чтобы создать и прикрепить новый скрипт к нашему узлу, нажмите правой кнопкой мыши на Sprite2D в панели сцены и выберите "Прикрепить Скрипт" (Attach Script).
Откроется окно "Прикрепить скрипт" (Attach Node Script). В этом окне вы можете указать язык программирования скрипта, путь в корневой папке и другие параметры.
Измените Template (Шаблон) с Default на Empty, чтобы начать с чистого файла. Оставьте остальные параметры по умолчанию и нажмите кнопку Create (Создать), чтобы создать скрипт.
Примечание
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
using Godot;
public partial class MySprite2D : 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!")
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
(например, Sprite
), Godot будет вызывать её каждый кадр и передавать в аргументе delta
время, прошедшее от предыдущего кадра.
Примечание
Игры работают в цикле, отображая множество изображений в секунду, каждое из которых называется кадром. Скорость, с которой игра создаёт эти изображения, измеряется в кадрах в секунду (Frame Per Second). Большинство игр нацелены на 60 FPS, хотя вы можете найти такие цифры, как 30 кадров в секунду на более медленных мобильных устройствах или от 90 до 240 для игр виртуальной реальности.
Движок и разработчики игры делают все возможное, чтобы обновлять игровой мир и рендерить изображения с постоянным интервалом времени, но всегда существуют небольшие отклонения во времени рендеринга кадров. Поэтому движок предоставляет нам это значение дельта-времени, делая наше движение независимым от частоты кадров.
В нижней части скрипта определите функцию:
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+ЛКМ на любом встроенном свойстве или функции, таких как position
, rotation
, или _process
, чтобы открыть соответствующую документацию в новой вкладке.
Запустите сцену, чтобы увидеть, что иконка Godot крутится на месте.
Примечание
Заметьте, что в 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 = 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 игра вы узнаете другой подход к перемещению объектов с обнаруженем столкновений.
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
using Godot;
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;
}
}