ImpossibleColors - Первый html5 блин, и даже не комом ))

Привет всем! У меня выдалось свободное время, и дабы занять его чем то интересным, а может быть даже и полезным, я решил сесть и написать этот, достаточно полный, обзор разработки первой html5 игры — ImpossibleColors(Играть).
Итак, после того, как провалилась(в финансовом плане) наша последняя flash игра SuperBoxotron2000, стало очевидно что Flash, как инструмент заработка, действительно отходит в мир иной и необходимо искать новые ниши для разработки. Очевидном выбором стал html5, игры под который имеют приблизительно ту же “суть” и “вес”, однако в отличие от flash имеются еще более жесткие ограничения по производительности и поэтому в первую очередь встал вопрос о выборе корректной идеи для игры.

Идея игры:
Идею надо было выбрать такую, что бы она не только была бы мало-затратна по ресурсам, но и достаточно быстро реализуема, так как это был новый опыт, и пилить очередной долгострой без каких либо гарантий, желания абсолютно не было. Установленные сроки разработки — от 2 до 4 недель. Спустя небольшой срок, мой напарник-художник Захар(с ним же мы делали и боксотрон на flash), показал мне видео игры в жанре изометрический-пазл: “Hocus” (смотреть трейлер) и предложил эту идею в качестве основы новой игры. Я же, сломав себе мозг после первой минуты просмотра трейлера, смотрел на эту идею, как на “вызов”, так как первый раз за очень долгий срок у меня как у программиста возникло подзабытое чувство, когда ты смотришь на что то, что нужно потенциально “закодить” и даже не представляешь с какой стороны подступится… Челендж? — Вызов принят!
Вообщем после того как я пересмотрел трейлер раз 10 и хотя бы точно уяснил “визуальные” правила и принципы по которым строится уровень, сказал что мне нужно пару дней дабы обмозговать все и систематизировать, после чего я отвечу, возьмусь я за такое или нет.

“Учи мат. часть”:
Итак все что у меня было это… пару видео на ютубе к игре “Hocus”, которая была взята за основу, полное отсутствие опыта работы с изометрией и полнейшее непонимание того как это можно “систематизировать” и вывести общие правила перемещения\постройки таких “иллюзорных” конструкций, дабы впоследствии перевести это в код. Поэтому разработка началась, как обычно, не с открытой IDE и кода, а с листочка бумаги, карандаша и гугла. К моему огромному разочарованию гугл, на запросы по моим вопросам — молчал, да и было сложно сформулировать запрос когда не знаешь с чего вообще начать и что тебе нужно, что было очевидно — там изометрия, как в ней строить и отрисовывать последовательно объекты было и так понятно, а вот все остальное… Как организовать постройку стен? Как структурировать стены? Как строить чисто визуально эти “невозможные” конструкции? И одно из самых сложных: Как организовать “сцепку” стен? (когда стены визуально и программно находятся на разных высотах, но при этом для геймлпея высота у них одинаковая, то есть они — сцеплены).

Первое с чего я начал — это решение проблемы отрисовки стен, то есть обеспечение возможности постройки иллюзорных конструкций, а за основу всех иллюзий, можно взять вот такой вот “невозможный” треугольник:


Я думаю большинство понимают о какой проблеме отрисовки я говорю, но на всякий случай, вот пояснения:


Решением данной проблемы было очень простым и не требовало особых мозговых потуг, суть в том, что на «стыках», там где соединяются стены мы должны использовать не «честные» блоки\стены, а «обрезанные», таким образом, что бы две обрезанные стены расположенные стык-в-стык визуально создавали единую стену, но при этом уже абсолютно не важно в какой последовательности их отрисовывать:


Приблизительно в этот же время возни с отрисовкой я наткнулся на второе видео по «Hocus»(смотреть видео) где демонстрировалась работа редактора, и можно было подглядеть некоторые технические особенности, в частности — то что стены образовывали единый «монолит» именно с помощью такой хитрости. Второй важной деталью, которую я почерпнул из этого видео была — гексагональная сетка, и как только я ее увидел все мгновенно встало на свои места — структура построения уровня ясна. И если со стыками стен все было более-менее очевидно, то вот гексагональную структуру сам я не разглядел, так как до этого не имел с ней дела, но когда я увидел эту сетку стало очевидно, что гекс тут подходит как нельзя кстати, так как он идеально описывает структуру изометрии и доступное перемещение в 6 направлениях. Ячейки же гексов являлись структурными точками, в которых происходило строительство «пучка» стен, исходящее из центрального блока\центра гекса, обрезка же стен как раз происходила по границе принадлежащего ей гекса:


После того как это было освоено, я располагал всей необходимой информацией для того, что бы собрать простенькую демку, где можно было бы строить всевозможные изометрические конструкции с «невозможными» элементами. Это я и сделал, родной FlashCS6, код в кадрах, пара часов работы и вуаля — демка готова, к слову возможность писать код в кадрах во Flash — одна из моих самых любимых, так как при необходимости позволяет добавить интерактивность буквально в несколько кликов\строк. Вообщем после того как я собрал демку в которой можно было строить всякие ломающие мозг фиговины, я посчитал что в целом понял основную суть, разобрался почти со всеми потенциальными проблемами и отписался Захару, что да — могу и берусь, однако...«я еще никогда так не ошибался» :D

Теперь настала пора начинать саму html5 игру. Как я и говорил это был мой первый именно html5 проект, однако с JS до этого я был знаком и более того — он мне очень нравится, просто в моем понимании в отличие от строгого Объектно Ориентированного подхода являющемся «позвоночником» и основной парадигмой, для таких языков как любимая мной Java, или навевающему не лучшие жизненные воспоминания C#, JS предлагает взглянуть на программирование немного под другим углом, попробовать другую парадигму, и если это понять и принять, вместо того что бы пытаться выродить из JS строгую Java, то из недостатка и неудобств это может превратится в колоссальную силу, с одним названием — гибкость! Таким образом в целом, сам процесс «программирования» не принес особо никаких сюрпризов и переход на новый язык почти никак не сказалось на скорости разработки. В качестве движка был выбран Phaser, которым в целом я доволен, однако по моему субъективному мнению в нем куча всякого ненужного хлама, что говорится «из коробки», и мне это не очень нравится, к тому же(возможно!!!) это сказывается на производительности и не в лучшую сторону(конкретных тестов не проводил, чисто субъективное ощущение по падению производительности по ходу разработки на ровном месте), поэтому потенциально новые проекты под html5 буду делать скорее всего с использованием голого PixiJS.

Начало разработки — редактор
Начал я с разработки не самой игры, а редактора, в котором я планировал реализовать все те же механизмы что должны быть и в игре, продумать архитектуру, а впоследствии перенести это все в игру, поэтому редактор разрабатывался в виде отдельных классов\объектов\модулей, которые бы легко «переносили» миграцию. В первую очередь необходимо было воспроизвести функционал реализованный в flash-демке, то есть гексагональное поле с постройкой стен, однако если в flash-демке у меня по сути просто рисовались стены по нужным координатам привязанным к центру соответствующего гекса, то здесь уже было необходимо продумать общую архитектуру, и в первую очередь что бы стены были не просто картинками, а некими «жесткими» объектами, на которых может «стоять» ГГ или другие объекты и вдоль которых можно перемещаться, а так же некоторые другие «игровые» особенности и детали. И первое с чего я начал, и что пришлось выродить — структура каждого гекса.
Суть в том что каждый гекс должен был содержать игрока, кубики, но самое главное стены, и надо было как-то искать доступные направления для перемещения ГГ. Решать проблему псевдо «физики» и перемещения «в лоб» было глупо, хотя наверное и возможно, что бы при постройке каждая стена хранила какие то доступные точки, на которых может находится ГГ, какие точки достижимы из данной и т.д., но это было не для меня, я решил продумать «общую» структуру для гекса, которая позволила бы свести все к нескольким общим методам, и в случае чего добавлять\расширять функционал и геймплей, что в последствии кстати избавило меня от тонны проблем.
Так же после решения проблем с отрисовкой и применения гексагональной сетки, было сделано еще одно, достаточно важное открытие, а именно что все «ломается» и вся «магия» происходит именно на стыках гексов, где и порождаются иллюзии, внутри самого же гекса сохраняется абсолютно нормальная изометрическая структура без каких-либо выкабенов! Из этого вытекла вполне логичная структура самого гекса — трехмерный массив[x, y, z] хранящий «сетку» изометрического «псевдо» 3D, сама сетка состоит из «псевдо» блоков имеющих следующую структуру:
Код
var Block = function(hex, x, y, z)
{
	this.width = 45; // "Физическая" ширина
	this.height = 52; // "Физическая" высота

	this.hex = hex; // Родительский гекс
	this.x = x; // x данного блока в координатах 3D "сетки" гекса
	this.y = y; // y данного блока в координатах 3D "сетки" гекса
	this.z = z; // z данного блока в координатах 3D "сетки" гекса

	this.tags = []; // набор тегов, применяется для проверки наличия в блоке некоего содержимого
	this.targetBlock = null; // ссылка на кубик который собирает ГГ, если он в данном блоке
	this.wall = null; // если данный блок пренадлежит "стене" то здесь ссылка на стену

	this.twin = null; // блок "близнец" для "варп" прыжков между гексами и внутри гекса, об этом позже

	this.z_index = 0; // по значению этого индекса сортируются объекты, и отрисовываются
};



