История про то, как я решил заняться разработкой игры без знаний и опыта в этой области, без движка и вложений. Зачем мне это? Зачем это кому-то другому? О провалах и успехах, о начале indie-разработки пост.
![](https://habrastorage.org/webt/bz/ws/bj/bzwsbjf6bk4drammvj83jrnwqbk.png)
Всем привет! Меня зовут Рома и я несколько лет разрабатываю для embedded на, прости господи, С/С++. Программирование для меня чуть больше, чем работа. Отсюда и желание иметь какой-либо собственный проект, который будет расти, а с ним и мой профессионализм. Я в это верю, во всяком случае. Было перепробовано много языков и технологий, было много идей и столько же провалов. Думаю, кто-то узнал себя. В этом посте будет рассказано о старте разработки компьютерной игры на С++ с использованием OpenGL. Далее будет про следующее:
- Сложности, возникающие передо мной и подходы к их решению.
- Обзор используемых технологий и средств разработки.
- Ссылки на использованные ресурсы в сети.
Чего далее не будет:
- О тонкостях разработки на C++. Язык будет упомянут с той степенью абстракции, чтобы его можно с легкостью заменить на другой, нативно поддерживающий ООП.
- О готовых движках и их использовании. Ничего не имею против, я даже ЗА. Но пост о другом.
- О великолепной картинке, использующей шейдеры последнего поколения. До этого пока далеко.
Итак, пост об авантюризме и искусстве. Описанный в конце поста подход к разработке мне кажется как минимум не каноничным. Тем не менее, я думаю, что у него есть право на существование. Если Вы дочитали до этого места и Вам нравится конструировать из палок и го подручных средств, то Вы не будете разочарованы.
Старт и провал
Краткий обзор инструментов для разработки 2D-игры без какого-либо движка показал, что сразу предстоит выбор фреймворка для обработки мыши, клавиатуры, а также поддержки аудио и отображения графических примитивов. Выбрана была библиотека SFML. На знакомство ушло около недели, было кое-что набросано: по прямоугольному полю ездили танки и убивали друг друга, была возможность строить их фабрики и тому подобное в духе RTS начала 2000-х. Это показалось унылым и захотелось 3D. О 3D я знал меньше, чем javascript о безопасности типов. Гугл первым выдал OpenGL, который выходит из моды. А также про рекомендации использовать так называемый Core Profile этого OpenGL. Кто я такой, чтобы писать по устаревшим методикам? Из попыток скрестить Core Profile c SFML выяснилось, что SFML именно этот профиль одновременно с использованием своего графического модуля не поддерживает. Это был сильный удар по морали, так как на изучение SFML были потрачены ресурсы. К тому же не вся кодовая база была абстрагирована от графической библиотеки.
GLFW и новая надежда
Как следует из названия раздела, Core Profile OpenGL и GLFW прекрасно уживаются. Основной ресурс, используемый мной по OpenGL. Да-да, без VPN скорее всего не откроется, спасибо защитникам рунета. Вспомогательный. Через неделю-две по экрану будут плавать простые геометрические элементы с текстурами. Переход на GLFW с SFML научит кого-то угодно ценить Dependency inversion principle (D в SOLID). В результате на свет появилось это
![](https://habrastorage.org/webt/kq/g8/yg/kqg8ygc7zv5tgxujqf_q8gphqi4.png)
У меня не было иллюзий относительно эстетической стороны вопроса, однако прототип был жив. Да, он был некрасив, но все знают известную сказку. Настроение поправилось. На тот момент была решена самая сложная на сегодня для меня задача: создание модели с анимацией. Задача была разбита на подзадачи:
- Создание анимации в редакторе, например, в Blender.
- Экспорт в поддерживающий анимацию формат, например, Collada.
- Импорт на C++, например, с библиотекой Assimp.
- Проектирование классов и их реализация, используя OpenGL.
Таким образом, танки получили вращающуюся башню.
Когда горд работой, но стыдно её показать
Да, сегодня не все могут по-достоинству оценить великолепно спроектированные абстракции, особенно когда их нет. Нужно было что-то, что бы радовало глаз. Этим чем-то стал процедурный ландшафт. Генератором стал давно всем известный, но не мне, шум Перлина. Выяснилось, что есть параметры, требующие эмпирического подбора. Перекомпиляция – это удар по психике, поэтому появилась потребность в GUI для прототипирования. Результатом поиска стала блестящая библиотека ImGui. С ней численные параметры, цвета, режимы отображения настраивать одно удовольствие. Итог работы получившегося генератора
Немного тумана
Отображение тумана на заданной высоте с заданной насыщенностью выполняется во фрагментном шейдере с помощью эмпирически-подобранной функции. При необходимости можно добавить несколько слоев тумана со своими параметрами, включая цвет. Пример ландшафта до и после наложения имитации тумана:
Тот момент, когда понадобились алгоритмы
Да, это случилось. Второй раз за 5 лет. Речь о поиске пути между двумя точками при наличии препятствий, ведь не могут же наземные юниты передвигаться по горам! На помощь приходит алгоритм A*. Псевдокод брал отсюда. Реализация требует профилирования и оптимизации, как и много где ещё, однако в текущем варианте юниты объезжают препятствия, если путь вообще существует. Где-то в этот момент оформилась идея игры.
Космос, который мы…
Рабочая идея, которая будет эволюционировать – освоение планеты первопроходцами. Создание био-, атмо-, и в конечном итоге, экосферы. Приведу пример. Первоначально жизнь будет возможна лишь внутри искусственно созданного купола, внутри которого можно будет выращивать живое: растения, животных. Они в свою очередь будут воздействовать на ландшафт. Далее представлен пример купола и ландшафта под ним через N и M итераций, N < M.
О Меркаторе, Земле и политике
Плоский ландшафт – уже что-то, но всего лишь один из взглядов на планету. Куда привлекательней, с моей точки зрения, смотреть на более реальное космическое тело. Время картографии!
Если о том, что прямоугольник натянуть на сферу без искажений нельзя, я подозревал, то количество способов отображения стало откровением. Наиболее распространённая проекция Меркатора имеет проблемы с отображением у полюсов и сильно искажает пропорции при удалении от экватора. Да так, что кажется, что РФ больше Африки, а США — Австралии.
Аналитически подсчитана может быть, как оказалось, также и мера искажения. Грубо говоря, окружность на плоскости становится эллипсом на сфере и наоборот. Задача получилась следующая: к плоскому виду добавить вид на шарообразное тело. Отсюда проблема – какой вид выбрать за основной, а какой отображать с искажениями. Решено было отображать без искажений плоский вид как вид допускающий больше операций, включая выделение и перемещение юнитов. Вид на шарообразное тело оставлен для операций с летательными аппаратами, например, искусственными спутниками. В качестве отображения используется Gall stereographic projection как одно из компромиссных. Искажения подсчитывались при помощи эллипсов искажения, они же индикатрисы Тиссо. В результате можно видеть следующее: на скриншоте представлен вид на планету как на шарообразное тело с двумя куполами, один из которых питает два источника энергии, другой – один источник.
Программные модули и цикл разработки
Задачей-минимум на этапе “Начинать ли вообще?” было следующее: эволюционировать от простого к сложному и красивому в течении года. Крайне легко за пару недель от любви к проекту дойти до отвращения. У меня на это пять причин:
- Первая причина это код. Без поддержки вменяемой архитектуры и рефакторинга, большая часть времени будет багфиксом, а какая в нём радость?
- Недостаточная концентрация на одном. Занимаясь час алгоритмом, час — моделью в Blender, мне не добиться цели.
- Излишняя концентрация. Занимаясь движком и алгоритмами долгое время, картинка не меняется и кажется, что прогресса нет.
- Сложность в освоении инструмента. Богатство интерфейса Blender или API OpenGL внушает уважение, если не страх. От старта до первого proof of concept может пройти несколько дней, что сильно бьет по морали.
- Завышенные ожидания и неготовность к провалу. Порой сложно отказаться от подхода “Спроектировать, реализовать и не возвращаться” в пользу “Прототип/Реализация/Уточнение интерфейсов”
Являясь поборником TDD, должен сказать, что не вижу возможности его применять при таком проценте R&D. Буду рад, если Вы, уважаемый читатель, дадите мне повод усомниться.
На данный момент выделились следующие области разработки:
- Проектирование моделей в Blender.
- Реализация алгоритмов и математики, например, A* или Perlin Noise.
- Разработка “движковой” части. Под ней понимается, например, генератор ландшафта или импорт модели из Blender.
- Разработка модуля, ответственного за рендеринг.
- Разработка логики игры. Требуется, чтобы она использовала движок и модуль рендеринга.
- Рефакторинг.
В планах разделение модулей 2-5 на уровне библиотек с выделением фасада в каждой. Одна из возможных причин: добавление функционала по управлению камерой требует каскадной перекомпиляции большого количества исходного кода.
Практика показывает, что продуктивно получается работать, если фокусироваться на одной области в течении 5-10 часов. Меньше — фокус теряется, больше — замыливается глаз.
Периодически для достижения цели вижу возможным нарушать некоторые правила нормальной разработки, при условии, что будет помечено место нарушения и выделено время на рефакторинг. Последний случается раз в 7-10 дней. Пример: временно создаются глобальные переменные. От них избавлюсь, передав в конструкторы/методы при рефакторинге, что поможет выделить классы с низкой связностью и высоким зацеплением. Что повлечет новый виток рефакторинга. Плюсы подобного подхода:
- Готовность к реализации новых идей. Отказ от старых.
- Возможность эволюции интерфейсов.
Минусы:
- Рефакторинг может затянуться.
- Мне видится нереальным поддержка unit/mock тестов.
- Некоторые, преодолеваемые, сложности в Vim. Зачем Vim, если он добавляет минусы? Затем что плюсов для меня больше.
To be continued
Благодарю за внимание к моему скромному посту! Весь код здесь. Помимо описанных выше задач много времени ушло на знакомство с Blender, кастомизацию vim и рефакторинг в нем. Если было хоть немного интересно, напишите, пожалуйста. Могу более детально осветить что-то в одном из следующих постов. Видео с чуть большим количеством деталей по реализации тут.