Американский опыт

Английский для сомневающихся

Как я опять сделал игру за два дня

  • 25 апреля, 2015
  • 8 комментариев

В конце прошлого года я рассказывал о том, как участвовал в Ludum Dare, самом крупном игровом джеме.  Если пропустили этот пост, то сейчас самое время его почитать, кликнув на эту ссылку. Сейчас же я хочу рассказать о том, как участвовал в этом джеме второй раз.

Второй джем для меня, для всех остальных получил номер 32 и прошел 17-20 апреля. Голосованием участников была выбрана тема An Unconventional Weapon, что можно перевести как нетрадиционное оружие. Честно говоря, тема мне не понравилась. Моё мнение, что игры должны отходить от темы насильственного способа решения проблем. Как минимум для разнообразия. Но что есть, то есть.

Прежде, чем читать дальше, рекомендую посмотреть игру на сайте Ludum Dare, чтобы лучше понимать, о чем я буду говорить. Там же на сайте инструкция как запускать игры под Unity WebPlayer, если у вас последняя версия браузера Chrome.

ScreenShot_01

ИГРАТЬ

Основным отличием этого Ludum Dare для меня стал вопрос тайминга. Во-первых, потому что в этот момент я находился (и пока нахожусь) в Калифорнии. А значит, для меня соревнование началось в 18:00 пятницы и закончилось в 18:00 воскресенья. То есть только один целый день и два дня по кусочкам. В отличие от московского времени, когда можно оба выходных кодить до упора. Во-вторых, рабочие вопросы не отпускали меня до позднего вечера пятницы и съели несколько часов в субботу.

Так что первым решением по игре была минимизация контента. Делать большой мир, полный уникального контента, мне было не вариант. Если моя игра будет зависимой от контента, то у меня будут полные штаны рисков к концу джема остаться с полуготовой игрой. Я даже думал сделать игру, в которой весь контент уместится в один экран. Типа игр EYEZMAZE. Но хорошей картинки в голове не складывалось, так что от этой идеи я отказался.

Ещё задачкой было выбрать визуальный стиль, которым можно было бы выделиться среди других игр. При том, что я ни разу не художник и не моделер, чтобы уметь по-разному. Я могу либо фотографии в фотошопе, либо лоуполи арт, навыки которого недалеко ушли с предыдущего Ludum Dare. Тут мне на помощь пришел фильм «Город грехов 2». Уйти в чернобелую гамму, используя редкие вкрапления цвета – звучит не сложно и относительно уникально.

Но по-прежнему главной задачкой оставалась тема игры. У меня не было в голове никаких заготовок про игры с оружием. Напомню, что тему джема я обдумывал поздним вечером, после непростого рабочего дня. Голова лопалась, хорошие мысли не лезли. Поэтому, помыкавшийсь, решил отложить вопрос темы и начать делать ту игру, в которую просто хотел бы поиграть сам, а с темой джема что-нибудь придумать по дороге.

К счастью, вижн такой игры у меня в голове зрел давно. Порой очень хочется поиграть в какую-нибудь незамысловатую игру, в которой минимум управления и все решения принимаются спинным мозгом, позволяя головному мозгу отдохнуть. Что-нибудь такое, где уии, мчишься, огибая препятствия. Но только так, чтобы казуально. Вот с последним в других играх подобного жанра проблема.

Так что первый вечер я посвятил созданию базовой механики. Кубик, изображающий из себя самолет, летит над террейном строго в заданном направлении, а игрок может стрелками двигать его по оставшимся двум координатам.

ld32_first_prototype

Второй день начался с того, что я полностью переписал механику движения. Для начала развел камеру и самолет на разные объекты. До этого самолет был дочерним объектом камеры. Камера летит вперед, а самолет елозит относительно камеры. Идея имела право на существование, но у неё был сильный минус. Когда самолет подлетал к краю экрана, то вместо самолета начинала двигаться сама камера с той же скоростью. Иначе говоря, самолет продолжал двигаться в сторону без изменений, но визуально ощущалось падение скорости. Ведь самолет по экрану движется быстрее, чем камера по уровню.

Решил не хитрить и сделать, чтобы самолет летал свободно в рамках уровня, а камера за ним следовала по координатам, но не была дочерним объектом, чтобы не наследовать наклоны. Иначе было бы неприятно играть, если бы камеру колбасило, также как самолет.

Второй причиной для того, чтобы изменить механику движения, была необходимость прикрутить фирменную физику Unity. Соударение самолета с препятствиями — основной элемент геймплея, поэтому он должен обыгрываться более качественно, чем просто списание HP и пролетание сквозь модель. Прикручивание физики потребовало перейти от управления напрямую позицией самолета, к управлению скоростью его физического тела. Может было бы правильней управлять силой, но я что-то не справился с управлением, когда попробовал это сделать. А первое правило Ludum Dare и вообще разработки в условиях таймпрессинга: не работает и не знаешь как поправить – не делать этого.

