Разработка одной игры — новый заход, Ч2

в 13:59, , рубрики: cross-platform development, game development, Lua, mobile development, метки: , ,

Skippy's photoВот и пришло время продолжить рассказ об увлекательном хобби — геймдеве — разработке казуальных игр.
Ранее в статье я рассказал о первой своей игре под Андроид — «Draw and ride», которая подтолкнула меня пересмотреть подход в этапах создания и продвижения мобильного приложения. Сегодня я хочу поделится тем, к чему же я все-таки пришел после своего первого опыта и рассказать о создании новой, кросспалтформенной игры под Android и iOs, так же по дороге была сделана html5 и Tizen версия, но обо всем по порядку…

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

Вместо сухого описания процесса разработки, я предпочел выстроить рассказ как сравнение подходов в разработке двух игр — старой «Draw and ride» и новой «Skippy the traveler», ведь по сути не так важно что именно я сделал, как то, на сколько статья поможет Вам сделать собственные выводы, принять собственные решения и натолкнуть на гениальные идеи, которые, я надеюсь, выльются в первоклассные приложения!

Дальше найдете описание всех этапов разработки — от идеи до релиза, в свете чего получилось «много букв», разделенных по этапам, поехали!

С чего все начиналось

Идея «Draw and ride» была от части навеяна ранее популярными флеш и не только играми на PC, и, в общем, я никогда не скрывал, что в поисках идей ходил по разным игровым сайтам, искал то, что бы меня зацепило. Такими темпами поиски довели до игры, которая и послужила прототипом для мобильного развлекательного приложения.

Данный подход хорош в том плане, что «все новое — хорошо забытое старое» (с), но, к сожалению, он не учитывает маленькой, но очень важной детали — управление на PC мышкой и клавиатурой довольно сильно разнятся с тем, что мы видим сегодня на планшетах и телефонах, когда взаимодействие с устройством происходит на «кончиках пальцев». В новой игре надо было сначала продумать максимально простой вариант геймплея и взаимодействия пользователя с виртуальным миром.
Было решено выделить «скелет» наиболее удобной и привлекательной игры, основываясь на предыдущем опыте, и, главное, успешных проектах других классных разработчиков. В ходе небольшого анализа и изучения рынка мобильных казуальных игр появился список этаких ключевых аспектов «удачной мобильной казуальной игры»:

Мой рецепт "удачной казуальной игры"

Максимально легкое управление, идеально — один жест

Если посмотреть то, во что играют люди, можно заметить стремление к связке — минимальное взаимодействие с экраном телефона + максимальная интерактивность. Как примеры хорошо подходят «Angry birds» — единственное движение — свайп приводит к динамическому развитию сюжета и цепной реакции, в ходе которой весь игровой мир приходит в движение; «Cut the rope» — опять же изначально только лишь свайп, далее вводятся более сложные взаимодействия, но только после освоением пользователем базовых навыков.

Теперь можно на минутку отвлечься на «Draw and ride» — с самого первого уровня требуется относительно серьезный скилл точного позиционирования пальца на экране, одновременного переключения режимов игры и аналогового управление джойстиком… рядовой пользователь вполне обоснованно снесет приложение после первых же неудачных попыток.

Пробуя различные варианты геймплея можно прибегнуть к простому, но очень эффективному способу проверки «играбельности» — дать приложение ребенку, сесть рядом и наблюдать. Моя 5-ти летняя племянница спокойно играет и любит Cut the rope, с новой игрой она справилась относительно быстро. Касательно «Draw and ride» — тут можно привести слова моих партнеров — корейцев: «Игра вполне может пойти в Корее, они любят хардкорное управление».

Геймплей превыше всего

Возьмем, к примеру, любимые издателями f2p игры, такие как «Clash of clans», если посмотреть — такого рода игры были еще и в браузерах до массового появления смартфонов и планшетов, главное время от времени заходить в игру, поставить строитсяисследоватьвоевать виртуальных человечков и можно дальше пойти посмотреть любимый сериал. На мой взгляд, при хорошей реализации, социальные мультиплеерные игры не нуждаются в инновационном, интересном геймплее, люди часто приходят не только за игрой, но за общением и попутно показать «кто тут главный».