Теперь соответственно все объекты на поле, отлично структурированы и привязаны к конкретному блоку, конкретного гекса, и внутри этого блока есть ссылка на этот объект, то есть мы спокойно можем определять «пути» для ГГ так как, идя вдоль какой то координаты и перебирая блоки, мы можем проверять есть ли внутри этого блока например стена(когда создается стена, то она занимает под себя соответствующие блоки в гексе) или есть стена у соседа снизу, и если да, то все — проход закрыт, пути нет, и т.д. таким образом мы можем проверять наличие и получать любые объекты, так как они не «висят в воздухе» где-то в куче массивов, а строго привязаны к конкретному блоку, то есть строго определены на поле!
После того как это сделано, по сути все геймплейные задачи практически решены, мы можем определять доступные пути движения для ГГ, а так же проверять есть ли на его пути кубики, которые можно подобрать. Блок остановки для ГГ(конечная точка движения) высчитывается по простому правилу — если по данному направлению движения прохода дальше нет(стена) или есть другие доступные направления из проверяемого блока кроме изначального и обратного изначальному. А поскольку у каждого блока можно получить не только его координаты в 3D «сетке» гекса, но и обычные xy координаты на поле, то перемещение между блоками вообще не вызывает никаких проблем — сначала находим конечный блок, а затем перемещаемся в его уже 2D XY координаты.
Простая функция вычисления XY у блока:
Код
Block.prototype.getPosition = function()
{
        // this.x, this.y, this.z - координаты внутри 3D "сетки" гекса
	var x = this.hex.centerX + this.x * 22.5 + this.y * -22.5;
	var y = this.hex.centerY + this.x * 13 + this.y * 13 + this.z * -26;
        // x, y - уже рассчитанные 2D координаты на поле

	return new Phaser.Point(x, y);
};


Все бы замечательно, если не одно ОГРОМНОЕ НО, у каждого гекса, своя «сетка» блоков, и допустим мы проверяя доступное направление для ГГ вверх-вправо, дошли до конца «сетки» текущего гекса, как перейти на «сетку» следующего гекса, ведь координаты внутри «сетки» каждого гекса свои, и (0,0,0) координат это центр гекса, и у всех он свой, данная проблема была мной решена путем добавления одного блока пустышки по всей грани «сетки» в начале и конце для каждой координаты x, y, z, и каждый такой блок пустышка ссылается уже на конкретный блок, но находящийся в соседнем гексе, короче дойдя до края сетки одного гекса, там будет блок пустышка который отошлет нас на блок в начале «сетки» но уже соседнего гекса(аля связный список), такой скачок для себя я назвал «варп прыжок», мде объясняю я конечно… может быть графически будет яснее:




В целом получилось может немного запутанно, но зато работает идеально и быстро. После того как я завершил данный этап, можно было уже спокойно и без ошибок перемещаться по построенному полю. Еще раз общая система в двух-словах: поле состоит из гексов, внутри каждого гекса «псевдо» 3D сетка, состоящая из «блоков», когда мы строим стену или создаем объекты на поле(ГГ, кубики) они занимают под себя конкретный блок\блоки, конкретного гекса, сетки гексов связаны между собой с помощью «прыжков», и мы можем спокойно перемещаться вдоль любой оси сетки с переходом на соседнии, а следовательно у нас есть все данные для того что бы определять доступные пути перемещения для ГГ.