После базовой механики встал вопрос за контентом. Как я писал раньше, времени у меня было мало и собирать уровень вручную выглядело опасной затеей. Особенно для такого геймплея, когда нужен очень длинный уровень. Поэтому решил уровень генерировать. Сначала просто сделал заготовку террейна и автоматически раскопировал её для достижения заданной длины. Затем сделал несколько моделей препятствий и растиражировал их каждые N метров, рандомя модель, масштаб, угол поворота и позицию относительно исходной точки.

Позже эту систему усложнил, добавив изменение правил расстановки в зависимости от расстояния от начала уровня. Чтобы при продвижении игрока по уровню вокруг него происходили изменения. Сначала усложнение, увеличением масштаба. Затем введение новых элементов. Плюс почти пустые пространства в начале, чтобы было время для обучения, и в конце, чтобы подготовить игрока к финалу.

Ещё добавил штуку с использованием второго террейна. Просто большая лоуполи модель, которая также тиражируется, как и первый террейн. На геймплей не влияет, но добавляет картинке глубину.

Только базовый террейн:
ld32_farterrain_before

Вместо со вторым террейном:
ld32_farterrain_after

Чтобы придать геймплею осмысленности, добавил три штуки: 1) полоску прогресса, чтобы видеть сколько осталось до конца уровня; 2) набор очков, которые чем дальше, тем быстрее набираются; 3) возможность за набранные очки покупать апгрейды между полетами.

Опыт разработки предыдущей игры Fill The Bar, а вернее разгребания собственного багла, научил меня работать с прогрессией. Во-первых, как сохранять и загружать прогресс игрока. Во-вторых, что все бонусы должны увеличивать значения сложением, а не умножением, чтобы числа не улетали в космос. В-третьих, все цены на бонусы наоборот должны увеличиваться умножением, чтобы опять же игрок не улетал в космос с бесконечными апгрейдами, а в какой-то момент его развитие затормозилось, но не радикально. Типа если один раз сумел набрать сумму на апгрейд, то сможешь ещё два раза сделать также для следующего. Конечно, за настоящей балансировкой логика сложнее, но если на пальцах, то этого объяснения будет достаточно.

Поскольку за очки можно покупать полезные апгрейды, то, значит, они ревард. Ревард, он хорош тогда, когда идет рука об руку с риском. Когда есть возможность соблазниться на больший риск ради большего реварда. В моём случае риск довольно очевиден – чем ниже летишь, тем это опасней. Поэтому прикрутил простую штуку – множитель на набор очков, когда игрок летит на низкой высоте. Плюс такие полеты более красивы.

На этом второй день разработки закончился. У меня на руках была игра с полностью готовым core gameplay. Можно было пролететь до конца уровня, уворачиваться от препятствий, набирать очки, апгрейдится.

Утро последнего дня началось с осознания факта, что базовый геймплей без долгосрочной цели не работает. В игру не будешь играть, если не знаешь, зачем в неё играть. Эх, если бы я с самого начала тему продумал, то от неё мог бы продумывать цели, нарратив, оформление и всё такое. Но позняк метаться, нарратив в голову не шел, надо было как-то выкручиваться.

Тут, опять же, на помощь пришел приём, когда дизайнерское решение является комбинацией из имеющихся кусочков пазла. В данном случае это были следующие куски:

1)      Нужно было раскрыть тему «An Unconventional Weapon».
2)      Я не хотел делать игру про применение оружия.
3)      Нужен был сюрприз, чтобы игрок остался удивленным.
4)      Надо было что-то поставить в конце пути. Типа цель.
5)      Это что-то должно быть непонятным, чтобы был интерес узнать, что это такое.

Каждый из этих кусков стал элементом картины:

1)      Слово Weapon раскрываем с самого начала. Называем игру «Bomb Bringer». Показываем пару бомб в главном меню. Вешаем бомбу под самолет. Но не даём применять её где попало. Как работает бомба и что в ней unconventional игрок сможет узнать только в конце.
2)      Конечно же бомба не настоящая, она не должна ничего уничтожать. Нужно сделать наоборот, чтобы она что-то оживляла. Например, дерево.
3)      Да, задача игрока сбросить «бомбу» под дерево, чтобы то ожило, покрылось красками. Как раз то, что нужно для чернобелого мира.
4)      Поставим это дерево в конце пути.
5)      Но раз дерево изначально мертвое, то без листвы его форму можно сделать агрессивной, непонятной. Как раз подсуппортит изначальную идею, что мы летим с бомбой взрывать неведомую фигню.

А теперь загадка. Уровень длинною должен быть порядка 30 километров. При этом в начале пути мы должны видеть дерево, а в конце долететь до него. Радиус видимости более 1-4км делать вредно для производительности. Если дерево будет заметных размеров в начале, то значит в конце один его полигон будет размером с несколько игровых экранов. Нарисовать на фоне – значит заявить, что объект не настоящий и к нему по-честному не приблизится. Как быть? Подумайте пару минут, прежде чем читать дальше.