Теперь давайте вернемся к казуальным не социальным играм. Для чего человек скачивает и что заставляет его возвращаться к игре? Только сам игровой процесс, больше особо нечему. И что тогда будет если он (геймплей) будет скучен? Человек вряд ли запустит приложение более одного раза.

Сейчас, смотря как пользователь на «Draw and ride», становится очевидно, что на первом же уровне, пользователь впадает в ступор — не понятно ни что нужно делать, ни зачем это нужно делать, даже не очевидно как… «Skippy» же с самого первого уровня учит и объясняет как и для чего нужно двигаться вперед и проходить все новые уровни, пытаясь с самого начала не отпускать пользователя.

Пользователя нужно учить

При разговоре о геймплее стоит упоминуть тот факт, что при длительной разработке игры он успевает приесться и кажется, что управление очевиднее некуда, а уровни пройдет даже младенец, но попробуйте дать другу игру и попросить пройти первый уровень… В моем случае в «Draw and ride» не справился практически никто, в «Skippy» до появления обучающего экрана справилось чуть-чуть больше народа. После заботливого объяснения через интерфейс игры ситуация кардинально меняется — пользователя не вводит в ступор первый же уровень, что несомненно повышает его лояльность.

Сложность от уровня к уровню опять же стоит тщательно выверять, ведь когда строишь очередной уровень, зачастую ответ известен заранее, а если посмотреть со стороны, то что поставлено вторым по сложности вполне может сойти и на сто второй. К примеру в том же «Skippy the traveler» были несколько уровней, которые мне казались не очень то и сложными, а примерно через месяц, после того как я к ним вернулся и попробовал пройти, получилось это сделать раза с 6-7.

Мотивация для возвращения

Что только люди не придумают, чтобы заставить своих пользователей день ото дня возвращаться в приложение: и бонусы за дневное посещение, и отдельные ивенты, и назойливые напоминания с пуш уведомлениями. С своей игре я решил попробовать не вводить на первом этапе поощрения за отдельно взятое дневное посещение (банально не смог придумать, чем можно на столько завлечь пользователя), но постарался дать мотивацию для прохождения всех уровней, а именно — раз игра про лягушку-птуешественницу, то путь будут после каждого вновь пройденного уровня интересный факт с стране «пребывания». В дальнейшем есть идеи — выводить «Факт дня» в отдельном окне, но не понятно, на сколько это может быть важно для пользователей.

Сюжет вокруг главного(ых) героя(ев)

Вспомните такие хиты, как «Cut the rope», «Angry birds», «Where's my water» и другие — везде игровая механика завязана на помощи милым созданиям, котроым необходима именно Ваша помощь. При таком подходе кроме всего прочего на мой взгляд происходит более тесное сопоставление одной конкретный игры с ее названием и персонажами, ведь игр, где можно чем-нибудь куда-нибудь запустить можно найти не мало, а «Злобные птицы» — одни. Нельзя утверждать, что без ярко выделенных героев игра бы не слилась даже со своими же клонами.

Разработка одной игры — новый заход, Ч2«Skippy» олицетворение игры — милый (на сколько конечно получилось сделать его таковым) лягушенок с портфелем и в кепке, без него это была бы очередная логическая игра, где нужно пропрыгать по стрелочкам.

Мягкая монетизация

В мыслях о том, как же издаваться я обращался к разным издателям — от небольших компаний, у которых есть просто свои изданные приложения, до таких гигантов как chillingo, rovio, glu и другие, сейчас большинство твердят о том, что хотят выпускать f2p игры, в целом я их конечно понимаю, в теории с пользователя f2p можно получить заведомо больше, нежели с paid/freemium игры, но больше всего мне не понравилась позиция менеджера проектов одной довольно крупной компании — суть заключалась примерно в том, что игры должны зарабатывать, а все остальное (геймплей и тд) потом (а в целом, если они зарабатывают, то и вовсе ничего больше не надо). Я целиком верю в то, что первично крутое приложение, которое нравится пользователям и которые в него играют и делятся своими эмоциями, а классный продукт уже потом можно монетизировать.

