Всем привет!

Давненько от меня не было слышно никаких новостей, тем более и повод соответствующий, наконец-таки поделится своими наработками по Godot, и уже аж версии 3!

В этом вводном материале мы рассмотрим сам редактор, базовые элементы и немного затронем скрипты.

Скачать редактор можно как с официального сайта, так и установив через клиент Steam (кому как удобнее).

Я буду использовать версию из Steam, так как она позволяет одновременно работать как с версией 3, так и запускать версию 2.1. Забегая вперёд скажу, что в третьей версии очень многое поменялось, некоторая логика, вызовы в скриптах и т.д. Но обо всём по порядку.

После запуска Godot, вы увидите окошко со списком доступных проектов. Их можно как запустить сразу, нажав кнопку «Запустить», так и открыть в редакторе, соответственно кнопка «Редактировать».

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

После того как вы скачали и распаковали архив в какую-нибудь папку на диске, её нужно подключить к редактору. Нажимаем кнопку «Импорт», указываем путь, и нажимаем «Импортировать и Редактировать», после чего наши демо-проекты появятся в списке доступных.

Так же демо-проекты можно посмотреть, выбрав вкладку «Шаблоны». Выбираем заинтересовавший нас проект, например, «2D Particles Demo». Нажимаем на название, и во вновь открывшемся окне устанавливаем (кнопка «Установить»).

По сути можно сразу посмотреть проект в действии, кнопкой «Запустить». Однако может быть ситуация, как с «2D Particles Demo», когда для просмотра нужно его сначала всё-так открыть в редакторе для импорта некоторых компонентов.

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

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

После создания проекта, у нас откроется сам редактор. Он состоит из нескольких блоков: Блок «Файловая система» — здесь располагаются блок навигации (дерево папок) и собственно все файлы нашего проекта; Блок «Сцена» — это структура (дерево) всех наших элементов на текущей сцене; Блок «Инспектор» — позволяет редактировать свойства и параметры выбранного элемента в дереве блока «Сцена».

Ещё есть блоки «Импорт» и «Узел», но мы пока рассматривать их не будем.

По центру расположен сам редактор, в зависимости от того что мы хотим редактировать он может отображать 2D-сцену, 3D-сцену, редактор скриптов, а также список доступных модулей (плагинов для самого Godot) — «AssetLib». Переключаются разделы нажатием на соответствующие надписи в верхней части.

В нижней части редактора есть ещё один блок, который по умолчанию скрыт, и открывается только при возникновении каких-либо ошибок или отладке. Он состоит из четырёх вкладок: «Вывод» — различная информация самого редактора, в том числе ошибки; «Отладчик» — используется для отладки скриптов; «Аудио» и «Анимация» мы пока рассматривать не будем.

Для того, чтобы скрыть это блок опять, достаточно нажать ещё раз на название раздела («Вывод», «Отладчик», «Аудио» или «Анимация»).

Но вернёмся к редактору, по своей сути все элементы Godot это сцены, их можно сохранять, изменять тип, встраивать в другие сцены и т.д. Мы будем работать с 2D-сценами и использовать соответствующие для них типы элементов.

Сначала создадим простой компонент, который будет у нас в будущем игроком. Для этого в блоке «Сцена» нажимаем плюс и во вновь открывшемся окошке ищем тип «KinematicBody2D» с иконкой в виде человечка. Его можно сразу найти задав фильтр в строке поиска или найти открыв дерево со списком компонентов: Node → CanvasItem → Node2D → CollisionObject2D → PhysicsBody2D → KinematicBody2D. После чего нажимаем кнопку «Создать».

По своей сути мы могли бы выбрать и обычный элемент «Node2D», но у «KinematicBody2D» есть ряд свойств, которые нам понадобятся в будущем.

После добавления элемента на сцену, рядом с названием появится желтый восклицательный знак, нажав на пиктограмму которого мы получим предупреждение:

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

Для начала переименуем наш компонент «KinematicBody2D» в «player». В последствии это имя будет использовано при отображении элементов на игровой сцене. (Для этого достаточно кликнуть на названии и откроется поле для ввода нового имени).

Теперь необходимо добавить компонент, отвечающий за область взаимодействия или если быть точнее область обнаружения столкновений (Collision). Если у нас простой элемент или мы не хотим заморачиваться с высокой точностью, то подойдёт «CollisionShape2D». Если же у вас сложный, многогранный объект, то можно выбрать «CollisionPolygon2D».