Стыки и визуальный переход ГГ между гексами
Имея описанную выше структуру все работает как часы на «программном» уровне, а вот в визуальном отображении, на стыках возникаю проблема:


И вот тут, какого то общего, красивого решения я не придумал и было решено пойти на хитрость — когда герой находится на краю сетки гекса, в последнем блоке, его z-index, начинает высчитываться не исходя из позиции его блока в «сетке», а исходя из того по какой грани сейчас движется ГГ, и на основе этого ГГ просто отрисовывается либо «над всем», либо «под всем»:


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

Итоги
После того как был полностью реализован геймплей, собраны менюшки, запилен туториал и пофиксены все(ну или почти все:D) баги, настал самый волнующий момент — поиск спонсоры и продажа. Лично для меня в плане продажи все было совсем не очевидно, рынка html5 я практически не знал, контактов и наработок со спонами не было, а вот страхи и неудачный опыт был, поэтому даже зная, что объективно получилась качественная игра, в финансовом результате уверенности не было. Однако переживал я не долго, и все сомнения были развеяны почти мгновенно — как только Захар отправил письма спонсорам, сразу же отозвались спилы, и после недолгих переговоров, сходу, предложили 4.500$ — мы сияли, так как это сумма была для нас вполне солидной, и мы без особых раздумий согласились. Далее была интеграция брендинга, еще раз баг-фиксы, заполнения бумажек по переводу, беганье в банк по несколько раз в день(банковская система, как при царе горохе, честное слово...) для того что бы таки заполнить «нужные» реквизиты и ничего не перепутать, что в итоге меня задолбало и в мы просто сделали перевод на PayPal, потом ожидание оплаты, долгожданная смска о переводе, и полное удовлетворение когда спустя недели три после начала всей этой возни оплата наконец «на руках». По срокам конечно мы не вписались в ожидаемые 4 недели, и исключительно на разработку было потрачено около 6 с небольшим недель. По грубым подсчетом вышло около 6.500 строк кода. В целом разработкой я крайне доволен, так как на выходе получилось не только качественная, интересная и финансово успешная игра, но и огромный объем полезного опыта.

P. S. За возможные грамматические ошибки извиняюсь, мой бич))
P. S. По моему получился очень сумбурный рассказ, но писал долго и очень хотел поделится, так что буду в двойне рад, если кому-то материал окажется интересным и полезным )
  • +16

Комментарии (11)

0
Классный пост! Спасибо!
0
На рынке html5 сколько активных спонсоров? Каковы тенденции и ожидания на ближайшие полгода-год? Опираться на одних Спилов как-то не очень. Имхо.
0
Поскольку именно продажей и переговорами занимался не я, отвечу насколько знаю: Самыми первыми и достаточно быстро отозвались спилы, предложили цену и мы согласились, потом писало вроде еще несколько спонов, но поскольку мы уже договорились со спилами, то с другими спонами ничего конкретного уже не обсуждалось. Как сказал Захар(он занимался продажей): «Активных спонов на пальцах пересчитать можно, а часть из них ориентирована на определенный тип игр (спортивные, слоты), так что на деле вообще остается несколько».
Вообще нельзя сказать, что все прям замечательно, но после этой игры мы сделали еще одну(Играть), без массовой рассылки предложили спилам и они взяли, а так же дали понять что готовы и дальше сотрудничать. Так что кол-во спонсоров не впечатляет, но те что есть, пока берут и за адекватные деньги, так что думаю на ближайшие пол-года\год «рынок» еще будет существовать и можно работать.
0
LongCat гениально, вы молодцы!
0
Соглашусь с Vogd, очень прикольная!) Откуда вы идеи берете?))
+1
0
Возможно, возможно =)
0
Эксклюзивно ушла игра? или еще планирует сайтлоки продавать?
0
Да, эксклюзив в одни руки.
0
Отличная статья, отличная игра!
0
Поиграл. Не сразу понял. Не помню точно, но там же не было анимации-примера перетаскивания кубиков по сторонам фигуры? Мне такое обучение кажется более удобоваримым, чем любой статичный текст.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.