Эту статью я написал для своего блога в октябре 2017 года.
Речь идёт об игре Speebot, которая сейчас выпущена в Steam. Бесплатная demo версия прилагается.
Я разрабатывал эту игру с января 2016 года в своё свободное время в одиночку. Мною выполнено всё программирование, дизайн игрового процесса, создание графики и музыки. Кроме того, я написал собственный игровой движок с нуля.
Люди часто спрашивают меня, почему я решил создать свой движок, когда на рынке доступно множество бесплатных универсальных движков. Есть много причин, и о них я попытаюсь рассказать в этой статье.
Одним из самых больших преимуществ собственного движка является абсолютный контроль кода. Есть возможность настроить его именно так, как это нужно для конкретной задачи. Такой узкоспециализированный движок получается оптимизированным для конкретного типа игр и работает быстрее и надёжнее, чем универсальный движок.
Универсальные игровые движки называются так, потому что они предназначены для общего использования, и в них заложены функции, которые не всем нужны. Это неизбежно приводит к "раздуванию" кода, и к замедлению производительности игр.
Второе преимущество — это контроль самого процесса разработки. Я считаю, что инструментарий должен быть по-максимуму удобным для разработчика. Что является удобным — зависит от самого типа данной игры. Например, для Speebot — это встроенный редактор уровней, который позволяет быстро создавать новые уровни и незамедлительно их тестировать.
Решение использовать собственный движок позволяет мне интегрировать мои собственные инструменты таким образом, чтобы мне было проще и быстрее создавать контент.
Ещё один большой плюс: не нужно соглашаться с условиями лицензии стороннего движка, подписывать договора и платить проценты от прибыли.
Ну и наконец: написание собственного движка — это очень интересно.
Разработка движка началась в январе 2016 года. Я назвал его YUME ("мечта" по-японски). Он написан на Haxe, C++ и OpenGL. Я использую модифицированную версию библиотеки Lime, которая включает в себя несколько полезных функций, например, позволяет загружать ресурсы и открывает доступ к OpenGL.
До начала создания движка я почти ничего не знал о разработке 3D игр. Нужно было разбираться в OpenGL читая документацию, форумы и уроки, предназначенные для других языков (Java и C++). Через пару месяцев у меня получился довольно стабильный 3D-визуализатор.
Кроме самого 3D-визуализатора, нужно было с нуля создать множество разных систем: 2D-визуализатор, машину состояний, систему временных шагов (об этом позже), систему интерфейсов, систему управления мышью, клавиатурой и джойстиками, динамические тени, 3D звуковую систему (используя OpenAL), загрузку моделей (в собственном формате, основанном на IQM), "скелетные" анимации, иерархию объектов, эффект зеркального отражения в реальном времени, отображения текста и так далее.
В конце концов, получилась 3D библиотека, которую можно использовать для чего-то конкретного. Многое из того, что я перечислил, присутствует и в других движках, но в YUME есть несколько отличий. Одно из них — система временных шагов.
Система временных шагов гарантирует, что движок обрабатывает и показывает кадры игры с определённым интервалом. В YUME нет ограничения по количеству кадров в секунду, т.е. нет привязанности к 30 или 60 кадрам в секунду. Частота кадров может быть любая, а игра всё равно будет работать с одной и той же скоростью, потому что частота обновления логики не связана с частотой обновления экрана. На компьютерах разных мощностей может быть разная производительность, и время для показа одного кадра может быть любым. А логика всегда привязана к частоте 62.5 циклов в секунду (16 миллисекунд на каждый цикл). В этом основной принцип системы временных шагов, хотя есть некоторые крайние случаи.
В результате: на более слабых компьютерах уменьшается частота кадров в секунду, но на игровой процесс это не влияет.
У меня была готовая библиотека, но пока ещё не движок. Пришла пора начать разрабатывать игру, и принимать решения о нужных функциях. К тому времени у меня уже было несколько идей, и я знал, что хотел попробовать поэкспериментировать с 3D "плитками".
Я начал создавать систему игровых уровней, которая использовала что-то похожее на 2D плитки (tilemaps), но с одним дополнительным измерением. Получается, что уровень можно сложить из "кубиков", как конструктор. Я создал редактор карт, чтобы ускорить процесс создания уровней. В итоге этот редактор попал в финальную версию игры и доступен каждому игроку.
Движок автоматически определяет, какую 3D модель использовать для отображения каждой плитки, в зависимости от соседних плиток. Придумал способ, как объединить все плитки в одну общую 3D модель, чтобы видеокарте не нужно было рисовать каждую плитку индивидуально. Вся карта рисуется за один раз, что очень сильно улучшает производительность.
Уровни можно редактировать и тестировать сразу. Для продуктивности — то что нужно.
Я написал простую систему игровой физики и начал экспериментировать с игровым процессом. Через несколько недель был готов первый прототип игры, в котором игрок мог перемещать цилиндр по 3D уровню.
YUME продолжал развиваться параллельно с разработкой Speebot (примерно в это время я выбрал такое название для игры). Было найдено и устранено несколько проблем с архитектурой движка, добавилось несколько новых функций: физика, частицы, отражения на поверхности воды, инструменты для анимации камеры, интерактивные объекты... Постепенно библиотека эволюционировала в игровой движок.
Я продолжал добавлять новые элементы игрового процесса, оставляя элементы, которые казались мне интересными, и избавляясь от лишнего. После некоторых экспериментов с художественным направлением графики игры я создал персонажа в Blender — маленького робота с одним колесом. Персонаж нарисован и анимирован в мультяшном стиле.
В это время я уже работал в основном над самой игрой, а не над движком. Я продолжал создавать новые уровни, декорации, персонажи и элементы игры.
В конце 2016 года я сделал паузу от разработки игры, и посвятил несколько месяцев изучению и практике написания музыки. У меня нет музыкального образования, но это — моё хобби. У меня уже был небольшой опыт в композиции музыки для моей предыдущей игры Hypnorain, но я хотел улучшить свои навыки, поэтому снова погрузился в изучение музыкальной теории. Для композиции музыки я использовал программу SunVox, которая является виртуальным модульным синтезатором. В финальной версии игры Speebot всего 23 трека, которые вместе составляют более часа оригинальной музыки. Я удовлетворён результатом, и продолжу улучшать свои навыки для следующей игры.
После этого я концентрировался на создании новых уровней, добавлении новых игровых элементов, написании музыки и устранении ошибок. Такой подход к разработке игр мне по душе. Если мне становится скучно заниматься одним и тем же делом, я переключаюсь на другой вид деятельности, и поэтому не теряю интереса к разработке игры.
После выпуска нескольких демо версий, обработки отзывов от игроков и улучшения игры, Speebot был выпущен в октябре 2017 года. В финальной версии игры 200 уровней, 4 мира, редактор пользовательских уровней, несколько дополнительных режимов игры, и много другого дополнительного контента.
Самое сложное при разработке игры было сохранять мотивацию и интерес на протяжении всех 20 месяцев. Работать над игрой мне удавалось только по вечерам после университета и работы, и по выходным дням. Но всё равно, это было очень интересно.
Я продолжу использовать и развивать свой движок YUME в своих будущих играх, и уже начал работать над своим следующим проектом.
После написания этой статьи я разработал и выпустил ещё две игры на этом движке: сюжетная приключенческая игра Phantom Path, и игра-головоломка Pilie Pals.
Комментарии (35)
discipuli
22.04.2022 18:50А исходники движка открыты?
Просто увидел что в системных требованиях только винда и немного погрустнел.
kircode Автор
22.04.2022 20:13+4Код движка недоступен. Думаю, что движок слишком узкоспециализирован для общего потребления, а на создание полной документации и поддержку ушло бы много времени. Посчитал, что полезнее было писать такие статьи, в которых делюсь опытом самого процесса разработки.
Говорят, игра работает под Wine/Proton без проблем. Может быть в будущем сделаю нативные билды для Linux.
a-postx
22.04.2022 19:54+1Отличный результат! Вот так и рождаются независимые игроделы, на которых сегодня вся надежда. Успехов!
Oldshelf
22.04.2022 20:25+1Лёгкая (в плане эмоций и нагрузки на комп) игра. Здорово, что поддерживается gamepad!
da-nie
22.04.2022 20:40А невидимые грани вы как отсекаете?
kircode Автор
22.04.2022 21:10+2Если Вы говорите о culling, то в данной игре этого не происходит.
Уровень практически весь состоит из статичный объектов, которые при загрузке объединяются в одну модель для оптимизации, так что приходится отображать его полностью. В таком объекте не очень много полигонов, так что оптимизировать что-то дальше нет особого смысла. Если бы уровни были намного больше, то, наверное, был бы смысл в такой оптимизации, и я бы резал их на сектора, показывая только те, которые попадают в обзор камеры.
0x131315
22.04.2022 21:08+1А в чем преимущество привязки логики к какому-то определенному таймеру? В универсальных движках логика завязана на дельту времени, и таким образом тоже отвязывается от кадровой частоты.
kircode Автор
22.04.2022 21:22Я думаю, это зависит от ситуации. Но на мой взгляд, гораздо удобнее, когда логика работает с определённой частотой.
Главное, чтобы логика была отделена от отображения.
avengerweb
24.04.2022 07:09Удобнее, но дельту использует в играх когда определённую частоту соблюсти сложно, к примеру кадр не успел обработаться за 16мс. Если таких кадров 100 то получится слоумо. В оффлайн играх наверно пофиг, в онлайн к сожалению не подойдёт. Довольно сильное ограничение движка, если делать какие то очень нагружённые игры в 16мс на слабом в железке будет уложиться сложно
Miwwa
24.04.2022 07:27+1Если кадр не успевает обработаться за 16мс на целевом железе, то это значит, что пора заниматься оптимизацией или снизить требования к логике/графике. Уложиться в 16мс/32мс (60/30фпс) любыми средствами - это основное требование к производительности любой современной игры на любой платформе
Miwwa
22.04.2022 21:25Обычно в качестве аргументов приводят общий детерминизм игровой логики и стабильность физики.
Но есть и минус, если игровая логика выполняется с частотой 62.5 гц, то на экранах с частотой 60 гц будет заметен пропуск кадров, а на экранах с высокой герцовкой изображение не меняется несколько кадров, теряется плавность анимаций. Этого можно избежать, интерполируя все видимые игроку значения (положения объектов, костей в анимациях и т.д.), что влечет значительное усложнение кода движка
kircode Автор
22.04.2022 22:49+2В моём движке применяется интерполяция, поэтому все движения остаются плавными. Возможно, стоит написать об этом отдельную статью.
controlDns
23.04.2022 12:46-4vrode ranshe osobo ne tracha resursov vsegda schutali tekushyu skorost vychesleniy zaodno ponimaya tekushuyu (obschiyu) nagruzku na ustroistvo da ot raschyota korrekturovalos to chto on nazval система временных шагов ... pro eto dazhe v knishkah iz90yh po sozdaniyu igr na pascale bylo i tam ne nazyvali timerom a imenno tekuschaya skorost vychesleniya kotoray menyala vse neobhodimye zaderzhki obespechivaya plavnost proishodyaschego
tohntobshi
22.04.2022 21:43Прикольно) я как то тоже пытался сделать движок на c++, sdl, opengl. Сделал примитивный 3д рендеринг, чтоб модельки из блендера загружать, примитивнейшую физику в виде гравитации и прямоугольных хитбоксов для вычисления столкновений, пытался еще научиться рисовать. Вдохновлялся ютуберами Thomas Brush и The Cherno. Но чет забил в итоге)
FD4A
23.04.2022 02:48Сам недавно занялся такимже процессом. Сейчас только в начале пути для обработки ввода от игрока выбрал GLFW, а для аудио FMOD, не смотрели в их сторону? И там и там заявляется кроссплатформенность.
Выглядит прикольно =)
aakumykov
23.04.2022 10:38До чего же круто. Успехов! Завидую вам.
Несколько лет назад слышал в чём-то похожую историю от человека, который разрабатывал "убийцу Minecraft". Тоже рассказывал, как с нуля, ничего не зная про 3D, изучал OpenGL, делал свой движок, решал проблемы производительности. Название игры забыл, но работал он тогда в Кемеровском Goodline главным разработчиком интернет-тв.
xshd
23.04.2022 12:46Смотрится здорово!
посмотрел на сайте ролик про Phantom Path и думаю многим бы зашла такая игра.
Пару вопросов / предложений? к Phantom Path :
- есть возможность добавить GI (global illumination) для теней и источников света? Визуально игра начала бы выглядеть еще привлекательней.
-возможно ли многопользовательская игра? бегать компанией 3-4 человека
-есть вариант портировать на консоли (ps/xbox)?
Понравилась стилистика/динамика у PP, успехов!
kircode Автор
23.04.2022 12:59Спасибо! Ни GI, ни multiplayer в движке пока нет. Если пригодится для будущих игр, возможно, добавлю. На консоли возможность портировать есть, так как Haxe кроссплатформенный, но пока не пытался.
APXEOLOG
23.04.2022 12:51+1Многое из того, что я перечислил, присутствует и в других движках, но в YUME есть несколько отличий. Одно из них — система временных шагов
Ну, запихивать логику в
render()
- это ошибка новичка. В любом популярном языке программирования есть встроенные возможности для создания таймеров, которые будут срабатывать с нужным интервалом, поэтому этот функционал и не нужен в графических движках. В идеале нужно разделить вычисление логики и рендер по двум разным потокам, чтобы не было ситуации, когда игрок куда-то нажал, запустив тяжелые вычисления (например поиск пути) и картинка повисла.Универсальные игровые движки называются так, потому что они предназначены для общего использования, и в них заложены функции, которые не всем нужны. Это неизбежно приводит к "раздуванию" кода, и к замедлению производительности игр.
Есть и обратная сторона медали. Качественные современные движки предлагают хорошие оптимизации для конкретных случаев (например в зависимости от того, какую версию OpenGL поддерживает видеокарта будут использованы разные API - на современных системах какие-то вещи будут работать быстрее). Также, если мы говорим о высоко-реалистичной графике, то туда соваться без готового движка это вообще смерть. Люди там годами только реалистичную воду или деревья создают.
Самое сложное при разработке игры было сохранять мотивацию и интерес на протяжении всех 20 месяцев
Вот за это мое уважение. Хотел бы иметь такую же способность
vadim100
23.04.2022 19:04Игра смотрится хорошо на видео. Странно, что вы закончили разработку в 2017 и до сих пор не сделали мобильную версию игры. Зря однако. На ПК в такие казуальные игры мне кажется не играют особо.
leominder
24.04.2022 10:18Классная работа! Но ещё нужна кроссплатформенность и мультиплеер, хотя бы игра за одним компом вдвоём.
Seruios
24.04.2022 20:51-2Чел, ты серьезно? Извини, я вряд ли вернусь сюда, Но, ты слышал про Unreal engine 5?) Он хоть и универсальный, но с новыми разработками говорят что он вообще не лагает, автоматическая оптимизация, не важно насколько большие модели будут в плане полигонов. А ты тут свой движок писал 20 месяцев. Это все равно что написать Виндоус заново, хотя он уже есть 20+ лет и у тебя не будет лучше.
vadim100
25.04.2022 09:26+1Можно было бы критиковать, если бы автор бы начал писать движок и бросил на полпути, что постоянно происходит. Он же довёл работу до конца и выпустил уже 6 своих игр на нём. Если рождается что-то новое можно это только приветствовать.
FloorZ
25.04.2022 04:25а сколько весит билд со сценой без ассетов?
Когда писал свой движок, у меня только интерпретатор рантайм-скриптов весил over 20mb.
А когда взял исходник готового движка, того же acid или godot engine, выходной инарник выходил меньше и шустрее.
Как по мне, самодельный движок нужен только, и только, если задача к игре стоит специфичная.
Например воксельная механика или в рантайме очень быстро сплитить меши, или еще какая нибудь не стандартная задача, тип не эфклидовой геометрии..
pecheny
Статью уже видел, но аккаунт только на хабре, задам накопившиеся вопросы.
Под мобилки пробовали собирать?
OpenAl динамически линкуете?
Для воспроизведения музыки санвоксовский же рантайм используется? Всегда было интересно потыкать, но никогда руки не доходили попробовать. Особенно, собрать под мобилы.
Вопрос про опенсорс уже поднимался, выскажу мнение: чтоб поделиться, причесывать и документировать совсем не обязательно. Все равно может быть полезно: взять готовые экстерны для санвокса, поэкспериментировать с IQM…
kircode Автор
На мобильные собирать пока не пробовал, но такая возможность в теории есть, так как Haxe/Lime кроссплатформенный.
OpenAL-Soft входит в состав Lime, который сам по себе open source и линкуется динамически.
Нет, музыка и все звуки — в формате ogg.
Спасибо, подумаю.