Именно по этому и в «Skippy» придерживался позиции максимально мягкой монетизации — можно отключить рекламу (которая появляется только тогда, когда не мешает пользователю — между уровнями — и не блокирует дальнейшее взаимодействие), можно приобрести небольшие упрощения игрового процесса, такие как подсказки. Но целиком игру от начала и до конца можно пройти без единого цента.

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

Проектирование

Должен сказать, о том, чтобы подумать как вообще должно строиться приложение, при создании «Draw and ride» я даже не задумывался — делал по мере прихода новых мыслей и идей, тут можно сказать одно — я не очень советую так делать.

«Skippy» изначально создавался на бумажке, в голове прогонялись разные возможноые сценарии, разные расположения экранов и элементов и только после того, как рабочий стол был уклеен разными набросками и схемами встала задача о выборе того, где же буду делать в итоге игру.

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

В целом, оглядываясь назад, можно сказать, что прототипы, экраны и идеи стоило бы изначально заводить в цифровом виде, но с поры «Draw and ride» я считаю новый шаг сделан и можно с уверенностью сказать, что разрабатывать по готовым макетам и прототипам куда удобнее, чем по идее в голове.

Дизайн

«Draw and ride» было нарисовано от руки и на тот момент это было еще не до конца избито, но сегодня я прихожу к выводу, что дешевле отдать некоторые вещи на откуп профессионалам, что в общем я и сделал. Фриланс богат на хороших специалистов, надеюсь «Skippy» придется вам по душе!

Screenshot Screenshot

Как, где и на чем делаем?

«Draw and ride» была по сути одним из первых опытов разработки под андроид, тогда даже и в голову не приходило что можно или нужно писать на несколько платформ, новую игру же изначально было решено делать «серьезно», как минимум под iOS + Android.

В ходе изучения разных возможных вариантов разработки приложения — от нативных двух разных приложений до всяких разных фреймворков (описание и сравнения которых есть в избытке, в том числе и на хабре), выбор пал на corona, потому что что больше всего понравилось:

  • Относительно не высокая цена (сейчас поднялась, была в районе 350 дол),
  • Хорошая документированность,
  • Активное сообщество, которое пользуются, общается и помогает,
  • Относительно не сложные примеры.

Не обходится тут и без минусов:

  • 3d party libs можно добавлять только в enterprise версии (~1000уе),
  • Закрытие исходники, т.е. допилить внутри недостающий функционал можно только через п.1,
  • Делать большие проекты на скриптовом языке требует отдельного навыка, мне, к пример, отсутствие ООП сильно мешало.

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

Лично я далеко не мастер скриптов и lua не мой родной язык, в итоге в ходе работы над проектом возникали вполне стандартные проблемы, которые порой решались нестандартным на мой взгляд способом.

Интересные сложности с lua и corona

Откровенно говоря это мой первый опыт с lua, по этому ну судите строго, описываю моменты, которые показались мне с первого взгляда не самыми тривиальными.

Lua и ооп

«Из коробки» lua не поддерживает ООП подход, но в нем реализованы метатаблицы, на которых можно построить некое подобие ООП самому, также на днях мне посоветовали посмотреть в сторону готового решения проблемы, но честно говоря его еще не пробовал.

Как сделать свой класс на метатаблицах описано в сообществе coronasdk вот тут:
www.coronalabs.com/blog/2011/09/29/tutorial-modular-classes-in-corona/

Поддержка разных разрешений

Как организовать поддержку максимально возможного зоопарка устройств описано хорошо вот тут:
developer.coronalabs.com/forum/2012/03/12/understanding-letterbox-scalling

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

Локализация

Самый удобный вариант, что я нашел, это сделать отдельный lua файл, примерно с таким содержимым:

local translations =
{
    ["test"] =
    {
        ["en"] = "Test",
        ["ru"] = "Test",
    },
    ["play"] =
    {
        ["en"] = "Play",
        ["ru"] = "Играть",
    }
}

