Раннер под iOS с пятью персонажами
Привет, хабр! Так случилось, что я довольно давно занимаюсь разработкой под iOS, но вот незадача — никогда не писал игры. После змейки в 13 лет под IBM 386 наступил перерыв до 2014 года, когда я набрался сил воплотить теплую ламповую мечту в реальность. Что из этого получилось? Графика сводилась так: А геймплей хотелось сделать похожим на это: Если интересно, прошу под кат! (много картинок!)Проект некоммерческий, без пурчейзов, рекламы и смс, да и на текущей стадии напоминает скорее концепт. Возможно, читателям хабра знакома вторая картинка — одним прекрасным днем я увидел ее в этом посте, да-да, восторженные комментарии мои. Сначала немного слов про графику.
Графика.Я, к счастью или к сожалению, обычный программист и рисую довольно жалко, поэтому пришлось искать художника. А какой бюджет может предложить женатый мужчина для своей развлекалочки? Ну, оказалось в итоге около $1000, но конечно же этого не хватило бы на профессионального гейм-художника, поэтому спустя какое-то время вышел на девочку, которая весьма неплохо рисует в акварели, но фотошоп не видела в глаза. Начали с фона и, так как я всегда хотел сделать хоррор, жутких деревьев. Сканы вышли такими (картинки кликабельны): Последний скан — платформа — так вообще напомнила мне чем-то первый StarCraft по цветовой схеме. И так мне эта акварель понравилась, что я решил не переводить её в вектор и оставить как есть, вырезав и маленько подретушировав в фотошопе. В итоге из множества эскизов в игре появилось 13 видов деревьев, 2 вариации платформ и 5 персонажей, за которых предлагается одновременно играть игроку. В бумаге это выглядит так: C персонажами получилось сложнее. Из многих-многих вариантов деток мы выбирали очень долго. Первоначально я даже не знал, сколько их будет — с клавишами получалось естественней, но на экране айфона места не так много, как на midi-клавиатуре. После долгих экспериментов их осталось 5. Весь список еле уместился на фотографию: После сведения всего скриншот с победителями выглядит так: Всем персонажам дали клички, к примеру самый тощий — Освенцим. Кое-кого назвали в честь внешнего сходства с коллегами. С анимацией было сложно, освенцима пришлось даже переделать (в текущей версии он дергается, как паралитик, в версии 1.1 вылью обновленного). Сводил все по слоям в фотошопе, проверял анимированным гифом. На сведение и вырезку одного персонажа уходило примерно 3 часа: Зато результатом я весьма доволен. Конечно, современные дизайнеры и аниматоры ставили в упрек маленький FPS анимации — она состоит из восьми кадров для каждого игрока — зато картинки получились уж очень похожими на мультфильмы 20–30х годов прошлого века: Мне сразу стало интересно — все эти точки, штришки, потертости, появляющиеся на кадрах, в старых мультиках появились по причине старения пленки, либо же как у нас — от случайных движений карандаша по бумаге? У них ведь не было понятия пост-продакшена, картинки скорее всего отснимались и клеились как есть. Если у кого есть информация или соображения, поделитесь пожалуйста в комментариях.Программинг. Изначально я разработал полностью работающий прототип на Cocos2D+Box2D, но мне не понравились несколько нюансов:
С точки зрения Box2D, каждый игрок представляет собой параллелепипед. Если бы бежал один игрок, некоторые огрехи и погрешности просчета физики были бы просто незаметны, а при синхронном беге пяти игроков в произвольные участки времени дистанция между ними то сокращалась на пару пикселей, то наоборот увеличивалась. С чем это было связано, я так и не разобрался, но нашел в интернете информацию, что такие сложные движки не стоит использовать в раннерах хотя бы по этой причине — выходит, не я один наткнулся на эти грабли; Мне не особо понравился Cocos2D ввиду его слабой инкапсуляции — в SpriteKit код получается короче и более понятным, ввиду отсутствия ОГРОМНОГО_ВИДА_OPENGLES3_КОНСТАНТ и иных прямых вызовов OpenGL, которые мне порой напоминали кошмар WinAPI — нужно либо знать его досконально, либо курить кучу документации и форумов, что в конечном итоге приведет к доскональному знанию огромного количества констант, без которого мне неплохо живется. В итоге я переписал все на SpriteKit (а что, имею право, проект-то мой), а в качестве физики написал примитивный движок — не более, чем требуется для 2D-раннера, строк на 100. Ничего интересного или нового в нем нет, любой программист напишет такой же за день. Зато единицы измерения из сферических в вакууме превратились в пиксели на секунду и на секунду в квадрате — с такими вполне приятно работать, в отличие от абстрактных для девайса метрах :)
А вот с миром пришлось знатно повозиться — изначально я хотел написать бесконечный скроллер с автогенерируемым миром, что и доставило мне массу приятных и не очень впечатлений. Все слои видимого мира генерируются случайно, по определенным законам, в некоторых из которых (например, алгоритме генерации деревьев на фоне) я не могу разобраться до сих пор. Код пестрит магическими константами вида «три корня из двух на два», которые с течением времени утеряли для меня смысл — зато смотрится прикольно! Наверное, про это стоило бы написать отдельную статью.
Также я довольно хитро сделал параллакс деревьев — когда крутишь телефон в руках, они изображают 3D-эффект. Добавил невидимую вьюшку, параллакс которой обсчитывает сама iOS, и на каждый тик игры считываю дельту ее координаты, которую умножаю на удаленность дерева от пользователя (1 — самое дальнее, 0 — самое ближнее) и складываю с (X; Y) самого дерева. Получается довольно симпатично и производительно.
Кстати, с производительностью тоже пришлось изрядно повозиться, но тут больше по неопытности — к примеру, самым большим тормозом оказалось то, что я обращался к UIKit-элементу на каждом цикле перерисовки. Наконец-то я понял, для чего в игровых движках есть свои кнопки и лэйблочки! А я-то, неуч, сделал HUD на обычных iOS-овых контролах.
Заключение. Музыку мне по знакомству написал лидер одного белорусского рэп-коллектива за символическую плату в 1 банку бабушкиной аджики, которую он любит со времен обучения в институте. По-моему, она прекрасна сама по себе (и музыка, и аджика). Остальные звуки нашел наш тестировщик Игорь на стоках, за что ему огромное спасибо как и всем, кто помогал мне в создании игрушки. Чуть не забыл, ссылка на апстор, приятной игры! Буду рад каждому комментарию!