На просторах интернета часто встречаются «команды», которые существуют уже годами, список разработчиков состоит из десятка персон, да ещё и «нужны все!». При этом никакой адекватной демки нет даже в ближайших планах. Глядя на это всё так и хочется сказать: «Да что же вы, блин, делаете?!». Но это деструктив. Мало раскритиковать. Нужно и позитивные примеры предоставить.
Эти размышления натолкнули меня на занятный эксперимент: в ноябре на gamedev.ru стартовал «конкурс леталок». Конкурс предполагал разработку в течении двух месяцев. Однако мне показалось, что это многовато. Поэтому я записался в участники… И забыл о конкурсе на полтора месяца.
Основная идея эксперимента — сделать полноценный проект за две недели. Срок завершения конкурса — неплохой дедлайн. К тому же последняя неделя конкурса совпала с концом новогодних праздников, что дало возможность не отвлекаться на другие задачи. Итак: конкурс, проект с нуля, две недели.
Если вам не хочется тратить время на всю статью — можете промотать вниз. Там обзор конкурсных проектов и кратенький вывод из всего этого эксперимента.
У нас есть две недели. Основной вопрос в том, что делать. Честно говоря, я изначально думал, что конкурс идёт до 7 января и планировал потратить на него только одну неделю.
Одна неделя — это не очень много, в связи с чем и был выбран жанр лаунчеров.
Лаунчер — это игра, всё действие которой происходит только на одном уровне. По сути, прохождение сводится к череде попыток пролететь дальше/выше. Каждая попытка (кроме последней) обречена на провал, но даёт очки, которые можно потратить на прокачку персонажа, чтобы он мог летать лучше. Игра заканчивается в тот момент, когда персонаж прокачан настолько, чтобы долететь до конца уровня.
Прекрасным представителем этого жанра является игра Butibo Bison.
Повторить геймплей именно этой игры я и планировал. Однако когда решил уточнить детали конкурса, выяснилось, что финал не 7, а 12. 12 дней! С этим уже можно работать! Будем делать 3D Action!
За основу возьмём несколько моих любимых игр: Вангеры, Механоиды, Ex Machine, Renegade Ops. Хочется сделать РПГ, но в такой короткий срок проработать прокачку не выйдет. Поэтому цель: за основу берём геймплей RenegadeOps/Вангеры, набор квестов — по аналогии с Ex Machine/Механоиды. Ну и чтобы не тратить время на продумывание вселенной, пусть игра будет во вселенной Механоидов. Тем более, что моё фактическое место жительство в 7 км от бывшего офиса SKYRIVER studios располагает к таким заимствованиям.
День первый
Что мы имеем? Фреймворк, на котором выпущено несколько 2Д игр. Из 3Д возможностей — только загрузка меша из файла. Ещё есть редактор ландшафтов. Используем его для создания игрового ландшафта. Задача на первый день:
Для этого нам понадобится 3Д камера. Она должна уметь устанавливать видовую матрицу и матрицу проекции. Класс камеры даже не пришлось писать, за годы разработки он у меня уже был сделан. Просто перетаскиваем камеру во фреймворк.
Следующая подзадача — перенести шейдеры из редактора в игру. Шейдеры лежат в открытом виде, всё что нужно сделать — убрать из них обработку инструментов редактора: подсветку края тайлов, динамический расчёт нормалей и прочие мелочи.
Основная подзадача, которая заняла большую часть дня — реализация класса, отвечающего за загрузку файла, содержащего ландшафт и передачу геометрии на рендер. Задача не слишком сложная, но пол дня заняла.
Итог работы:
И что же мы видим в результате? Ландшафт страшно шумит. Причина очень простая — при конвертации текстур я забыл прописать генерацию MipMap'ов. Но уже 11 часов вечера… Мелкая задача, но очень хочется спать.
День второй
На сегодня запланировано две задачи:
Первым делом включаю MipMap'ы, которые не включил вчера и выясняется, что в коде что-то генерирует OpenGL ошибку. Проверок в коде не очень много и ошибка вылезает при загрузке шейдеров. Грешу на криво перенесённые шейдеры из редактора… Потратил час, чтобы понять, что ошибка не в шейдерах… Оказывается, неправильно указал настройку текстур и в MAG_FILTER уходило значение GL_LINEAR_MIPMAP_LINEAR, которого там быть не должно. Исправляю на GL_LINEAR и всё заводится без проблем. А между тем потрачено два часа… Это очень много, учитывая что есть всего 12 дней.
Теперь займёмся моделями. Вообще, у меня уже есть загрузчик простых моделей. Но мало просто уметь отрисовывать модель на экране. Нужно, чтобы игра рисовала только те модели, что сейчас находятся в фрустуме камеры. Самый простой способ организовать это в нашем случае — разбить всё игровое пространство на квадраты, где квадрат примерно равен зоне, видимой на экране.
Ландшафт уже разбит на примерно такие квадраты, поэтому создаём менеджер объектов, который разбивает игровое пространство на квадраты в соответствии с настройками ландшафта и при отрисовке обрабатывает только те объекты, которые находятся не далее одного квадрата от камеры. То есть рисуется зона 3х3 квадрата, где центральный квадрат — это квадрат, в котором находится камера. Плюс менеджер объектов должен отслеживать перемещение объектов и в случае, если объект выехал за пределы своего квадрата, перемещать его в актуальный квадрат. Задача по написанию такого менеджера заняла около 5 часов.
Следующая задача — реализация карты теней. Но для карт теней нужна поддержка Render To Texture во фреймворке, которой у меня не было, поскольку ранее реализованные проекты не требовали пост эффектов, а RTT в 2Д, кроме как для пост-эффектов, нигде не используется.
Ещё час тратим на реализацию обёртки над FBO. Ничего особо сложного.
Приступаем к последней задаче второго дня — Shadow Maps. Всё бы ничего, но я приверженец Stencil Shadows… Всеми силами я всегда избегал прикасаться к Shadow Maps. Ну не нравились они мне. Но время идёт… в современных реалиях вообще нет ни одной причины использовать стенсильные тени. Слишком сильно падает их производительность с ростом сложности геометрии и разрешений экранов. Так что альтернативы нет — приходится взяться за реализацию карт теней. Конечно, я прекрасно знаком с теорией работы карт теней, хотя никогда их не реализовывал. Поэтому особых сложностей не жду. Взял давно отложенный на чёрный день мануал и по нему реализовал отрисовку теней.
Кстати, использовал этот мануал. Всем рекомендую. Грамотно и по делу всё расписано, в том числе и основные проблемы, вылезающие при реализации карт теней.
С мипмапами ландшафт стал выглядеть лучше, да и тени неплохо смотрятся.
День третий
Продолжаем прикручивать нужный нам функционал. На сегодня запланировано две задачи.
Начнем с LuaJIT. Качаем исходники и легко собираем dll под Windows. Пишем небольшой класс-обертку (не люблю luabind и аналоги, предпочитаю работать с lua через минимум прослоек). И, собственно, всё.
Попробовал собрать под Android… и в течение часа не смог этого сделать. Решил не тратить дальше на это время, потому что для конкурса это не критично, а в дальнейшем можно будет и отдельно заморочиться.
Вторая часть плана на сегодня — интеграция системы частиц. Я много и продуктивно работал именно с системой частиц Magic Particles от Astralax, поскольку действительно сложно найти что-то более мощное и простое в этой сфере. Плюс очень адекватный разработчик, что немаловажно при разработке проектов.
Однако меня остановил один не важный для конкурса, но важный для фреймворка момент. Дело в том, что фреймворк создаётся, в частности, для проектов под Windows CE. И, к сожалению, это чуть ли не единственная из распространенных ОС, которая не поддерживается MP. Это и понятно, игровой рынок на WinCE отсутствует как класс. Но для меня это важно, поэтому MP я решил пока не использовать…
От расстройства и прокрастинации пошёл играть в Burito Bison и потратил на это полтора часа времени.
Однако день ещё далеко не закончен. Едва перевалило за обед. Решил сделать стартовое меню. Сделал несложный ландшафт, поместил на него пару зданий и два вертолётика. И вылез баг с картами теней. Его хорошо видно на КДПВ на угловой стене слева под кнопкой «Выход». Однако решил этот баг не править — вид в игре не такой и на нём эти баги практически не видны. А правка альясинга теней обещает убить несколько драгоценных часов.
Сделал меню, интересно ездящее вверх/вниз. Получилось занятно. Добавил кнопки «Настройка» и «Продолжить», хотя прекрасно понимаю, что с большой вероятностью их функционал в рамках конкурса реализовать не смогу — не хватит времени.
Может создаться ощущение, что я потратил время на ненужную фигню — анимации менюшек. Но это не заняло слишком много времени, поскольку фреймворк умеет анимации для UI. Всего десяток минут потребовалось, чтобы указать — что и когда анимировать. Зато с анимацией меню стало гораздо интереснее.
День четвертый
План на сегодня:
Только в 16 часов дня я занялся задачами непосредственно из плана. До этого решал всякие задачи, которые к плану отношения напрямую не имеют, но выполнение плана нельзя было начинать пока их не закончишь. Одна из таких задач — спаун юнита. Например, вертолёта игрока… Спаун требует работающих скриптов, работающие скрипты требуют загрузки уровня и прописывания соответствующих функций, через которые можно управлять юнитами…
Дальше — больше. Сделал управление вертолётом и оказалось, что при нажатии на кнопку и движении мышью Qt начинает адски тормозить.
Я, как любой разумный программист, грешил на себя… Переписал внутреннюю систему обработки сообщений. Сделал проверку на дублирование сообщений… И это не помогло.
Ладно, я отказался от обычной системы сообщений и сделал считывание состояния клавиатуры и мышки… И это не помогло.
Я полностью отключил систему ввода в своём движке… И всё равно получил фризы. Сделал хук WH_GETMESSAGE на все сообщения, касающиеся ввода, с перехватом и отменой всех сообщений… Это не помогло. Ничего не осталось, кроме как исследовать систему вне моей среды разработки.
Разгадка оказалась простой… Я потратил три часа, исправляя баг, которого нет… Это Synergy тормозила, если зажимать несколько кнопок одновременно. Убрал Synergy и всё стало плавненько и аккуратненько.
В итоге не успел сделать наклон вертолёта в сторону полета. Вроде бы мелочь, но ведь важная… Но всё же не настолько важная, чтобы тратить на неё время сейчас. Тем более, что уже 11 вечера 4 января… Прошло 4 дня, а я только вертолёт запустил полетать. Так что стрельба, стрельба и ещё раз стрельба.
В два часа ночи я записал видео. Ракеты не успел. Но решил, что сейчас они не так важны, как сон.
День пятый
Задача на сегодня — сделать игровую локацию.
У меня есть десять зданий, который были куплены на 3drt.com для другого проекта. Сначала я примерно расписал сюжет игры, далее составил список зданий и прикинул, какое здание какую роль может выполнять в игре. Что похоже на шахту, что похоже на главную базу и т.д.
В редакторе ландшафтов примерно набросал игровую зону:
На каждой точке сделал подпись, состоящую из названия и порядкового номера используемой модели.
После этого нарисовал границы игровой зоны с помощью гор и пару непроходимых гор нарисовал в середине карты, чтобы игрок напрямую летать не мог.
Следующий этап — придание неоднородности ландшафту и прокладывание дорог. Т.к. времени очень мало — выделил на всё три часа. Этого времени хватило только на то, чтобы создать минимально играбельный ландшафт. На какие-то художественные изыски времени не осталось.
Следующая задача — расстановка объектов и задание зон проходимости. У меня нет подходящего 3Д редактора для фреймворка, т.к. фреймворк всегда был 2Д и все проекты на нем были 2Д. К счастью, у меня есть редактор, созданный гораздо раньше для 3Д проектов. Он достаточно сложный и имеет сложный формат сохранений. Да и писался он для совершенно другого движка, поэтому напрямую использовать его не получится. Однако, на сегодня это не важно. Создаем в этом редакторе локацию.
В редакторе я расставил объекты и нарисовал зоны:
Моменты на видео, когда весь ландшафт раскрашен в красно-зелёное — это, собственно, редактирование зон.
День шестой
План:
У нас есть локация в редакторе, который не предназначен для работы с нашим игровым движком.
Я решил не заморачиваться с загрузкой его сложного формата в игре и сделал простую вещь: добавил в редактор возможность сохранения сцены в виде текстового файла.
Дальше локацию сохранил в текстовый файл. Получилось что-то вроде:
Дальше пишем простенькую утилиту, которая из сложного текстового файла с кучей объектов и свойств выдирает только нужные непосредственно в игре и сохраняет в удобоваримом формате.
Дальше нам нужно загрузить зоны и объекты. Объекты-декорации просто добавляются в менеджер объектов, написанный ранее, и игра о них забывает, а остальные объекты создаются в обычном порядке.
В общем-то конверт и загрузка локации заняли достаточно маленькую часть дня. Больше всего времени ушло на реализацию функционала турелей. Работают они просто: если игрок выстрелил в безопасной зоне, то активируется таймер на 15 секунд, в течении которого все турели, в радиусе поражения которых находится игрок, открывают по нему огонь.
День седьмой
У меня уже есть искусственный интеллект, который умеет выполнять разные функции.
Делался он несколько лет назад, когда была идея реализовать конкурс ИИ. Собственно была реализована 2Д модель мира механоидов с их правилами. Торговцы получали очки за доставку товаров, охранники — за сопровождение торговцев, охотники — за привезённые головы, мародеры — за украденные (не купленные) и проданные товары.
Как работал этот ИИ можно посмотреть тут:
Круги — это живые юниты.
Красные буквы — это мёртвые юниты.
Чёрные кресты — это груз.
Две команды — зелёные и красные. Активно пытаются изображать живой мир.
ИИ в лоб перенести не получится. Дело в том, что в мире механоидов юнит — это нечто парящее и стреляющее перед собой. То есть нет проблемы с радиусом поворота, есть возможность двигаться боком. В этом проекте ситуация другая: юнит — это наземное транспортное средство с колёсами и всеми вытекающими проблемами.
Весь день был потрачен на то, чтобы сделать ИИ.
Видео для этого дня нет. Связано с тем, что к концу дня всё ещё нечего было показывать. Результатом работы в течение седьмого дня стала возможность создавать юниты с помощью текстовых файлов (уже вне конкурса был создан редактор для этих дел).
Конфиг обычного юнита выглядит примерно так:
За день игра научилась парсить это всё и загружать данные. Конфигов подобного рода, на самом деле, не один, а два. Второй — для описания турелей, которые ставятся на юнита. В данном случае ставится турель GUN_TURRET_1.
Как можно понять — это 7 января, Рождество. И семейная традиция — собираться вместе со всеми родственниками в родительском доме… Поэтому так мало сделано — большую часть дня я провел в кругу семьи.
День восьмой
Юниты научились ездить и атаковать. Также преследуют противника в зоне видимости. Основная часть работы была посвящена передвижению.
Амортизаторы прикручивать не стал. Час ночи… Из-за отставания по срокам седьмого января — категорически выбился из плана. Так что объезд препятствий — в топку… В ту же топку и физическое взаимодействие между юнитами… И подвеску техники тоже туда же… Особенно печалит последнее. Без расчета подвески юниты жёстко повторяют ландшафт и выглядит это не айс. Но функционал свой выполняют, так что оставляем так.
День девятый
В игре планировалось четыре вида ИИ:
Торговцы — покупают товар и продают в другом здании.
Охранники — следуют за торговцами и атакуют противника, если видят.
Охотники — курсируют по карте и атакуют противников, периодически отвозя на базу головы убитых врагов и друзей.
Мародеры — курсируют по карте и атакуют в первую очередь торговцев, периодически отвозя на базу подобранные товары.
Сделаны три вида ИИ. Мародеров делать не стал, потому что нет товаров. Вернее товары есть. Торговцы закупаются ими и продают. Но решил не делать вываливание грузов на локацию в случае смерти юнита. Соответственно, мародеры, которые должны были собирать грузы рядом с трупами, не имеют смысла. В итоге сделан ИИ торговцев, охранников и охотников. Починил пару багов. Сделал отношение кланов к игроку меняющимся — в зависимости от действий игрока.
Сделан HUD. Сделан инвентарь, в который можно подбирать убитых юнитов и из которого их можно выкидывать при необходимости.
День десятый
Приближается финал.
Есть понимание того, что нужно финализировать картинку. Как видно по результату предыдущего дня, бои смотрятся нормально… до тех пор, пока кто нибудь не умирает. Юниты просто исчезают, что смотрится нехорошо. Вариантов два. Либо сделать разваливание юнитов на отдельные части. Это задача достаточно сложная, причём не столько с точки зрения программирования, сколько с точки зрения рутинной работы по разрезанию юнитов на части и экспорту их в удобоваримый формат. Отдельный момент — очень не хочется тратить время на добавление анимаций в движок. Второй вариант — система частиц. Но Magic Particles не умеет WinCE. Интегрировать его для использования на остальных платформах? Но очень хочется избежать решений в кроссплатформенном фреймворке, которые не смогут работать везде…
В итоге я остановился на следующем решении: использовать Magic Particles, но при этом полностью отказаться от его родного API.
На практике это было реализовано следующим образом: был реализован конвертер, который проигрывал эффекты созданные в MP и каждый кадр сохранял состояние всех видимых частиц в файл. На выходе получался файл, описывающий состояние эффекта в каждый момент времени, но при этом не привязанный к Magic Particles API. Файл, который я могу проигрывать своими силами на любой платформе.
Такой вариант даже близко не покрывает весь спектр возможностей MP, но со взрывами и другими простыми и не зацикленными эффектами вполне справляется. А это-то мне и нужно.
Взрыв почему-то получился белёсым, но я решил не тратить время на разбирательства. Выглядит на троечку, но времени осталось совсем мало. По факту — полтора дня: одиннадцатое число и ночь на двенадцатое (конкурс заканчивается 12 числа в 9 утра).
День одиннадцатый
Всё оставшееся время решено потратить на квесты. Конечно, в игре и так уже есть какой-никакой геймплей. Но квесты придадут смысл и, может быть, задержат игрока чуть подольше.
Расписывать тут особо нечего.
Квесты полностью захардкожены в скриптах. Никаких инструментов для редактирования связей. Никаких инструментов для настройки скрипта без кодинга… Простой и незамысловатый код.
Сделал окно диалогов для общения с NPC (у нас их роль исполняют здания). Принцип работы такого окна почти идентичен квестовому диалоговому окну в Космических рейнджерах. Думаю, вполне реально написать несложный конвертер, который сделает текстовые квесты из Космических рейнджеров пригодными для запуска в данной игре.
Решил не делать мини-карту, т.к. тогда сразу становится очевидной ограниченность мира. А ведь хочется создать впечатление, что мир живой и большой. Но и просто так оставлять игрока блуждать нельзя. Конечно, найдутся игроки, которым это будет интересно. Но большая часть заблудится на первом перекрестке и пошлёт проект подальше.
Поэтому было принято половинчатое решение — реализовать компас без карты. Компас указывает направление на выбранную цель, а на стартовой базе можно отдельно добавить себе метку на любое здание.
На видео показан процесс выполнения одного из заданий целиком. Скорость вертолета увеличена, чтобы не затягивать видео.
Surprise!
Доделал квесты. Игру возможно полностью пройти. Поздняя ночь одиннадцатого дня. Полез в тему конкурса, чтобы ещё раз уточнить сроки и определить план на ночь… И оказалось, что пару дней назад большинство участников проголосовало за продление конкурса ещё на две недели!
Это идёт вразрез с моими планами. Да и нарушает идею сделать проект за короткий срок.
В итоге прихожу к следующему решению: ночь нормально отсыпаюсь, а в двенадцатый день делаю то, что планировал сделать в ночь. И добавляю ещё два дня (до полных двух недель), чтобы «причесать» проект.
День двенадцатый
Отполировал и перепрошёл все квесты. Сделал эффект респауна игрока. В точке, где находился игрок в момент смерти, создаётся эффект телепортации, в точке респауна тоже создаётся эффект. Немного улучшил поиск пути, чтобы юниты реже натыкались на препятствия. Но они всё равно с некоторой вероятностью натыкаются.
Добавил ещё несколько видов юнитов. Вернее не видов — юниты фактически остались те же. Но раньше все роли (охотник, мародер) у всех кланов выполняли юниты, выглядящие одинаково. А я сделал так, чтобы каждый юнит у каждого клана выглядел уникально.
Чуть-чуть подправил работу ИИ: раньше охотники почти никогда не привозили юнитов на респаун. Просто не доезжали.
Последние два дня
Плана работы нет. Делаю всё, что взбредет в голову. Всё, что бросается в глаза. Всё, что хочется исправить. Видео результата работы в эти дни нет, т.к. изменений много и они в основном мелкие. Потребовалось бы минут 10-15 снимать, чтобы показать их все на видео. А всё, что получилось в итоге и так видно в конкурсном проекте.
Вот примерный список того, что было сделано (совсем мелкие исправления не включены):
Включена поддержка геймпада — вообще, фреймворк для интерфейса умеет геймпад из коробки, ничего придумывать не нужно. Только добавил управление непосредственно вертолётом.
Исправлен баг с неверным расчётом наклона юнитов по отношению к поверхности — на видео иногда проскакивает момент, когда транспорты странно носом в землю закапываются. Это связано с неверным применением кватерниона, описывающего наклон поверхности под колесами юнита.
Сделан простой расчёт движения юнитов, чтобы они друг в друга не въезжали — добавил несложные коллизии между юнитами.
Исправлен баг с вылетом при работе с окном диалогов: пересоздавать элементы окна в обработчике этих самых элементов — плохая идея.
Добавлены метки кланов над клановыми юнитами.
Тени от облаков — вроде бы мелочь, а плоский мир перестаёт таким быть.
Разлёт груза — груз теперь не просто появляется на земле рядом с местом, где его выбросили, а красиво разлетается от точки выбрасывания.
Эффект телепортации грузов — при подборе груза он исчезает не мгновенно, а плавно, с соответствующим эффектом.
Тестирование и исправление багов.
Результат работы можно посмотреть по ссылке в теме проекта: SkyRanger.
Обзоры на все конкурсные проекты:
Ссылка непосредственно на проект, о разработке которого вы читаете (если не хотите смотреть весь обзор):
www.youtube.com/watch?v=0nu2QxXAYjo&t=708
Итог:
Данная игра была сделана за 14 дней с нуля на фреймворке, который вообще не умел 3Д на момент старта.
Если уж говорить откровенно, половина времени потрачена не на игру, а на то, чтобы допилить недостающий функционал в самом фреймворке.
Если бы разработка велась на каком-нибудь готовом промышленном движке (например, на UE4, который на днях стал полностью бесплатным), то проект можно было бы сделать дней за 7 и с лучшим качеством. Причём это касается практически любого жанра. В современном мире играбельный прототип любого жанра собирается в пределах месяца неспешной работы.
Выводы:
Если вдруг вы видите людей, которые предлагают вам вступить в проект на энтузиазме и сделать Супер-МЕГА-Убийцу-Крайзиса-и-ВОВки, но при этом у них нет хотя бы минимальной демки — бегите от них, ведь это лентяи, которые не удосужились потратить неделю работы и 200$ на ассеты, чтобы сделать прототип, реализующий их идею.
P.S. Проект после конкурса решено в неспешном режиме дорабатывать. Проект полностью открыт для участия — любой может придти и сделать что-то своё. Также с выходом UE4 решено перенести всё уже сделанное на UE4 и сосредоточиться именно на разработке игры, а не движка для неё.Если сообществу будет интересно, я напишу статью о том, как делался переход на UE4 и с какими сложностями при этом пришлось столкнуться.
UPD:
Хаброэффект убил мне дропбокс и мне заблокировали внешние ссылки. Все файлы будут перенесены на свой хостинг в ближайшие часы, пока все это недоступно. Это будет исправлено в ближайшее время. Прошу прощения за доставленные неудобства.
Ссылки снова живые.
UPD2:
Выяснилось, что часть читателей восприняла данную статью как «Ой, да игры можно за пару недель делать! Чё вы там уже три года ковыряетесь, лентяи???».
Это не то, о чём я говорил.
К сожалению, правило «20% работы отнимают 80% времени» никуда не делось.
За очень короткий срок можно сделать прототип, который будет играбельным и будет отражать ваши идеи.
Но это ещё очень и очень далеко от игры. Скорость разработки падает с каждой новой фишкой.
Первые дни разработки носят взрывной характер:
Вот у нас нет ничего. Через день у нас ландшафт. Разница между «ничего» и «ландшафтом на экране» — огромна. Но ведь всего полдня работы!
А теперь добавьте сюда деревьев. Нет, серьёзно. Самых обычных деревьев. Ну лесок небольшой.
«То есть как? Сделать ландшафт — 5 часов работы, а лес на ландшафте — месяц????». А вот так. При реализации леса у нас встаёт ряд вопросов, начиная с оптимизации (нарисовать в лоб лес не выйдет. Просто упрётесь в недостаток производительности. А значит, нужны оптимизации — много и зачастую нетривиальные) и заканчивая визуальными артефактами (внезапно deffered shading не хочет нормально работать с блендингом, а оптимизированная листва только блендингом и делается). Не говоря уж о поиске пути, который вообще не учитывал существования отдельно стоящих мелких объектов, которые ИИ должны объезжать.
Разработка нормальной и качественной игры — это сложная, долгая и кропотливая работа. Большая часть которой вообще не видна снаружи.
Я рассказал о том, что можно за короткий срок создать демонстрацию вашей идеи, но никак не законченный продукт.
Эти размышления натолкнули меня на занятный эксперимент: в ноябре на gamedev.ru стартовал «конкурс леталок». Конкурс предполагал разработку в течении двух месяцев. Однако мне показалось, что это многовато. Поэтому я записался в участники… И забыл о конкурсе на полтора месяца.
Основная идея эксперимента — сделать полноценный проект за две недели. Срок завершения конкурса — неплохой дедлайн. К тому же последняя неделя конкурса совпала с концом новогодних праздников, что дало возможность не отвлекаться на другие задачи. Итак: конкурс, проект с нуля, две недели.
Если вам не хочется тратить время на всю статью — можете промотать вниз. Там обзор конкурсных проектов и кратенький вывод из всего этого эксперимента.
У нас есть две недели. Основной вопрос в том, что делать. Честно говоря, я изначально думал, что конкурс идёт до 7 января и планировал потратить на него только одну неделю.
Одна неделя — это не очень много, в связи с чем и был выбран жанр лаунчеров.
Лаунчер — это игра, всё действие которой происходит только на одном уровне. По сути, прохождение сводится к череде попыток пролететь дальше/выше. Каждая попытка (кроме последней) обречена на провал, но даёт очки, которые можно потратить на прокачку персонажа, чтобы он мог летать лучше. Игра заканчивается в тот момент, когда персонаж прокачан настолько, чтобы долететь до конца уровня.
Прекрасным представителем этого жанра является игра Butibo Bison.
Повторить геймплей именно этой игры я и планировал. Однако когда решил уточнить детали конкурса, выяснилось, что финал не 7, а 12. 12 дней! С этим уже можно работать! Будем делать 3D Action!
За основу возьмём несколько моих любимых игр: Вангеры, Механоиды, Ex Machine, Renegade Ops. Хочется сделать РПГ, но в такой короткий срок проработать прокачку не выйдет. Поэтому цель: за основу берём геймплей RenegadeOps/Вангеры, набор квестов — по аналогии с Ex Machine/Механоиды. Ну и чтобы не тратить время на продумывание вселенной, пусть игра будет во вселенной Механоидов. Тем более, что моё фактическое место жительство в 7 км от бывшего офиса SKYRIVER studios располагает к таким заимствованиям.
День первый
Что мы имеем? Фреймворк, на котором выпущено несколько 2Д игр. Из 3Д возможностей — только загрузка меша из файла. Ещё есть редактор ландшафтов. Используем его для создания игрового ландшафта. Задача на первый день:
- Создать тестовый ландшафт и отобразить его в игре.
Для этого нам понадобится 3Д камера. Она должна уметь устанавливать видовую матрицу и матрицу проекции. Класс камеры даже не пришлось писать, за годы разработки он у меня уже был сделан. Просто перетаскиваем камеру во фреймворк.
Следующая подзадача — перенести шейдеры из редактора в игру. Шейдеры лежат в открытом виде, всё что нужно сделать — убрать из них обработку инструментов редактора: подсветку края тайлов, динамический расчёт нормалей и прочие мелочи.
Основная подзадача, которая заняла большую часть дня — реализация класса, отвечающего за загрузку файла, содержащего ландшафт и передачу геометрии на рендер. Задача не слишком сложная, но пол дня заняла.
Итог работы:
И что же мы видим в результате? Ландшафт страшно шумит. Причина очень простая — при конвертации текстур я забыл прописать генерацию MipMap'ов. Но уже 11 часов вечера… Мелкая задача, но очень хочется спать.
День второй
На сегодня запланировано две задачи:
- Карты теней.
- Отрисовка моделей (без моделей толком не протестировать работу теней).
Первым делом включаю MipMap'ы, которые не включил вчера и выясняется, что в коде что-то генерирует OpenGL ошибку. Проверок в коде не очень много и ошибка вылезает при загрузке шейдеров. Грешу на криво перенесённые шейдеры из редактора… Потратил час, чтобы понять, что ошибка не в шейдерах… Оказывается, неправильно указал настройку текстур и в MAG_FILTER уходило значение GL_LINEAR_MIPMAP_LINEAR, которого там быть не должно. Исправляю на GL_LINEAR и всё заводится без проблем. А между тем потрачено два часа… Это очень много, учитывая что есть всего 12 дней.
Теперь займёмся моделями. Вообще, у меня уже есть загрузчик простых моделей. Но мало просто уметь отрисовывать модель на экране. Нужно, чтобы игра рисовала только те модели, что сейчас находятся в фрустуме камеры. Самый простой способ организовать это в нашем случае — разбить всё игровое пространство на квадраты, где квадрат примерно равен зоне, видимой на экране.
Ландшафт уже разбит на примерно такие квадраты, поэтому создаём менеджер объектов, который разбивает игровое пространство на квадраты в соответствии с настройками ландшафта и при отрисовке обрабатывает только те объекты, которые находятся не далее одного квадрата от камеры. То есть рисуется зона 3х3 квадрата, где центральный квадрат — это квадрат, в котором находится камера. Плюс менеджер объектов должен отслеживать перемещение объектов и в случае, если объект выехал за пределы своего квадрата, перемещать его в актуальный квадрат. Задача по написанию такого менеджера заняла около 5 часов.
Следующая задача — реализация карты теней. Но для карт теней нужна поддержка Render To Texture во фреймворке, которой у меня не было, поскольку ранее реализованные проекты не требовали пост эффектов, а RTT в 2Д, кроме как для пост-эффектов, нигде не используется.
Ещё час тратим на реализацию обёртки над FBO. Ничего особо сложного.
Приступаем к последней задаче второго дня — Shadow Maps. Всё бы ничего, но я приверженец Stencil Shadows… Всеми силами я всегда избегал прикасаться к Shadow Maps. Ну не нравились они мне. Но время идёт… в современных реалиях вообще нет ни одной причины использовать стенсильные тени. Слишком сильно падает их производительность с ростом сложности геометрии и разрешений экранов. Так что альтернативы нет — приходится взяться за реализацию карт теней. Конечно, я прекрасно знаком с теорией работы карт теней, хотя никогда их не реализовывал. Поэтому особых сложностей не жду. Взял давно отложенный на чёрный день мануал и по нему реализовал отрисовку теней.
Кстати, использовал этот мануал. Всем рекомендую. Грамотно и по делу всё расписано, в том числе и основные проблемы, вылезающие при реализации карт теней.
С мипмапами ландшафт стал выглядеть лучше, да и тени неплохо смотрятся.
День третий
Продолжаем прикручивать нужный нам функционал. На сегодня запланировано две задачи.
- Интеграция скриптового языка Lua с помощью проекта LuaJIT. Как раз не так давно вышла обновленная версия JIT компилятора для этого языка и наш эксперимент — отличная возможность новый компилятор опробовать.
- Интеграция системы частиц. Я планировал использовать Magic Particles от Astralax.
Начнем с LuaJIT. Качаем исходники и легко собираем dll под Windows. Пишем небольшой класс-обертку (не люблю luabind и аналоги, предпочитаю работать с lua через минимум прослоек). И, собственно, всё.
Попробовал собрать под Android… и в течение часа не смог этого сделать. Решил не тратить дальше на это время, потому что для конкурса это не критично, а в дальнейшем можно будет и отдельно заморочиться.
Вторая часть плана на сегодня — интеграция системы частиц. Я много и продуктивно работал именно с системой частиц Magic Particles от Astralax, поскольку действительно сложно найти что-то более мощное и простое в этой сфере. Плюс очень адекватный разработчик, что немаловажно при разработке проектов.
Однако меня остановил один не важный для конкурса, но важный для фреймворка момент. Дело в том, что фреймворк создаётся, в частности, для проектов под Windows CE. И, к сожалению, это чуть ли не единственная из распространенных ОС, которая не поддерживается MP. Это и понятно, игровой рынок на WinCE отсутствует как класс. Но для меня это важно, поэтому MP я решил пока не использовать…
От расстройства и прокрастинации пошёл играть в Burito Bison и потратил на это полтора часа времени.
Однако день ещё далеко не закончен. Едва перевалило за обед. Решил сделать стартовое меню. Сделал несложный ландшафт, поместил на него пару зданий и два вертолётика. И вылез баг с картами теней. Его хорошо видно на КДПВ на угловой стене слева под кнопкой «Выход». Однако решил этот баг не править — вид в игре не такой и на нём эти баги практически не видны. А правка альясинга теней обещает убить несколько драгоценных часов.
Сделал меню, интересно ездящее вверх/вниз. Получилось занятно. Добавил кнопки «Настройка» и «Продолжить», хотя прекрасно понимаю, что с большой вероятностью их функционал в рамках конкурса реализовать не смогу — не хватит времени.
Может создаться ощущение, что я потратил время на ненужную фигню — анимации менюшек. Но это не заняло слишком много времени, поскольку фреймворк умеет анимации для UI. Всего десяток минут потребовалось, чтобы указать — что и когда анимировать. Зато с анимацией меню стало гораздо интереснее.
День четвертый
План на сегодня:
- Управление вертолётом игрока
- Оружие: лазер, пулемёт, ракеты
Только в 16 часов дня я занялся задачами непосредственно из плана. До этого решал всякие задачи, которые к плану отношения напрямую не имеют, но выполнение плана нельзя было начинать пока их не закончишь. Одна из таких задач — спаун юнита. Например, вертолёта игрока… Спаун требует работающих скриптов, работающие скрипты требуют загрузки уровня и прописывания соответствующих функций, через которые можно управлять юнитами…
Дальше — больше. Сделал управление вертолётом и оказалось, что при нажатии на кнопку и движении мышью Qt начинает адски тормозить.
Я, как любой разумный программист, грешил на себя… Переписал внутреннюю систему обработки сообщений. Сделал проверку на дублирование сообщений… И это не помогло.
Ладно, я отказался от обычной системы сообщений и сделал считывание состояния клавиатуры и мышки… И это не помогло.
Я полностью отключил систему ввода в своём движке… И всё равно получил фризы. Сделал хук WH_GETMESSAGE на все сообщения, касающиеся ввода, с перехватом и отменой всех сообщений… Это не помогло. Ничего не осталось, кроме как исследовать систему вне моей среды разработки.
Разгадка оказалась простой… Я потратил три часа, исправляя баг, которого нет… Это Synergy тормозила, если зажимать несколько кнопок одновременно. Убрал Synergy и всё стало плавненько и аккуратненько.
В итоге не успел сделать наклон вертолёта в сторону полета. Вроде бы мелочь, но ведь важная… Но всё же не настолько важная, чтобы тратить на неё время сейчас. Тем более, что уже 11 вечера 4 января… Прошло 4 дня, а я только вертолёт запустил полетать. Так что стрельба, стрельба и ещё раз стрельба.
В два часа ночи я записал видео. Ракеты не успел. Но решил, что сейчас они не так важны, как сон.
День пятый
Задача на сегодня — сделать игровую локацию.
У меня есть десять зданий, который были куплены на 3drt.com для другого проекта. Сначала я примерно расписал сюжет игры, далее составил список зданий и прикинул, какое здание какую роль может выполнять в игре. Что похоже на шахту, что похоже на главную базу и т.д.
В редакторе ландшафтов примерно набросал игровую зону:
На каждой точке сделал подпись, состоящую из названия и порядкового номера используемой модели.
После этого нарисовал границы игровой зоны с помощью гор и пару непроходимых гор нарисовал в середине карты, чтобы игрок напрямую летать не мог.
Следующий этап — придание неоднородности ландшафту и прокладывание дорог. Т.к. времени очень мало — выделил на всё три часа. Этого времени хватило только на то, чтобы создать минимально играбельный ландшафт. На какие-то художественные изыски времени не осталось.
Следующая задача — расстановка объектов и задание зон проходимости. У меня нет подходящего 3Д редактора для фреймворка, т.к. фреймворк всегда был 2Д и все проекты на нем были 2Д. К счастью, у меня есть редактор, созданный гораздо раньше для 3Д проектов. Он достаточно сложный и имеет сложный формат сохранений. Да и писался он для совершенно другого движка, поэтому напрямую использовать его не получится. Однако, на сегодня это не важно. Создаем в этом редакторе локацию.
В редакторе я расставил объекты и нарисовал зоны:
- Дороги
- Проходимые зоны бездорожья
- Зоны для полетов
- Безопасные зоны (расположены рядом со зданиями, в пределах таких зон нельзя стрелять).
Моменты на видео, когда весь ландшафт раскрашен в красно-зелёное — это, собственно, редактирование зон.
День шестой
План:
- Загрузка локации, созданной в редакторе
- Функционирование всех зданий (функционирование турелей и определение «входа» в здания)
У нас есть локация в редакторе, который не предназначен для работы с нашим игровым движком.
Я решил не заморачиваться с загрузкой его сложного формата в игре и сделал простую вещь: добавил в редактор возможность сохранения сцены в виде текстового файла.
Дальше локацию сохранил в текстовый файл. Получилось что-то вроде:
Пример содержимого текстового файла с уровнем
FILENAME
TLevelStaticObject.Model.FileName
\\buildings\bld10.sxm
STRING
TLevelBaseObject.Name
CLIMAT_1
FLOAT
TLevelBaseObject.Position.x
2248.16
FLOAT
TLevelBaseObject.Position.y
2874.08
FLOAT
TLevelBaseObject.Position.z
-0.355
FLOAT
TLevelBaseObject.Rotation.angle
0
FLOAT
TLevelBaseObject.Quaternion.x
0
FLOAT
TLevelBaseObject.Quaternion.y
0
FLOAT
TLevelBaseObject.Quaternion.z
-0.732
FLOAT
TLevelBaseObject.Quaternion.w
-0.68
BOOL
TLevelBaseObject.ShadowCaster
false
TLevelStaticObject.Model.FileName
\\buildings\bld10.sxm
STRING
TLevelBaseObject.Name
CLIMAT_1
FLOAT
TLevelBaseObject.Position.x
2248.16
FLOAT
TLevelBaseObject.Position.y
2874.08
FLOAT
TLevelBaseObject.Position.z
-0.355
FLOAT
TLevelBaseObject.Rotation.angle
0
FLOAT
TLevelBaseObject.Quaternion.x
0
FLOAT
TLevelBaseObject.Quaternion.y
0
FLOAT
TLevelBaseObject.Quaternion.z
-0.732
FLOAT
TLevelBaseObject.Quaternion.w
-0.68
BOOL
TLevelBaseObject.ShadowCaster
false
Дальше пишем простенькую утилиту, которая из сложного текстового файла с кучей объектов и свойств выдирает только нужные непосредственно в игре и сохраняет в удобоваримом формате.
Дальше нам нужно загрузить зоны и объекты. Объекты-декорации просто добавляются в менеджер объектов, написанный ранее, и игра о них забывает, а остальные объекты создаются в обычном порядке.
В общем-то конверт и загрузка локации заняли достаточно маленькую часть дня. Больше всего времени ушло на реализацию функционала турелей. Работают они просто: если игрок выстрелил в безопасной зоне, то активируется таймер на 15 секунд, в течении которого все турели, в радиусе поражения которых находится игрок, открывают по нему огонь.
День седьмой
- Пришло время реализовать искусственный интеллект.
У меня уже есть искусственный интеллект, который умеет выполнять разные функции.
Делался он несколько лет назад, когда была идея реализовать конкурс ИИ. Собственно была реализована 2Д модель мира механоидов с их правилами. Торговцы получали очки за доставку товаров, охранники — за сопровождение торговцев, охотники — за привезённые головы, мародеры — за украденные (не купленные) и проданные товары.
Как работал этот ИИ можно посмотреть тут:
Круги — это живые юниты.
Красные буквы — это мёртвые юниты.
Чёрные кресты — это груз.
Две команды — зелёные и красные. Активно пытаются изображать живой мир.
ИИ в лоб перенести не получится. Дело в том, что в мире механоидов юнит — это нечто парящее и стреляющее перед собой. То есть нет проблемы с радиусом поворота, есть возможность двигаться боком. В этом проекте ситуация другая: юнит — это наземное транспортное средство с колёсами и всеми вытекающими проблемами.
Весь день был потрачен на то, чтобы сделать ИИ.
Видео для этого дня нет. Связано с тем, что к концу дня всё ещё нечего было показывать. Результатом работы в течение седьмого дня стала возможность создавать юниты с помощью текстовых файлов (уже вне конкурса был создан редактор для этих дел).
Конфиг обычного юнита выглядит примерно так:
Конфиг, описывающий юнит
FILENAME
VERSION
1
TYPE
CAR
NAME
GUN_JEEP
SCALE
1.0
BODY
vehicles/jeep_1/body.sxm
WHEELS_COUNT
4
MODEL
vehicles/wheels/wheel3_left.sxm
POSITION
3.581
-4.362
2.024
MODEL
vehicles/wheels/wheel3_right.sxm
POSITION
-3.537
-4.362
2.024
MODEL
vehicles/wheels/wheel3_left.sxm
POSITION
3.581
3.387
2.024
MODEL
vehicles/wheels/wheel3_right.sxm
POSITION
-3.537
3.387
2.024
SPEED
50
ROTATION_PER_METER
1
STORAGE_SIZE
2
HEALTH
4000
SHIELD
4000
SHIELD_REGENERATION
50
WEAPONS_COUNT
1
TYPE
GUN_TURRET_1
POSITION
0.013
3.251
6.755
VERSION
1
TYPE
CAR
NAME
GUN_JEEP
SCALE
1.0
BODY
vehicles/jeep_1/body.sxm
WHEELS_COUNT
4
MODEL
vehicles/wheels/wheel3_left.sxm
POSITION
3.581
-4.362
2.024
MODEL
vehicles/wheels/wheel3_right.sxm
POSITION
-3.537
-4.362
2.024
MODEL
vehicles/wheels/wheel3_left.sxm
POSITION
3.581
3.387
2.024
MODEL
vehicles/wheels/wheel3_right.sxm
POSITION
-3.537
3.387
2.024
SPEED
50
ROTATION_PER_METER
1
STORAGE_SIZE
2
HEALTH
4000
SHIELD
4000
SHIELD_REGENERATION
50
WEAPONS_COUNT
1
TYPE
GUN_TURRET_1
POSITION
0.013
3.251
6.755
За день игра научилась парсить это всё и загружать данные. Конфигов подобного рода, на самом деле, не один, а два. Второй — для описания турелей, которые ставятся на юнита. В данном случае ставится турель GUN_TURRET_1.
Как можно понять — это 7 января, Рождество. И семейная традиция — собираться вместе со всеми родственниками в родительском доме… Поэтому так мало сделано — большую часть дня я провел в кругу семьи.
День восьмой
- Продолжаем пилить ИИ.
Юниты научились ездить и атаковать. Также преследуют противника в зоне видимости. Основная часть работы была посвящена передвижению.
Амортизаторы прикручивать не стал. Час ночи… Из-за отставания по срокам седьмого января — категорически выбился из плана. Так что объезд препятствий — в топку… В ту же топку и физическое взаимодействие между юнитами… И подвеску техники тоже туда же… Особенно печалит последнее. Без расчета подвески юниты жёстко повторяют ландшафт и выглядит это не айс. Но функционал свой выполняют, так что оставляем так.
День девятый
В игре планировалось четыре вида ИИ:
Торговцы — покупают товар и продают в другом здании.
Охранники — следуют за торговцами и атакуют противника, если видят.
Охотники — курсируют по карте и атакуют противников, периодически отвозя на базу головы убитых врагов и друзей.
Мародеры — курсируют по карте и атакуют в первую очередь торговцев, периодически отвозя на базу подобранные товары.
Сделаны три вида ИИ. Мародеров делать не стал, потому что нет товаров. Вернее товары есть. Торговцы закупаются ими и продают. Но решил не делать вываливание грузов на локацию в случае смерти юнита. Соответственно, мародеры, которые должны были собирать грузы рядом с трупами, не имеют смысла. В итоге сделан ИИ торговцев, охранников и охотников. Починил пару багов. Сделал отношение кланов к игроку меняющимся — в зависимости от действий игрока.
Сделан HUD. Сделан инвентарь, в который можно подбирать убитых юнитов и из которого их можно выкидывать при необходимости.
День десятый
Приближается финал.
Есть понимание того, что нужно финализировать картинку. Как видно по результату предыдущего дня, бои смотрятся нормально… до тех пор, пока кто нибудь не умирает. Юниты просто исчезают, что смотрится нехорошо. Вариантов два. Либо сделать разваливание юнитов на отдельные части. Это задача достаточно сложная, причём не столько с точки зрения программирования, сколько с точки зрения рутинной работы по разрезанию юнитов на части и экспорту их в удобоваримый формат. Отдельный момент — очень не хочется тратить время на добавление анимаций в движок. Второй вариант — система частиц. Но Magic Particles не умеет WinCE. Интегрировать его для использования на остальных платформах? Но очень хочется избежать решений в кроссплатформенном фреймворке, которые не смогут работать везде…
В итоге я остановился на следующем решении: использовать Magic Particles, но при этом полностью отказаться от его родного API.
На практике это было реализовано следующим образом: был реализован конвертер, который проигрывал эффекты созданные в MP и каждый кадр сохранял состояние всех видимых частиц в файл. На выходе получался файл, описывающий состояние эффекта в каждый момент времени, но при этом не привязанный к Magic Particles API. Файл, который я могу проигрывать своими силами на любой платформе.
Такой вариант даже близко не покрывает весь спектр возможностей MP, но со взрывами и другими простыми и не зацикленными эффектами вполне справляется. А это-то мне и нужно.
Взрыв почему-то получился белёсым, но я решил не тратить время на разбирательства. Выглядит на троечку, но времени осталось совсем мало. По факту — полтора дня: одиннадцатое число и ночь на двенадцатое (конкурс заканчивается 12 числа в 9 утра).
День одиннадцатый
Всё оставшееся время решено потратить на квесты. Конечно, в игре и так уже есть какой-никакой геймплей. Но квесты придадут смысл и, может быть, задержат игрока чуть подольше.
Расписывать тут особо нечего.
Квесты полностью захардкожены в скриптах. Никаких инструментов для редактирования связей. Никаких инструментов для настройки скрипта без кодинга… Простой и незамысловатый код.
Сделал окно диалогов для общения с NPC (у нас их роль исполняют здания). Принцип работы такого окна почти идентичен квестовому диалоговому окну в Космических рейнджерах. Думаю, вполне реально написать несложный конвертер, который сделает текстовые квесты из Космических рейнджеров пригодными для запуска в данной игре.
Решил не делать мини-карту, т.к. тогда сразу становится очевидной ограниченность мира. А ведь хочется создать впечатление, что мир живой и большой. Но и просто так оставлять игрока блуждать нельзя. Конечно, найдутся игроки, которым это будет интересно. Но большая часть заблудится на первом перекрестке и пошлёт проект подальше.
Поэтому было принято половинчатое решение — реализовать компас без карты. Компас указывает направление на выбранную цель, а на стартовой базе можно отдельно добавить себе метку на любое здание.
На видео показан процесс выполнения одного из заданий целиком. Скорость вертолета увеличена, чтобы не затягивать видео.
Surprise!
Доделал квесты. Игру возможно полностью пройти. Поздняя ночь одиннадцатого дня. Полез в тему конкурса, чтобы ещё раз уточнить сроки и определить план на ночь… И оказалось, что пару дней назад большинство участников проголосовало за продление конкурса ещё на две недели!
Это идёт вразрез с моими планами. Да и нарушает идею сделать проект за короткий срок.
В итоге прихожу к следующему решению: ночь нормально отсыпаюсь, а в двенадцатый день делаю то, что планировал сделать в ночь. И добавляю ещё два дня (до полных двух недель), чтобы «причесать» проект.
День двенадцатый
Отполировал и перепрошёл все квесты. Сделал эффект респауна игрока. В точке, где находился игрок в момент смерти, создаётся эффект телепортации, в точке респауна тоже создаётся эффект. Немного улучшил поиск пути, чтобы юниты реже натыкались на препятствия. Но они всё равно с некоторой вероятностью натыкаются.
Добавил ещё несколько видов юнитов. Вернее не видов — юниты фактически остались те же. Но раньше все роли (охотник, мародер) у всех кланов выполняли юниты, выглядящие одинаково. А я сделал так, чтобы каждый юнит у каждого клана выглядел уникально.
Чуть-чуть подправил работу ИИ: раньше охотники почти никогда не привозили юнитов на респаун. Просто не доезжали.
Последние два дня
Плана работы нет. Делаю всё, что взбредет в голову. Всё, что бросается в глаза. Всё, что хочется исправить. Видео результата работы в эти дни нет, т.к. изменений много и они в основном мелкие. Потребовалось бы минут 10-15 снимать, чтобы показать их все на видео. А всё, что получилось в итоге и так видно в конкурсном проекте.
Вот примерный список того, что было сделано (совсем мелкие исправления не включены):
Включена поддержка геймпада — вообще, фреймворк для интерфейса умеет геймпад из коробки, ничего придумывать не нужно. Только добавил управление непосредственно вертолётом.
Исправлен баг с неверным расчётом наклона юнитов по отношению к поверхности — на видео иногда проскакивает момент, когда транспорты странно носом в землю закапываются. Это связано с неверным применением кватерниона, описывающего наклон поверхности под колесами юнита.
Сделан простой расчёт движения юнитов, чтобы они друг в друга не въезжали — добавил несложные коллизии между юнитами.
Исправлен баг с вылетом при работе с окном диалогов: пересоздавать элементы окна в обработчике этих самых элементов — плохая идея.
Добавлены метки кланов над клановыми юнитами.
Тени от облаков — вроде бы мелочь, а плоский мир перестаёт таким быть.
Разлёт груза — груз теперь не просто появляется на земле рядом с местом, где его выбросили, а красиво разлетается от точки выбрасывания.
Эффект телепортации грузов — при подборе груза он исчезает не мгновенно, а плавно, с соответствующим эффектом.
Тестирование и исправление багов.
Результат работы можно посмотреть по ссылке в теме проекта: SkyRanger.
Обзоры на все конкурсные проекты:
Ссылка непосредственно на проект, о разработке которого вы читаете (если не хотите смотреть весь обзор):
www.youtube.com/watch?v=0nu2QxXAYjo&t=708
Итог:
Данная игра была сделана за 14 дней с нуля на фреймворке, который вообще не умел 3Д на момент старта.
Если уж говорить откровенно, половина времени потрачена не на игру, а на то, чтобы допилить недостающий функционал в самом фреймворке.
Если бы разработка велась на каком-нибудь готовом промышленном движке (например, на UE4, который на днях стал полностью бесплатным), то проект можно было бы сделать дней за 7 и с лучшим качеством. Причём это касается практически любого жанра. В современном мире играбельный прототип любого жанра собирается в пределах месяца неспешной работы.
Выводы:
Если вдруг вы видите людей, которые предлагают вам вступить в проект на энтузиазме и сделать Супер-МЕГА-Убийцу-Крайзиса-и-ВОВки, но при этом у них нет хотя бы минимальной демки — бегите от них, ведь это лентяи, которые не удосужились потратить неделю работы и 200$ на ассеты, чтобы сделать прототип, реализующий их идею.
P.S. Проект после конкурса решено в неспешном режиме дорабатывать. Проект полностью открыт для участия — любой может придти и сделать что-то своё. Также с выходом UE4 решено перенести всё уже сделанное на UE4 и сосредоточиться именно на разработке игры, а не движка для неё.Если сообществу будет интересно, я напишу статью о том, как делался переход на UE4 и с какими сложностями при этом пришлось столкнуться.
Хаброэффект убил мне дропбокс и мне заблокировали внешние ссылки. Все файлы будут перенесены на свой хостинг в ближайшие часы, пока все это недоступно. Это будет исправлено в ближайшее время. Прошу прощения за доставленные неудобства.
Ссылки снова живые.
UPD2:
Выяснилось, что часть читателей восприняла данную статью как «Ой, да игры можно за пару недель делать! Чё вы там уже три года ковыряетесь, лентяи???».
Это не то, о чём я говорил.
К сожалению, правило «20% работы отнимают 80% времени» никуда не делось.
За очень короткий срок можно сделать прототип, который будет играбельным и будет отражать ваши идеи.
Но это ещё очень и очень далеко от игры. Скорость разработки падает с каждой новой фишкой.
Первые дни разработки носят взрывной характер:
Вот у нас нет ничего. Через день у нас ландшафт. Разница между «ничего» и «ландшафтом на экране» — огромна. Но ведь всего полдня работы!
А теперь добавьте сюда деревьев. Нет, серьёзно. Самых обычных деревьев. Ну лесок небольшой.
«То есть как? Сделать ландшафт — 5 часов работы, а лес на ландшафте — месяц????». А вот так. При реализации леса у нас встаёт ряд вопросов, начиная с оптимизации (нарисовать в лоб лес не выйдет. Просто упрётесь в недостаток производительности. А значит, нужны оптимизации — много и зачастую нетривиальные) и заканчивая визуальными артефактами (внезапно deffered shading не хочет нормально работать с блендингом, а оптимизированная листва только блендингом и делается). Не говоря уж о поиске пути, который вообще не учитывал существования отдельно стоящих мелких объектов, которые ИИ должны объезжать.
Разработка нормальной и качественной игры — это сложная, долгая и кропотливая работа. Большая часть которой вообще не видна снаружи.
Я рассказал о том, что можно за короткий срок создать демонстрацию вашей идеи, но никак не законченный продукт.