function setLanguage() -- выставляем язык приложения (по идее для частичной локализации можно выполнять проверку каждый раз)
    language = system.getPreference("ui", "language")
    if (string.lower(language) == "english") then
        language = "en"
    elseif (string.lower(language) == "русский") then
        language = "ru"
    end
    if (string.lower(language) == "1049") then -- 1049 - эксперементально выяснено то, что возвращается симулятором
        language = "ru"
    elseif (translations["test"][language]) == nil then -- если нет перевода для языка, то используем английский (именно для этого переменная test).
       language = "en"
    end
end
 
return translations

А в тех местах, где нужно использование локализованной строки остается лишь использовать:

translations = require("translations") -- локализация, для удобство можо объявить в одном месте, в самом начале
translations["play"][language]

Замыкания

На экране с выбором уровня, где располагается сетка n*m элементов необходимо передать выбранный элемент в универсальный обработчик событий, в связи с тем, что хендлер задается для определенного события таким образом:

level:addEventListener( "tap", onImageTap);

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

level.idLevel =  value

и тогда сам обработчик будет выглядеть примерно так:

function onImageTap(event)
    level = "levels/"..packNum.."/"..event.target.idLevel

Анимации

На главном экране игры можно увидеть два вида анимации — циклическая по кругу (облака уплывают за экран) и циклическая с обратным ходом.
Первый вариант делается довольно легко, путем вызова внутри обработчика конца анимации самого себя:

cloudListener = function( obj )
    if (obj ~= nil and obj.width ~= nil) then -- если не ушли со сцены и объект еще живой
        local aTime = nAnimationTime * (30 + math.random(30)) -- рандомная скорость анимации
        obj.x = - obj.width -- перед анимацией вернуть объект на исходное состояние
        transition.to( obj, { time=nAnimationTime, x = display.actualContentWidth + obj.width / 2, time = aTime, onComplete = cloudListener} )
    end
end

Вторая ситуация обрабатывается также, только на этот раз будут 2 обработчика, которые по очереди вызывают друг друга.

Если объект остается жить после ухода со сцена необходимо не забыть очистить анимацию — transition.to возвращается object, который можно потом осободить от анимации:

transition.cancel(animtaionObject);
Поиск утечек

Для Conorы есть удобный сторонний дешевый профилировщик, который представляет из себя lua файл, который вставляется в проект и в потенциально проблемных местах вызывается метод сбора задействованных объектов, после Nого повторения, например открытия сцены, накапливается пул объкетов и анализ выводится в html страничку, по которой сразу видно где и какие объекты не умирают. Таким образом получилось отловить проблему, из-за которой моя игра начинала жутко тормозить после определенного количества сыгранных уровней.

In-app покупки при сборке под ios

В официальной документации подробно расписаны шаги, которые нужно проделать для тестирования in-app покупок, но почему-то нигде не смог найти один маленький, но очень критичный нюанс (особенно, если раньше непытались разрабатывать под iOS): необходимо в build.settings в секцию, описывающую ios приложение добавить 'CFBundleIdentifier = «yourbundleid» ', после этого, все сразу взлетело.

Система контроля версий?

Непосредственно перед разработкой встал вопрос — нужна ли вообще какая-либо система контроля версий, или, когда разрабатываешь один, то можно обойтись обычным бэкапом пару раз в неделю? Для меня есть только один правильный ответ — при разработке всегда использовать такого рода хранилища.
Можно привезти несколько вариантов, когда наличие истории изменений оказывается очень полезным:

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

Дизайн уровней — отдельная проблема

Вот без чего, а без уровней, казуальная игра не может существовать как таковая, в «Draw and ride» изначально уровни составлял руками в xml и могу сказать, что работка не из приятных, а редактор появился сильно позже.

В «Skippy» изначально был избран путь через редактор уровней. Были идеи написать его под мобильное устройство, чтобы можно было составлять и в дороге — с телефона или планшета, но более разумным показался вариант небольшого javascripta, который можно редактировать практически на любом девайсе из любого браузера, а результат сразу сохранялся на сервере. В итоге такой подход принес только пользу:

  • Доступность с любого девайса из любого места
  • Хранение результатов в одном месте — на сервере
  • Доступ к исходникам с любого компьютера
  • Простое редактирование скрипта в любом блокноте

Получился редактор, который сэкономил кучу времени и нервов.

Разработка одной игры — новый заход, Ч2

Сортировка уровней по сложности

