Привет, Хабр! Меня зовут Матвей, я уже несколько лет хочу научиться создавать игры. Скажу честно: все никак не хватало времени и, возможно, целеустремленности, чтобы изучить Unreal Engine, Cry Engine и им подобные движки.
Но я знаю Python. Оказывается, для любителей парселтанга есть относительно простой способ вкатиться в геймдев — игровой движок Godot, который поддерживает программирование на синтаксически похожем языке GDScript. Я его изучил и даже создал небольшую игру. В этой статье хочу рассказать об этом решении подробнее.
Используйте навигацию, если не хотите читать текст полностью:
→ Почему Godot
→ Знакомство с GDScript
→ Начало работы с Godot
→ Создание основных элементов игры
→ Добавляем интерактивность
→ Тестирование «шедевра»
Почему Godot
Лично для меня ответ на этот вопрос кроется в лиде, но постараюсь подчеркнуть то, что мне больше всего откликнулось.
Начнем с того, что в Godot можно программировать на Python, что ускоряет процесс создания игры. Кроме того, в движке есть встроенный визуальный редактор, с помощью которого можно легко создавать игровые сцены и анимации с различными эффектами.
Следует отметить, что в Godot доступны современные шейдеры, постобработка и поддержка физического света, а также различные другие полезные функции. И, наконец, программа позволяет экспортировать игры на различные платформы, включая Windows, macOS, Linux, iOS, Android и веб-браузеры.
Знакомство с GDScript
На самом деле, данная статья — введение. Поэтому для начала мы познакомимся с GDScript, встроенным языком для программирования в Godot. Он своим синтаксисом отдаленно напоминает Python, который мы будем использовать в следующих частях.
Привлекает GDScript своим синтаксисом в духе Python, что делает его легкочитаемым и эффективным. Улучшенная статическая типизация языка позволяет явно указывать типы переменных, что повышает производительность и надежность кода. Например, вот так можно объявить переменную определенного типа:
var health: int = 100
GDScript поддерживает множество типов данных от базовых до продвинутых. Среди них — простые: целые числа int, числа с плавающей запятой float, строки String и логические значения bool. А еще продвинутые: векторы Vector2, Vector3 для 2D- и 3D-координат, коллекции Array и Dictionary.
Вот пример объявления различных типов данных:
var health: int = 100
var name: String = "PlayerOne"
var position: Vector2 = Vector2(0, 0)
var inventory: Array = [item1, item2, item3]
var attributes: Dictionary = {"strength": 10, "agility": 15}
Функции
GDScript придерживается простого подхода. Функции определяются с помощью ключевого слова func, за которым следуют имя и параметры. Они могут возвращать значения и даже поддерживают параметры по умолчанию для большей гибкости.
Вот базовое определение функции с типом возвращаемого значения и параметрами по умолчанию:
func add_numbers(a: int, b: int = 10) -> int:
return a + b
Не забывайте об областях видимости переменных. Локальные переменные ограничены функцией, в которой они объявлены.
Управляющие конструкции
Структуры управления в GDScript, такие как операторы if-else и циклы for и while, необходимы для управления потоком игровой логики. Они используются для принятия решений, перебора наборов данных или задания «временных рамок»:
if health > 50:
print("Player is healthy")
else:
print("Player needs healing")
for i in range(10):
print(i)
Одни из уникальных функций GDScript — это сигналы и слоты, с помощью них можно настроить взаимодействие между объектами.
Сигнал объявляется внутри класса и могут передаваться с параметрами или без них. Другие объекты или узлы могут прослушивать эти сигналы, подключая их к своим методам:
signal player_damaged
func take_damage(amount: int) -> void:
health -= amount
player_damaged.emit(health)
Начало работы с Godot
Отлично! Теперь, когда мы базово знакомы с основами GDScript, можно создать первую игру. Или еще рано? Сначала нужно настроить рабочее окружение!
Установка движка
На самом деле, скачать движок достаточно просто. Достаточно перейти на официальный сайт, выбрать свою операционную систему и кликнуть по кнопке Скачать. После загрузки нужно кликнуть по иконке, и менеджер установки сделает все за вас. Процесс занимает всего 5-10 минут — это гораздо быстрее, чем установка Unity или других движков.
Как только движок установлен, открываем его и практически мгновенно попадаем на главный экран Godot. Начинаем изучать движок, а дальше используем свое воображение, вспоминаем видео на YouTube а-ля «программирование за пять минут» и создаем свою первую игру.
Интерфейс программы и основные инструменты
Сперва интерфейс может показаться сложным, но поверьте: он гораздо проще, чем тот же Unreal Engine или Unity.
В окне по центру наблюдаем основную сцену игры. Сюда можно перетаскивать различные объекты, тем самым создавая дизайн своего проекта, уровней.
Так как большинство разработчиков рекомендуют изучать геймдев с 2D, не будем предавать традиции и выберем двумерный вид отображения:
Здесь же можно открыть раздел Script для редактирования скриптов или AssetLib — аналог магазина, в котором можно скачивать различные плагины для ваших игр. В верхнем правом углу есть кнопки для запуска и остановки проекта, а также — функция активации сцены.
В окне слева вы можете создавать корневые узлы. Любая сцена должна состоять из одного основного узла, от которого будут наследоваться другие объекты. Чуть ниже в файловой системе отображаются все файлы, что есть в вашем проекте. Кроме того, в правой части программы можно найти вкладку Инспектор и Узел.
В Инспекторе будут отображаться все свойства выбранного вами объекта, а во вкладке Узел — редактирование узла, его сигналов и групп. Внизу есть еще вкладки для просмотра информации по статистике в игре. Это различная выводимая информация, отладчик, данные о звуке и анимации.
Создание основных элементов игры
Узлы
Первое, что необходимо сделать в пустом проекте Godot, так это создать основной (корневой) узел. Этот узел станет отправной точкой в создании игры. Например, он способен добавлять фоновые и другие элементы, задавать размер сцене, настраивать параметры камеры.
В нашем случае корневым узлом является 2D-сцена. После ее создания можно заметить, как в Инспектор подтянулись различные доступные свойства. Здесь можно поменять transform (расположения объекта), а также установить видимость и материал объекта. Если мы создадим другой объект, будь то свет, звук или коллайдер, то количество доступных свойств будет отличаться каждый раз.
Каждый узел можно переименовать — достаточно кликнуть по нему два раза и ввести название. В нашем случае — «main сцена». Теперь можно все это сохранить. Для этого следует перейти в раздел Сцена и нажать на Сохранить сцену.
Персонаж и спрайты
После создания сцены первое, что нам нужно сделать, — добавить в файловую систему спрайты, которые будем использовать для игры: персонажей и другие объекты.
Откроем файловую систему в проводнике. Для этого нажимаем ПКМ на папку res и нажимаем на Открыть. В проводнике откроется папка нашей игры. Сюда же переместим картинки и объединим их в файл Sprites.
Супер! Теперь у нас есть изображения объектов — визуальное представление о том, как наши персонажи и окружение будут выглядеть на сцене:
Создадим отдельную сцену с главным персонажем. Это нужно для того, чтобы удобнее работать с отдельно взятыми структурами и возможностью использовать персонажа для разных сцен.
Нажимаем на плюсик и добавляем новую сцену. Здесь нам необходимо указать корневой узел. Поскольку на этой сцене мы будем описывать нашего основного игрока, то нам не подходят такие узлы, как 2D- или 3D-сцена. Подойдет CharacterBody2D.
Для удобства переименуем его в player, а для добавления картинки переходим в папку Sprite и перетаскиваем основного игрока. Чтобы разместить героя в нулевых координатах, выбираем объект player, переходим в transform и просто указываем (0;0).
Чтобы добавить форму и персонаж мог взаимодействовать с другими предметами, к player необходимо привязать дочерний узел. Для этого нажимаем на плюсик и добавляем CollisionShape2D. При помощи этого узла мы можем указать определенную форму этого объекта. Так мы сказали движку, что пределах этой синей формы наш игрок будет твердым телом.
Теперь нам нужно сохранить эту сцену — назовем ее Player. Для того, чтобы добавить дочернюю сцену к основной, достаточно перенести ее в иерархию.
→ Управление движением
Давайте добавим базовый функционал и сделаем так, чтобы игрок мог передвигаться вправо, влево, а также прыгать при нажатии на Space. Для этого понадобится отслеживать нажатия на клавиши! Чтобы нам такое сделать нам в первую очередь нужно отслеживать нажатие на клавишу.
Отслеживание нажатий уже встроено в движок Godot — достаточно указать, какие клавиши нужно мониторить. Для этого нужно перейти в Проект → Настройки проекта и раскрыть список действий. В нем представлены базовые настройки проекта, но для удобства можно настроить самому.
Необходимо добавить к игроку скрипт, который будет отслеживать нажатия. Для этого нужно выбрать узел и создать скрипт. Придерживаемся правила: один узел — один скрипт.
Мы выберем основной узел player. Справа в Инспекторе откроем Script и добавим новый скрипт.
- В боковой панели у нас отображаются скрипты, над которыми мы работаем сейчас.
- Ниже отображаются все функции и методы, которые есть внутри открытого скрипта. В нашем случае есть только функция ready.
В базовом скрипте описывается, как можно задавать переменные,
и создаются две стандартные функции: ready и process. Они являются встроенными функциями Godot.
- Функция ready вызывается один раз при создании самого объекта.
- Функция process вызывается каждый frame, то есть все время, пока у нас будет работать игра
Пропишем код: настроим константы, «гравитацию» и другие параметры объектов.
Пояснение к коду
- SPEED определяет скорость движения персонажа по горизонтали.
- JUMP_VELOCITY устанавливает начальную скорость прыжка персонажа по вертикали.
- Значение гравитации извлекается из настроек проекта для использования в симуляции физики.
- Есть функция physics_process: если персонаж не на земле, к его вертикальной скорости добавляется гравитация. Условие if not is_on_floor проверяет, находится находится ли персонаж на земле.
- Проверяется нажатие клавиши Space. Если персонаж стоит на земле, ему назначается вертикальная скорость для прыжка.
- Используется функция move_and_slide, чтобы обновить позицию персонажа с учетом текущей скорости и физических коллизий.
Этот скрипт обеспечивает базовое управление персонажем, включая движение по горизонтали, прыжки и гравитацию. Он может быть настроен и расширен для реализации дополнительной функциональности в вашей игре. Например, можно настроить поворот изображения персонажа при движении вправо или влево
Рассмотрим другие функции для работы с персонажем.
→ Получение направления движения
Для этого используется функция Input.get_axis. Она возвращает значение оси движения игрока. В данном случае, проверяются оси player_left и player_right. Если значение оси не равно 0, значит, игрок движется либо влево, либо вправо.
→ Обработка движения/замедления
Если значение направления не равно 0, устанавливается горизонтальная скорость персонажа (velocity.x) в направлении движения, умноженная на скорость (SPEED).
Также происходит поворот игрока влево или вправо — в зависимости от направления движения. Если значение направления меньше 0, то есть игрок движется влево, устанавливается поворот персонажа влево ($Персонаж.flip_h = true), иначе — вправо ($Персонаж.flip_h = false).
Если значение направления равно 0, то есть игрок не двигается, горизонтальная скорость персонажа зануляется, чтобы персонаж остановился.
→ Управление состоянием персонажа
Добавим перезагрузку персонажа при его выходе за рамки игрового поля.
- Получаем прямоугольник, представляющий видимую область экрана, с помощью функцииget_viewport_rect.
- Добавляем проверку, выходит ли игрок за границы экрана по горизонтали или вертикали.
- Если условие выполняется, то позиция игрока (global_position) устанавливается в начальную позицию (START_POSITION).
Код ниже отвечает за обработку позиции игрока и его перенос на на стартовую позицию:
Отлично — персонаж умеет перемещаться, прыгать, не проваливается под сцену и не пропадает за пределы экрана. Можно сказать, что уже получилась «бродилка». Но все это — скучно, нужно больше интерактивности!
Добавляем интерактивность
Внутриигровые объекты
Чтобы создать базовую локацию в игре, нужно добавить объекты, с которыми будет взаимодействовать персонаж, — например, платформу.
Для удобства создаем новую сцену, слева нажимаем Другой узел, в поиске вбиваем класс StaticBody2D. Это узел, который представляет собой статическое тело в 2D-пространстве.
Добавляем в сцену объект (изображение) и узел CollisionShape2D, чтобы добавить форму для взаимодействия:
Этот же план повторяем для других объектов. Напоминаю, что для удобства редактирования лучше создавать отдельные сцены для каждого из элементов.
После того, как мы создали все предметы для взаимодействия, переносим их в главную сцену main.tscn и добавляем уровень для прохождения.
Для того, чтобы дублировать объект, достаточно выделить его в рабочей главной сцене, нажать Ctrl+C и Ctrl+V. А если нужно изменить форму добавляемого объекта, то можно использовать разные режимы курсора:
Фон сцены
После того, как все объекты расставлены, можно добавить фон сцены. Для этого можно создать уже на главной сцене новый узел с названием Sprite2D. Основное предназначение Sprite — отображение изображений на экране игры. Он может загружать изображения из файлов PNG, JPEG и других форматов.
Фоновая музыка
Добавим фоновую музыку для игры. Для этого перейдем в сцену и создадим узел AudioStreamPlayer2D. Он позволяет добавлять атмосферные звуковые эффекты и фоновую музыку. Далее добавим к этому узлу скрипт:
Данный код создает экземпляр объекта AudioStreamPlayer2D и загружает аудиофайл музыка.mp3, который находится в папке Sprites внутри проекта. После загрузки начинается воспроизведение звука. Загруженный аудиофайл присваивается переменной stream.
Тестирование «шедевра»
Давайте запустим то «детище», что мы создавали. Геймплей выглядит, мягко говоря, кхм, вот так:
Не могу сказать, что я научился делать красивые и интригующие игры, но это уже что-то. Как минимум, понял, что создать простой платформер с помощью Godot вполне себе реально. Хотя в сети много гораздо более впечатляющих шедевров, как, например, Road To Vostok:
Возможно, в будущем напишу статью о создании 3D-игр на Godot. Конечно, если тема оказалась для вас интересной. Что думаете насчет этого движка? Может, уже успели с ним поработать? Поделитесь своим опытом в комментариях!
Возможно, эти тексты тоже вас заинтересуют:
→ В огне не горит, в воде не тонет: новый вид связи может работать практически везде. Но и это не все
→ Полное краткое руководство по grammY — JS-библиотеке для создания Telegram-ботов
→ Российские СХД, очень много платформ для ML, новые GPU и коммутаторы. Дайджест серверного железа за февраль
Комментарии (14)
Gl-lab
18.03.2024 14:55+1Правильно ли я понял, что все таки игра на языке похожем на питон, но не на питоне?
GoldGoblin
18.03.2024 14:55+1Игра пишется либо на gdscript либо на C#.
gdscript - язык похожий на питон синтаксисомИ @techno_mot в godot 4 еще нет визуального редактора (На сколько я знаю)
otto_haendler
18.03.2024 14:55На С# особо не получилось, вешался сам движок под windows 11. В образцах есть хорошие примеры всего что можно делать. Покрутили повертели и продолжили пока работать в Unity.
gudvinr
Какой-то ужасный кликбейт. У gdscript единственное сходство с python - это отдалённо похожий синтакстс. Причем основное сходство - это разделение блоков количеством пробелов.
Более того, в godot есть подсистема расширений GDNative, которая позволяет цеплять к рантайму обработчики на лругих ЯП, в том числе и python: https://github.com/touilleMan/godot-python
Вот про настоящий python в godot с разбором gdnative было бы интересно почитать, а так, как вы делаете, делать не надо. Если уж пишете на gdscript - пишите без кликбейтов
MrSteelRat
Ох я щя мучаюсь с тем, чтобы вкинуть в проект C/C++ это тихий ужас, чтобы это дело связать с плюсами
slonik_nocry
да нет все правильно написано. Представь что ты ниразу не программист, и у тебя за плечами паскаль из школы и пайтон на самообучении. Под этой призмой Годо с py-like супер, против c# и c++ других двух популярных движков. А то что и то отличаеться, и сё сложнее — это как в unity тоже свой другой c#
dmiche
Ну почему же? Питонщику действительно очень удобно на старте, а быстрый старт иногда весьма полезен.
gudvinr
Как раз, когда хорошо знаешь какой-то язык, то "совсем другой язык который немного похоже выглядит" - это наоборот неудобно.
Язык - это не только синтаксис. Когда пишется программа, то от неё ожидается определённое поведение. Поведение определяется имплементацией языка. Даже Python - это не какой-то один язык, а много диалектов, и каждый из них ведёт себя по-разному. А gdscript вообще ничего общего с питоном не имеет в плане реализации, это отдельный язык.
Но важно не это, а то, что автор статьи просто обманывает, играя на популярности Python. Проблема не в языках, а в том что статья - кликбейт. Заголовок, кажется, изменили, но в начале статьи есть
И дальше ни слова именно про Python.
dmiche
Я только за себя скажу: нулевые затраты на изучение языка на старте для меня, как для питонщика, были очень приятным бонусом. Только на 3й день понял, что вообще это немного более не питон, чем казалось в начале.
При том, что я, так-то, много языков знаю, но между ними всеми базовых различий больше, чем между питоном и гдскриптом.
Да, потом полез, конечно, в их справочники и туториалы, чтобы выяснять, как на гдскрипте всякие сложные вещи делать. Но это потом.
gudvinr
Используя схожие закономерности, можно сказать, что C и JavaScript - это похожие языки, потому что у них синтаксис схожий, поэтому на C будет проще писать, если JavaScript уже знаком :)
dmiche
Это, в своё время, дало хороший бонус жаваскрипту. И awk-у. А вот бейсик оказался в пролёте: не настолько похож, чтобы не раздражать и не настолько хорош, чтобы себе это позволить. Итог был печален.