Road Run, или как я свою первую игру делал. Часть 1
Разработка игры это очень интересно и увлекательно, а ещё это красиво, и наличие подобного проекта украсит любое портфолио. Здесь я хочу поделиться полученным опытом в ходе решения этой задачи, какие инструменты я использовал и какие цели перед собой ставил.
Введение
Однажды я захотел написать игру, вернее даже, дело было так, мне стало интересно, как же пишутся игры. Работая программистом встроенных систем, я уже представлял, как пишутся программы и приложения, мог даже что-то написать сам, но вот с какой стороны подойти к разработке игры, с чего начать я представлял довольно смутно. Итак, я начал поиск ответов.
Некоторые самоучители по языкам программирования, по которым я пытался освоить написание кода ещё в студенческие годы, предлагали на ряду со всякими калькуляторами и органайзерами написание простой игры для закрепления пройденного материала. Игру предлагалось писать в не самых удобных для такого занятия комплектах разработчика, например Visual Studio, что не сулило ничего перспективного по крайней мере для меня, код быстро усложнялся, а результат был в стиле бегающего по экрану квадратика. Было ясно, что использовать только Visual Studio для этих целей у меня не получится.
Я стал собирать информацию о том, как в действительности пишут игры, а именно об увлекательном и захватывающем мире игровых движков и трёхмерных моделей.
Игровые движки
Из множества доступных в глобальной сети игровых движков я познакомился с двумя: Unreal Engine и Unity 3d, оба из которых популярны и хорошо документированы, выбор сделал в пользу последнего лишь потому, что в качестве основного языка программирования в нём используется мною очень любимый C#.
Игровой движок Unity 3d имеет бесплатную версию, на официальном сайте есть все необходимые инструкции по установке и подробная документация на русском языке. Кроме документации есть ещё и обширная образовательная программа с уроками и примерами, включающими в себя бесплатный раздаточный материал: код, модели, звуки, спецэффекты и прочее, изучать его приятно.
Модели
Одной из самых важных составляющих игры является графика, без неё игра будет всего лишь текстовым квестом, следовательно мне надо было решить вопрос, где брать или как делать модели, которые будут представлять пользователю мир моей игры.
По сути передо мной был выбор из трёх вариантов: купить готовые, скачать бесплатные или сделать самому. От покупки я отказался сразу, во-первых, не было смысла вкладывать деньги в то, что вряд ли принесёт прибыль, во-вторых, у меня не было чёткого представления о том, как должны выглядеть модели. Необходимого количества бесплатных моделей у которых совпадал бы стиль я тоже не нашёл, оставался только третий вариант.
Мой выбор пал на blender, как на бесплатный и бурно развивающийся редактор трёхмерной графики.
Три кита
Три кита: графика, код, публикация. Почему так? Это моё личное мнение ни в коем случае не претендующее на истину в последней инстанции: любая игра имеет как графическую составляющую, так и код управляющий игрой, но нет смысла переводить время на создание игры, а времени уйдёт много уж поверьте, если никто её не увидит. Даже для включения разработанной игры в собственное портфолио, её придётся где-то опубликовать.
И как в предыдущих случаях, основное требование к месту публикации игры — отсутствие каких-либо платежей за размещение контента, здесь я решил остановить свой выбор на портале itch.io, на нём можно бесплатно размещать свои творения, и как бонус у него есть собственное приложение — магазин с играми, которое работает подобно таким магазинам, как steam, origin и прочие, что сильно упрощает установку игр для конечного пользователя. Зарегистрироваться на itch.io не составляет проблемы, банковскую карту регистрировать необязательно, если игра будет распространяться бесплатно.
Концепция игры
Когда только начинаешь писать игру хочется создать что-то необыкновенное с интересными механиками, захватывающим сюжетом, разветвлённой системой прокачки персонажа и интерактивным миром, думаешь о таких жанрах как «стрелялка», РПГ или стратегия, но я решил остановиться на жанре «раннер» ибо опасался, что даже «раннер» может быстро выйти за пределы моих возможностей. Это основная проблема любого проекта, который делаешь в одиночку — рассчитать свои силы и оценить свои возможности, у меня не было желания провозиться пару лет с проектом, а потом бросить его поняв, что нужно ещё как минимум в два раза больше времени, чтобы его закончить.
По вышеприведённой причине я постарался максимально упростить себе задачу, но при этом выполнив следующие условия: игра должна иметь законченный вид, а не выглядеть как какой-нибудь тестовый или демонстрационный уровень, в ней должны быть: основное меню, система сохранения прогресса, статистика по достижениям игрока, настройки, прокачка персонажа игрока, инвентарь и магазин.
Уровень решено было сделать один с постоянно генерирующейся дорогой на которой будут располагаться препятствия и награды. Игрок по дороге передвигается на автомобиле, избегая препятствий и собирая награды. Автомобиль как персонаж игрока был мною выбран в том числе и потому, что я хотел работать с как можно меньшим числом анимаций, а антропоморфная модель потребовала бы как минимум анимации ходьбы, бега и столкновения с препятствием. Для автомобиля тоже надо было делать анимации поворота, разгона и торможения, но они всё же проще.
Игроку на выбор на дороге предоставлено три полосы, по которым он может двигаться, на полосе может находиться препятствие, награда или ничего не быть, более двух полос одновременно препятствиями заняты быть не могут. Если происходит столкновение, игрок теряет одну жизнь, в начале игры даются три жизни — три попытки, когда они израсходованы игра заканчивается.
Просто кататься по дороге, уворачиваясь от препятствий, не очень интересное занятие, поэтому я решил разнообразить игру следующими задачами и возможностями:
монеты — которые можно собирать двигаясь по дороге, они пригодятся для покупок в магазине
канистры — для ускорения автомобиля требуется топливо, если оно закончится, автомобиль перестанет ускоряться
батареи — энергия в игре необходима для питания системы управления автомобилем, если аккумулятор сел, то перестроение из полосы в полосу будет происходить медленно, когда аккумулятор заряжен, смена полосы движения происходит намного быстрее, но при этом тратится немного заряда, поэтому лучше собирать попадающиеся по пути батареи либо иметь одну-другую в запасе
Возможность получения награды и предметов, необходимых для комфортного движения, делали игру более интересной, но этого было недостаточно, нужно было придумать хоть какое-то объяснение не столько, почему игрок вообще движется по этой дороге (какая разница, может ему просто захотелось прокатиться), а почему он должен ехать быстро, создать для него стимул двигаться всё быстрее и быстрее, а не медленно ехать, аккуратно объезжая препятствия. Я решил ничего особого не изобретать, а пойти по самому простому пути — полицейской погони.
Скорость движения автомобиля по дороге можно контролировать — замедлять или ускорять, если автомобиль замедляется ниже определённой скорости, полиция начинает его нагонять, если же скорость автомобиля выше — то погоня отстаёт. Порог скорости, движение медленнее которого приводит к поимке, со временем увеличивается, усложняя жизнь игроку, что обеспечивает рост сложности игры со временем. Текущее состояние преследования отображается звёздами в верху в центре экрана: когда горят красные звёзды — погоня находится далеко, если полиция нагоняет игрока, красные звёзды гаснут, а синие наоборот — загораются.
Для защиты от преследования можно использовать щит, который активируется, когда погоня настигает игрока. Он замедляет погоню, давая игроку возможность разогнаться и уйти от неё. Щиты можно как купить в магазине, так и подобрать на дороге, купленные в магазине щиты хранятся в багажнике автомобиля, который является инвентарём игрока, и не сгорают при окончании игры, в то время как подобранные на дороге отображаются на крышке багажника и могут быть использованы только в текущей гонке, если игра заканчивается (игрок проиграл или вышел из игры), то они сгорают.
Меню инвентаря я решил сделать списком элементов и не стал сильно усложнять его функциональность, каждый элемент меню делится на три части: графическое изображение элемента инвентаря, его описание и кнопка продажи, если надо освободить место в инвентаре и заработать немного монет.
Инвентарь
На первых порах я решил избежать учёта размера и веса предметов в инвентаре, так как подобные игровые механики, если их можно так назвать, потребуют учитывать влияние веса содержимого багажника на динамику автомобиля, а это в свою очередь потребует создания механизма увеличения мощности двигателя автомобиля, иначе получится, что бороться с негативным эффектом от увеличения багажника будет особо не чем.
Всё вышеперечисленное потребовало бы и дополнительных моделей, и дополнительного кода, это как раз тот момент, когда стоит себя ограничить в желаниях, иначе подобными темпами объём работы быстро выйдет за рамки моих возможностей. В итоге, решил я всё это оставить для будущих обновлений.
В магазине на собранные на дороге монеты можно приобрести товары, которые призваны помочь игроку игроку проехать как можно дальше, избежав поимки. Такими товарами являются: батареи различной ёмкости, канистра с бензином, магнит, щит, а так же «жизнь» и комплект для улучшения характеристик автомобиля («апгрейд»). Меню магазина разделено на три части: в центральной части расположены товары и кнопка выхода из магазина, с права — описание выбранного товара, левая часть сообщает игроку о количестве имеющихся монет и наличии свободного места в багажнике, здесь же можно посмотреть оставшийся заряд аккумулятора и количество топлива в баке, чтобы принять взвешенное решение о необходимости приобретения топлива или батарей.
Магазин
После покупки комплект улучшения автомобиля (красный сундучок), как и любой другой товар, перемещается в багажник автомобиля, его (комплект) нужно применить в мастерской, где игрок может выбрать какую характеристику автомобиля стоит улучшить.
Улучшения я изначально делать не планировал да бы не сильно затягивать проект, но по мере разработки игры всё же решил, что возможность изменять характеристики автомобиля стоит сделать хотя бы в зачаточном состоянии, так и игра интереснее, и задел для будущего развития есть.
На первый раз я выбрал только три направления для улучшения автомобиля: багажник автомобиля, магнит и щит. В первом случае увеличивается количество предметов, которые могут находиться в багажнике. «Апгрейд» магнита позволяет продлить время его действия с начала активации, а «апгрейд» щита поможет снизить потребление энергии при его (щита) активации, что позволит пользоваться щитом даже при малом заряде батареи.
Меню улучшений
Меню улучшений автомобиля состоит из четырёх элементов, верхний элемент зеленого цвета отображает количество доступных игроку комплектов для улучшения автомобиля, ниже следуют элементы синего цвета, каждый из которых отвечает за определённую ветвь улучшения. Синие элементы содержат значок и описание улучшения, прогресс улучшения — поле со знаком «Главная дорога», которое показывает сколько комплектов было установлено на этой ветви улучшения, и кнопку «Upgrade» для установка улучшения. После установки отменить улучшение и вернуть комплект нельзя.
Три направления для улучшения характеристик автомобиля — не очень много, поэтому в планах у меня стоит добавить улучшения, которые будут повышать мощность автомобиля, запас его хода, тормозные характеристики и многое другое.
Трёхмерные модели
Хочу немного коснуться процесса создания трёхмерных моделей, так как я решил делать всё самостоятельно, включая и модели, то не поговорить о том, как я их делал не могу, иначе рассказ мой будет не полным. Прошу строго меня не судить, я не цифровой художник или 3д дизайнер, и способы, которыми я решал эту задачу, профессиональными назвать наверное нельзя, некоторые из них вообще могут показаться откровенно странными, но задача была решена, значит методы как минимум работают и может быть кому-то пригодятся.
Автомобиль двигается по дороге, поэтому первое (и самое лёгкое) чем я занялся была дорога или, если быть точным, её сегмент. Текстура для дороги была нарисована в редакторе растровых изображений (я использовал Krita), с мышкой и тачпадом у меня ничего не вышло, поэтому рисовал я на графическом планшете размера А5, для моих задач его размера хватило с головой.
Тогда я был в самом начале разработки игры и ещё слабо представлял какими следует сделать пропорции сегмента, сделаешь сегмент слишком маленьким, дорога получится слишком уж одинаковой, сделаешь слишком большим — может пострадать производительность. После небольших экспериментов в графическом редакторе пропорции дороги получились следующими: ширина — 1.3, длина — 10, ширина каждой полосы 0.3 единицы, всего полос три, ширина обочины 0.2 единицы, обочин — две, три полосы плюс две обочины в сумме дают 1.3. Длина сегмента дороги была выбрана произвольно.
Текстура дороги
Трёхмерной моделью дороги является плоскость, состоящая из двух треугольных полигонов, на которую я и наложил нарисованную текстуру. В блендере делается это довольно просто: запускаем программу, в открывшемся окне выбираем рабочее пространство «layout», рабочие пространства в blender находятся в самом верху окна с правой стороны от основного меню, нажимаем в нём комбинацию клавиш «Shift + A» и в открывшемся контекстном меню выбираем пункты «Mesh», а в нём выбираем «Plane», плоскость создана.
Для придания только что созданной плоскости требуемых размеров можно воспользоваться следующими командами: на клавиатуре нажать кнопку «S» для входа в режим изменения размера, затем кнопку «Х», чтобы размер будет изменяться только по оси Х, и ввести значение »1.3», для подтверждения действия нажать «Enter» — ширина задана. Длину можно задать такой командой: нажать кнопку «S», за ней — кнопку «Y» и ввести значение »10», плоскость получит требуемую длину. Если при нажатии кнопки «S» ничего не происходит, то следует щёлкнуть левой кнопкой мыши на плоскости, сделав её активной, плоскость в этом случае выделится оранжевым цветом.
В окне свойств, которое обычно находится в правой части основного окна программы, выбираем вкладку «Свойства материала», на которой создаём новый материал нажатием на клавишу «New».
Создание материала для модели
ак только материал создан, в него можно добавить нарисованную ранее картинку. Сделать это не составляет большого труда: переходим в рабочее пространство «Shading», в нём будет окно «Shader Editor», где при помощи узлов «nodes» можно настроить свойства материала, здесь нажимаем уже известную нам комбинацию «Shift + A», в выпадающем меню выбираем «Texture → Image Texture» и создаём узел «Image Texture».
В только что созданном узле нажимаем кнопку «Open» и в появившемся диалоговом окне выбираем картинку, которую будем использовать в качестве текстуры. Теперь надо подсоединить узел с картинкой к остальным узлам материала, так как материал был только создан, у него их всего два. Соединяем выход «Color» узла с текстурой со входом узла «Diffuse BSDF», и на этом редактирование материала можно считать оконченным.
Может потребоваться отредактировать развёртку, если текстура не правильно отображается на поверхности модели, в моём случае, развёртку необходимо было повернуть на 90 градусов. Для этой задачи можно использовать рабочее пространство «UV Editing», в котором внимание следует обратить на два редактора: «UV Editor», расположен слева, и »3D Viewport» — справа.
Рабочее пространство «UV Editing»
Редактор «UV Editor» позволяет работать с развёрткой трёхмерной модели и накладывать её на изображение, которое мы хотим отобразить на гранях модели. Это изображение и будет являться текстурой. В редакторе »3D Viewport» можно наблюдать, как изменяется окраска граней модели в зависимости от изменения размера, ориентации и положения её развёртки.
На изображении рабочего пространства «UV Editing» видно, что текстура дороги на плоскости модели отображается неверно, полосы в правом редакторе идут поперёк дороги, а должны бы идти вдоль дороги, как на загруженной в левом редакторе картинке. Если в редакторе «UV Editor» не отображается картинка дороги, то её следует выбрать в выпадающем списке вверху редактора, в нём находятся все загруженные или сгенерированные в blender изображения, сохранённые в файле, с которым осуществляется работа в текущий момент времени.
Чтобы исправить положение, нужно сначала повернуть развёртку на 90 градусов, для чего в редакторе слева следует выделить всю развёртку целиком, она должна окраситься оранжевым цветом, а не серым, затем нажимаем «R»,»9»,»0» и «Enter» на клавиатуре — развёртка поворачивается. Здесь надо быть внимательным и смотреть, чтобы курсор мыши находился над полем левого редактора, иначе, если курсор будет над редактором »3D Viewport», вращаться будет не развёртка, а сама модель.
Развёртка повёрнута, а изображение на модели стало ещё меньше походить на дорогу, что и не удивительно, хоть направления развёртки дороги и изображения дорожного полотна теперь совпадают, но их пропорции сильно отличаются: развёртка намного шире и короче чем полотно.
Надо всего лишь совместить развёртку с изображением не поворачивая его, для чего необходимо увеличить размер развёртки по оси «Х» и уменьшить по оси «Y». Нажимаем кнопку «S» на клавиатуре и затем одну из кнопок «Х» или «Y», чтобы выбрать по какой из осей должен меняться размер, если не нажать ни одной из двух кнопок, то размер будет меняться сразу по двум осям, что в данном случае не требуется. Размер меняется либо при помощи ввода числа с клавиатуры, либо движением мыши, как только размер развёртки будет соответствовать желаемому нужно нажать «Enter», и изменения будут применены. Я воспользовался вторым способом и подогнал размер развёртки так, чтобы она полностью покрывала картинку с полотном дороги, изображения в обоих редакторах выглядят одинаково, теперь текстура на модель наложена правильно.
Модель готова и всё, что осталось — это загрузить её в игровой движок «Unity 3D», для чего получившуюся модель надо сохранить в том формате, который понимает выбранный игровой движок. Здесь, правда, есть пара нюансов о которых я считаю нужным упомянуть.
Формат файлов с трёхмерными моделями, который понимает Unity — это ».fbx», чтобы сохранить модель в этом формате в blender нужно открыть меню «File», в нём выбрать пункт «Export», где уже можно будет выбрать тот формат, в котором должна быть сохранена модель.
Если модель экспортировать прямо сейчас, то в .fbx файле будет сохранена только сама модель без текстуры, потом текстуру придётся экспортировать в игровой движок отдельно, и уже внутри движка накладывать её на модель. В этом нет ничего страшного, когда модель простая и имеет малое количество текстур, но вот в случае больших и сложных моделей раскладка текстур по слотам разнообразных материалов может занять довольно продолжительное время, поэтому лучше сделать так, чтобы вся необходимая графика была сохранена внутри файла до начала экспорта.
Такие данные как текстуры обычно не хранятся внутри самого файла блендера (файл с расширением ».blend»), а хранятся отдельно, и могут быть как в общей с «blend-файлом» папке, так и в любом другом каталоге на усмотрение разработчика. Чтобы текстура оказалась внутри файла нужно её туда упаковать, делается это следующим образом: в меню «File» нажимаем на пункт «External Data», и в выпавшем подменю выбираем пункт «Pack Resources», теперь текстура с изображением дорожного полотна сохранена внутри файла с расширением ».blend».
Подготовительные операции завершены, можно приступать к экспорту в формат FBX. Для этого в меню файл следует выбирать пункт «Export», а в нём пункт «FBX (.fbx)», на экране появляется окно «Blender File View».
В окне «Blender File View» внимание следует обратить на два поля, роль нижнего из них вполне очевидна — ввод имени будущего fbx-файла, в том же, которое находится вверху справа и именуется «Path Mode» выбирается способ хранения графической информации. Я выбрал «Copy» — скопировать файлы текстур, и нажал на кнопку справа от выпадающего меню, она после нажатия должна подкраситься синим цветом, как показано на картинке. Нажатие этой кнопки даёт команду блендеру встроить текстуры внутрь файла, когда будет нажата кнопка «Export FBX», все текстуры будут сохранены внутри файла .fbx.
В правой колонке немного ниже находится секция «Include», внутри которой есть раздел «Limit to», в нём я установил галочку только напротив пункта «Selected objects», с остальных пунктов галочки я снял, таким образом экспортированы должны будут только выделенные объекты, а не всё, что есть в ».blender» файле. В .blender-файле помимо самой модели дороги ещё присутствовали источники света для лучшего понимания того, как будет выглядеть дорога при различных настройках материала, отображающего текстуру этой дороги, и камера, при помощи которой можно генерировать изображение дороги с разных ракурсов. В игровой же движок я хотел экспортировать одну лишь модель дороги без всего лишнего, поэтому прежде чем начать экспорт, я выделил только модель дороги, сняв выделение с любых других объектов.
Остальные настройки я оставил как было, ничего в них не меняя. Нажал на кнопку «Export», и .fbx-файл с моделью и текстурой был готов.
Заключение
Очень надеюсь, что статья была как минимум интересна, а кому-то может быть даже полезна,. Игру, описываемую в статье, можно скачать тут, так же удобно воспользоваться приложением для загрузки и установки игр с itch.io, которое скачивается здесь.
Во второй части постараюсь рассказать о создании моделей для окружающего игрока мира, запекании процедурных текстур и теней.