Каждый уровень игры был пройден после создания, но объективно оценить сложность, не видя картину целиком — не тривиальная задача, тут было найдено опять же универсальное решение:
Сриншотилка + онлайн галерея = сетка из всех уровней, которые позволяют визуально сравнить уровни между собой — должен сказать, получилось очень даже удобно.

*Но любые галереи, прогоны и тд не заменяют тестирование на живых пользователях — дайте друзьям поиграться, то что Вам может показаться элементарным, на деле может быть почти не проходимым для не посвященного пользователя.

Не упускаем шансы засветиться

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

Итак, «Skippy» был портирован усилиями найденного фрилансера на html5 и оттуда на tizen (в дальнейшем ведь можно будет найти применения и веб версии игры). К слову — «Draw and ride» между делом тоже появился на конкурсе.

Итого — потрачено менее 1000 дол на одну игру за возможность небольшого пиара и шанса выиграть деньжат на дальнейшее развитие проектов, пусть процент успеха не так велик как хотелось бы, но «игра стоит свечь» и, если бы я не решился, вероятно, в дальнейшем бы очень жалел. Результаты конкурса будут в начале 2014 года, так что будем ждать…

Следим за нашим пользователем

При создании «Draw and ride» я как-то не задумывался о том, чтобы логировать и отслеживать действия пользователя — а зачем, пусть себе играет спокойно… Сегодня я понимаю на сколько был не прав — подробная статистика позволяет не шпионить за игроком, а дает понять что ему нравится, что нет, какие важные элементы игры он не замечает и многие другие интересные факты.

На многих конференциях, посвященных мобильным разработкам сегодня говорят о том, как сбор статистики позволяет улучшить мобильное приложение, в «Skippy», используя flurry, conora позволяет легко логировать любые события, строя по ним эффективные графики и схемы, по которым можно проанализировать шаги пользователя в приложении, например понять, что ключевую фишку игры человек просто не заметил…

Маркетинг и издание

В прошлой статье можно очевидно наблюдать тот факт, что издатели не зря занимаются своим делом и 100% от 1уе гораздо меньше, чем 10% от 100уе, было решено пойти к издателям. Но не тут то было — на сегодняшний день все как один твердят о желании издавать f2p машины по выкачиванию денег. Вполне понятное желание и такая бизнес модель заведомо генерирует большую прибыль, но я все еще верю в казуальные игры, хотя бы потому, что слово 'casual' близко пользователям — ежедневно люди проводят некоторое время в ожидании, которое идеально можно скрасить парой минут в приложении, которое не требует вовлеченности и может быть тут же выключено без потери прогресса и без одинокого собеседника в онлайновой социальной игре. Ведь именно описанное выше характирезует слово 'casual'.

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

Для начала решил попробовать менее затратный метод — по возможности отправить пресс релизы и заказать обзоры на разных сайтах, таких как:
appadvice.com
androidtapp.com
iphones.ru
4pda.ru
148apps.com и другие, в том числе найденные тут.
О пользе прессрелизов и пресскитов, тут например, говорит Jeff Scott, основатель 148apps.

На сколько я понимаю, обзорные сайт сильно заинтересованы в поступлении новых обзоров интересных для них игр, так что они предлагают услуги по составлении обзора до конечного релиза, чтобы запустить pr машину одновременно с появлением игры в маркетах. (Сегодня ни для кого не секрет, что количество скачиваний в первые дни жизни приложений — очень важный параметр).

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

Финансы и показатели

Вероятно, некоторые читатели найдут данный пункт одним из самых интересных, но… на данный момент о каких-либо результатах говорить рано, если будет интерес, добавлю через некоторое время сюда статистику — интересно посмотреть — на сколько мой подход оказался правильным на сегодняшний день. Получит ли игра отдачу, или, как сказал однажды мой знакомый: «Пробовали, делали, старались… а что получили? Опять опыт.»

PS. Надеюсь я не окончательно утомил своим рассказом? Если хотя бы один любитель геймдева нашел хотя бы один абзац данного сочинения позновательным, я считаю что я не зря провел время… А если нет… я хотя бы попытался, спасибо!

Автор: dilix

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js