Без дерева:
ld32_tree_before

С деревом:
ld32_tree_after

Хитрость в том, что объект цепляем к камере на большом, но всё же разумном расстоянии. Когда при движениях камеры из стороны в сторону мы видим, как все объекты тоже двигаются, а дерево остается на месте, то мозг это обсчитывает как объект на очень большом расстоянии. При этом я увеличиваю дерево от одного заданного масштаба до другого в зависимости от того как далеко пролетел игрок. Для этого использую свою любимую функцию Mathf.Lerp.

Теперь нужно решить, что делать, если игрок долетел. Для удобства этот момент я выпилил в отдельную сцену. Слишком сложно было бы всё склеить в тех масштабах, которые в игре. А в новой сцене снова почитил с соотношением размеров дерева и самолета.

Ставим дерево, немного террейна. Ставим самолет и делаем ему анимацию полета вокруг дерева. Затем ставим камеру и тоже делаем ей анимацию полета вокруг дерева. Хорошо было бы это сделать в одной анимации. Но я таких штук не знаю. Поэтому камеру с самолетом синхронизировал методом многократных запусков игры.

Финальный аккорд – нужно менять цвета. Менять цвет материала через анимацию нельзя. Поэтому пишу код. По ходу дела обнаруживаю, что изменения цвета материала, сделанное во время игры, сохраняется после игры. Так после проверки вся графика становится внезапно цветной. Пришлось тоже подпереть кодом, принудительно выставляя материалам заданные серые тона.

Так, что-то ещё осталось. Ах, да, запилить главное меню, чтобы с самого начало было “дорого-бохато”. Делаю небольшой зацикленный каньон. С помощью той же анимации пускаю самолет летать кругами по нему. К самолету цепляю камеру, но запрещаю ей наклоняться. Вернее каждый кадр поправляю её. Немного помыкался с отладкой и готово. Подвесил бомбы и стало вообще торт.

Последнее, что надо было сделать – добавить музыку. Этот момент я оттягивал до последнего, так как это совсем не моё. Способ, которым в прошлый раз писал музыку, мне не понравился. Хотелось более интуитивного способа. Чтобы пальцем потыкал, как душа подскажет, и готово.  Раз пальцем, то значит экран телефона. Пошел смотреть, что он может мне предложить.

Перебрав несколько программ по ключевым словам «music composition» вышел на Fingertip Maestro. Результат, который получался в демоверсии, мне понравился, но пришлось заплатить за открытие доступа к нормальным инструментам.

На деле оказалось, что не всё так просто. Пока вожу пальцем, результат вроде устраивает. Но его затем нужно пересылать по почте, конвертировать в другой формат, подключать к игре и понимать, что это какая-то какофония, а не музыка. Но за несколько итераций удалось найти компромисс с чувством прекрасного. К тому же время подходило к концу.

Всё. Собираю билды. Заливаю. Проверяю. Оказывается в WebGL баг – в финальной сцене показывается полсекунды как надо, а потом синий экран, который исчезает только в самом конце. В других версиях такого нет. Мыкаюсь искать причину, но без результата. Тот цвет, что появляется, у меня нигде не используется. Видимо какой-то системный экран, намекающий на существование ошибки. К сожалению, быстро подебажить не получается. Сборка под WebGL занимает минут 10-15. Затем заливка на сервер ещё 20-30 минут. Потому что сервер в России, а я в США. В итоге поменял местами версию для вебплеера и WebGL. В конце концов, не так уж сложно посмотреть версию под вебплеером – инструкция висит над каждой игрой на сайте Ludum Dare.

Напоследок можно посмотреть всё тоже самое, но на ускоренном видео под музыку из игры, включая не вошедшие треки.

В конце хотел бы подвести итоги. Вернее обозначить, где был не прав и что стоило бы улучшить:

1) Без апгрейдов скорость полета очень медленная. Меньше, чем нужно, чтобы ощутить драйв. Или сделать, чтобы скорость росла без лимита.
2) Совсем нет звуков. Хотя бы клики и удары можно было озвучить.
3) Тему джема нужно раскрывать сразу, иначе многие не поймут и заминусуют.
4) Нарратив, история, персонажи, всё такое — хотел добавить, но не осилил.
5) Больше разнообразия в препятствиях. Хотел сделать варианты турелей, которые бы стреляли по игроку, но совсем не успел.
6) Игра вообще без юмора получилась. Пришлось снять её с этой номинации. А юмор это хорошо и полезно для виральности.
7) Это просто чудо, что людей не тошнит от моей музыки. Нужен более надежный способ её создания.
8) На финальную сцену было потрачено больше времени, чем следовало тратить на то, что многие не увидят.

Switch language:
Facebook