Я не буду усложнять материал, поэтому просто добавим компонент «CollisionShape2D». Выбираем наш элемент «player», нажимаем плюс и выбираем: Node → CanvasItem → Node2D → CollisionShape2D.

И вновь получаем предупреждение с желтым восклицательным знаком:

Дело в том, что компонент мы добавили, а сама область так и не задана. Но прежде чем мы её добавим, нам понадобится ещё один элемент — Sprite. Это будет внешний вид нашего персонажа.

Выбираем узел «player», нажимаем плюс и добавляем: Node → CanvasItem → Node2D → Sprite:

Как видите, в разделе «Недавние», появились наши ранее добавленные элементы. Гораздо быстрее, нежели искать однотипные элементы каждый раз.

Теперь переключимся в блок «Файловая система», и нажав правую кнопку мыши на «res://» выберем пункт «Новая папка». В открывшемся окне введём название «images», здесь будут изображения, которые мы будет использовать в дальнейшем:

Откроем эту папку в проводнике (правая кнопка мыши на «images» и пункт «Просмотреть в проводнике». Теперь сюда нужно скопировать картинку для нашего игрока в формате PNG.

Хочу обратить ваше внимание, что PhotoShop очень любит «пихать» в файлы системную информацию, и в частности задавать не совсем корректный «Color profile». Из-за чего Godot начнёт ругаться на некорректный формат «sRGB profile»:

В принципе вы конечно можете игнорировать данное сообщение, но я всё рекомендую очистить весь лишний «мусор». Сделать это можно, например, с помощью программы «XnView MP». Для этого на нашей картинке нажимаем правую кнопку мыши и в открывшемся меню выбираем «Пакетная обработка»:

На вкладке действия нажимаем «Добавить действие» → Изображение → Удаление метаданных. Отмечаем все чекбоксы (галочки) и нажимаем преобразовать:

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

Но вернёмся в наш редактор и убедимся, что изображение нашего игрока находится на месте. Теперь это изображение нужно добавить к компоненту Sprite. Для этого выберем этот элемент в разделе «Сцена», и переключим своё внимание на раздел «Инспектор». В данный момент нас интересует свойство «Texture». Изначально там указано значение . Нас интересует «Новый ImageTexture». Можно выбрать его из меню, а можно сразу перетащить нашу картинку из блока «Файловая система» и отпустить над свойством «Texture»:

После чего увидим, что в главном окне редактора у нашего «player» появилась форма в виде нашей картинки:

Сразу хочу обратить ваше внимание вот на какой момент. Если вы планируете использовать графику в стиле pixeart, то вам вполне вероятно понадобится отключить сглаживание. В противном случае ваша картинка будет «мутная».

Для этого, в блоке «Инспектор», выбираем нашу текстуру, и в открывшемся меню выбираем пункт «Редактировать»:

В разделе «Flags» снимаем все чекбоксы (галочки) и убеждаемся, что грани нашего кубика больше не сглаживаются.

Для того, чтобы не повторять эту процедуру каждый раз, откроем блок «Импорт», снимем чекбокс (галочку) напротив «Flags». Затем нажимаем на «Предустановка..» и выбираем «Установить по умолчанию для ‘Texture’»:

Теперь при импорте новых картинок редактор не будет выставлять флаги.

Вернёмся к блоку «Сцена» и добавим наконец область взаимодействия. Для этого выберем наш компонент «CollisionShape2D» и блоке «Инспектор» зададим свойство «Shape» в виде «Новый RectangleShape2D»:

Просто квадратная область. Поскольку изображение нашего игрока всего 32 на 32 точки, то область задать будет несколько проблематично:

Но можно с помощью колеса мыши приблизить изображение и выставить область таким образом, чтобы она покрывала весь спрайт персонажа:

Можно пойти несколько другим способом и не мучатся, тягая мышкой точки. Открываем в блоке «Инспектор» раздел «Transform» и задаём свойство Scale:

Честно сказу в редакторе Godot очень много непонятных моментов, например, почему свойство именно scale (масштаб), а ни, например, просто дать возможность указать точный размер области. Или глобальная область первичного объекта (в данном случае «player») она равна 64 на 64 точки и изменить её нельзя, даже если у нас спрайт размером меньше. Честно скажу это весьма неудобно в некоторых случаях. А на англоязычных форумах предлагают модифицировать основные классы прямо внутри Godot и задавать там размер. К сожалению, с ходу у меня это не получилось сделать.

Но вернёмся к нашему игроку. По сути базовые настройки завершены, и мы можем сохранить нашу сцену уже как компонент «player». Для этого в блоке «Файловая система» создадим ещё одну папку и назовём её «elements». Теперь в главном меню редактора выберем «Сцена» → «Сохранить сцену как…» и выбрав нашу папку «elements» сохраним файл «player.tscn»:

Теперь нам нужно создать главную игровую сцену. Для этого в том же главном меню «Сцена» выбираем пункт «Новая сцена». В блоке «Сцена» нажимаем плюс и выбираем компоненту «Node»:

По сути это базовый компонент, прародитель всех остальных и нам от него ничего не потребуется (пока). Единственное, что переименуем его в «gamescene». Теперь нам на игровую сцену нам нужно добавить нашего игрока. Для этого кликнем на «gamescene» и затем нажмём на пиктограмму в виде звена цепи (рядом с плюсом) и во вновь открывшемся окне выберем: «elements → player.tscn».

Как не трудно догадаться звено цепи прикрепляет к сцене элемент в виде нашего игрока. Причём если мы потом захотим что-либо изменить в «player», то этим изменения так же отобразятся на игровой сцене. Это очень удобно, так как таких элементов может быть очень много на сцене и отдельно редактировать каждый из компонентов очень утомительно.

Компонент «player» можно спокойно перемещать мышкой в нужное место, но мы пойдём немного дальше и включим сетку и сделаем перемещение дискретное. Для этого в основном блоке редактора нажмём обзор и включим «Показать сетку». По сути её можно в любой момент включать/отключать с помощь горячих клавиш — G:

Теперь настроим размер ячеек кратное нашему игроку. Для этого нажмём на пиктограмму в виде трёх вертикальных точек и выберем пункт «Настроить привязку…»:

И укажем размер ячеек 32 на 32:

Теперь надо активировать привязку нажав на пиктограмму в виде магнита:

Так же можно переключать это режим с помощью горячей клавиши — S.

Как мы видим на скриншоте выше наш игрок попадает на пересечение ячеек и это не есть совсем хорошо:

Для того что бы наш персонаж был чётко посредине ячейки, откроем его на редактирование нажав на пиктограмму в виде «Хлопушки-нумератора»:

Теперь изменим свойства позиционирования в блоке «Инспектор», сначала для Srpite:

В подразделе «Offset» снимаем чекбокс (галочку) рядом со свойством «Centered».

Затем у элемента «CollisionShape2D» в подразделе «Position» задаём смещение (16, 16) на половину размера нашего спрайта:

Сохраняем сцену (Ctrl+S) с «player.tscn» и переключаемся на нашу игровую сцену:

Проверяем, что наш персонаж точно по середине ячейки, хоть и общий контур больше (64x64) и сохраним игровую сцену. Создадим ещё одну папку «scenes» в «res://» и сохраним туда «gamescene.tscn».

Теперь самое время проверить всю нашу конструкцию в действии. Для этого выберем в верхнем меню справа нажмём кнопку «play» или горячую клавишу — «F5».

Редактор сообщит, что не выбрана главная сцена и предложит её указать. Нажимаем «Выделение» и выбираем «gamescene.tscn»:

После чего откроется окно с игрой, и мы увидим наш квадратик с персонажем.

Теперь попробуем задать управление с помощью клавиатуры и рассмотрим базовые элементы скриптов. Сначала нам нужно задать сами клавиши.

Для этого откроем в главном меню: «Проект» → «Параметры проекта». Во вновь открывшемся окне на закладке «Список действий» мы увидим большой список. Можно использовать уже готовые элементы списка, но мы создадим четыре своих: «player_up», «player_down», «player_left», «player_right». Вставляем поочерёдно названия и нажимаем кнопку «Добавить»:

Это будут четыре события, по каждой стороне перемещения. Теперь надо задать условия, при котором будет происходить сработка события. Нажимаем плюс и выбираем «кнопка», после чего откроется окошко и нам предложат нажать кнопку на клавиатуре. По такому же принципу можно задать кнопку у геймпада или мыши:

Я буду нажимать кнопки управления курсором, но вы можете назначить их по своему усмотрению, например, WASD. В результате чего должна получится такая вот картина:

Теперь создадим ещё одну папку в разделе «res://» для скриптов — «scripts». После чего открываем на редактирование нашу сцену «player.tscn». Выбираем главный узел «player» и нажимаем пиктограмму в виде свитка с зелёным плюсиком или же можно нажать правую кнопку на узле «player» и выбрать «Прикрепить скрипт»:

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

После нажатия кнопки «Создать» откроется редактор с нашим скриптом, с шаблоном по умолчанию. Несколько слов о самом редакторе:

  • В области 1 находятся открытые скрипты проекта, в данный момент он один — player.gd;
  • В области 2 находится список функций данного скрипта. На этапе создания она тоже одна это _ready();
  • В области 3 (начало скрипта) указан класс на базе которого основан данный скрипт. В данном примере это KinematicBody2D. У каждого класса свой функционал и надо быть внимательным.
  • В области 4 перечисляются локальные переменные доступные внутри этого скрипта. Несмотря на то, что тип переменной не указан явно (var), они типизированы и для того, чтобы склеить строку и число, придётся привести к одному типу. Например “lives: “ + String(10);
  • Далее в области 5 и 6 следуют функции. У зарезервированных функций имена начинаются со знака подчёркивания. В выше указанном примере функция _ready() вызывается 1 раз когда элемент добавляется на сцену, или проще говоря инициализируется. Если функция пустая, для того чтобы не было ошибки вставляется «заглушка» в виде вызова pass. Функция _process вызывается каждый фрейм (кадр), но только если предварительно была разрешена командой set_process(true) в функции _ready(). Причём при каждом вызове функции _process в переменной delta будет некое число (прирост) с момента предыдущего вызова. Это значение можно использовать как таймер для каких-либо действий в будущем;

Проведём небольшой эксперимент. Разрешим вызов set_process(true), а в функции _process добавим вывод в консоль отладки значение delta в консоль:

Теперь после запуска проекта (F5) мы получим кучу быстро сменяющихся цифр:

Ура! Всё работает! Но нам нужно добавить управление нашим кубиком. Сразу скажу, что приведённый метод не очень хорош, но как базовая демонстрация вполне сгодится. В моих проектах используется более корректный опрос, но он несколько сложен, а мне бы не хотелось перегружать и так достаточно большую статью. Итак, для того, чтобы сработал наш опрос кнопок необходимо на этапе инициализации добавить несколько переменных:

var direction = Vector2()
var speed = 0
const MAX_SPEED = 400
var velocity = Vector2()
  • direction — это двумерный вектор направления в какую сторону будет двигаться наш персонаж: (-1,0) влево, (1,0) вправо, (0,-1) вверх, (0,1) вниз. Возможны комбинации, например, для движения по горизонтали вверх и влево (-1,-1);
  • speed — текущая скорость перемещения нашего персонажа, изначально равно 0 (он стоит);
  • MAX_SPEED — константа, максимальная скорость с которой будет двигаться персонаж;
  • velocity — ещё одни двумерный вектор, в нём хранится текущее направление движения с учётом скорости;

Теперь опишем функционал в _process:

Инициализируем(сбрасываем) направление движения (0,0):

direction = Vector2()

Теперь опрашиваем события для кнопок влево/вправо:

if Input.is_action_pressed("player_left"):
	direction.x = -1
elif Input.is_action_pressed("player_right"):
	direction.x = 1 

Если одна из них нажата задаём горизонтальное направление.

Повторяем эту же процедуру для вертикального движения:

if Input.is_action_pressed("player_up"):
	direction.y = -1
elif Input.is_action_pressed("player_down"):
	direction.y = 1

Если вектор движения задан (не равен 0,0), то выставляем максимальную скорость движения, в противном случае она равна нулю:

if direction != Vector2():
	speed = MAX_SPEED
else:
	speed = 0

Теперь рассчитываем движение с учётом направления и скорости:

velocity = speed * direction.normalized()

Ну и далее собственно заставляем двигаться сам объект:

move_and_slide (velocity)

В результате чего у нас должна получится вот такая картинка:

А после запуска наш квадратик гоняется по экрану с помощью клавиш курсора.

На этом собственно всё. Не хочу сильно перегружать вводную часть. В следующий раз мы рассмотрим столкновения и более подробно поговорим о GDScript.

Удачи в ваших начинания, а готовый проект можно скачать по ссылке.