козявка

Игровой редактор для платформера — постмортем

Примерно 2.5 года назад мы задумали простенький проект — платформер с определенными свойствами: хардкорный, максимально динамичный, без стрельбы. Платформа — iOS, поскольку мы работаем только с ней — да и Андроид в тот момент еще не был серьезной альтернативой. За эталон был выбран не вышедший пока на тот момент Super Meat Boy.

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

e4659e2ed4146d6a18710a8f8d60f10e

Thus the story begins

Задумывалось это дело как простой “проект на месяц”, поскольку в успех жанра на мобильных платформах верилось не очень. Как мы его делали, тема отдельной большой статьи — но эта статья конкретно посвещена “эволюции” редактора, поэтому останавливаться на прочих деталях я не буду. Главное, что получилось так, что базовый прототип нам настолько понравился, что было решено “добавить фич”. А потом оказалось, что на создание уровней уходит раз в 10 больше времени, чем нам казалось априори, и проект незаметно вылился в самый грандиозный долгострой, который когда-либо выходил из нашего скромного коллектива (нас двое — программист и художник) — игра заняла без малого два года.

За это время игра немножко изменилась:

04add640752f5131fb6cd91f419d1d46

Знакомьтесь, Редактор

Итак, редактор. Редактор уровней я придумал сделать прямо на айпаде — по двум причинам. Во-первых, мой “движок” не поддерживает других платформ кроме iOS. То есть, чтобы сделать редактор на PC, пришлось бы либо портировать весь “движок” и всю игру — чего не хотелось, либо писать редактор отдельно от игры, без возможности поиграть сразу — чего не хотелось также.

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

ea4ba12be23978732a8b9898db646be9

Он сказал — поехали!

Первую версию редактора я сделал довольно быстро — за несколько дней. История не сохранила его вида, но от текущего он практически не отличается — редактор для внутреннего пользования, и какой смысл делать красивости, которые не увидит игрок?
Финальная версия с открытым дополнительным меню выглядит так:

ee921838a0a64c99dc5a9a1e339ac3ac

Идеология была проста — все начиналось с объекта номер ноль, который добавлялся специальной кнопкой. После чего, происходило клонирование до победного конца — новые объекты больше не добавлялись. Сначала копировался старый, потом ему выбирался индекс спрайта, и объект ставился в нужное место. Несмотря на примитивизм, схема работала неплохо. Забавно, но в течение 2-х лет мы выбирали индекс спрайта “на ощупь” — с помощью слайдера, в котором просто листались все спрайты подряд:

1dfc937c0993aef5d52a2eae883c8f28

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

2768ae208838044da5a2de25a41f42c9

What (else) went right

Хоть постмортемы принято писать для самих игр, а не для редакторов, традиционная рубрика кажется мне логичной. Итак, находки:

  • Одной из первых закоденных вещей была следующая штука — возможность дублировать текущий объект в любую из четырех сторон. С одной стороны это может казаться очевидным — но полезность этого была осознана не сразу — казалось расточительным тратить место на экране на целых четыре кнопки, которые делают одно и то же. Более того, если нажать на любую из кнопок-дубликатов, и не отпуская вести ее по экрану, объект стразу начинал перемещение в предположительно нужное место.
    Была даже пятая аналогичная кнопка — она копировала объект без сохранения параметров, выставляя дефолтные значения.
    Эта «фича» давала удобный способ расставлять повторяющиеся объекты, в частности, тайлы.
  • Второй удобной штукой оказалась возможность удаления объектов с помощью простого тапа в определенном углу экрана — в нашем случае, в верхнем левом. Первоначально там находилась “корзина”, в которую нужно было помещать объекты drag&drop’ом, но выяснилось, что объекты нужно удалять постоянно — и драгэндроп уже недостаточно для этого быстр и удобен. Вышло так, что после определенного времени у нас выработалась определенная хватка устройства — айпад держался левой рукой так, чтобы большой палец аккурат приходился на виртуальную корзину, правая же рука управляла выделением объектов для последующего удаления. Это стало настолько естественно, что лишние объекты удалялись в считанные мгновения.
  • Двойной тап для перехода в режим выделения объект(ов), по отпусканию объект фиксировался и редактор переходил в режим перемещения, который прекращался либо повторным двойным тапом, либо переходом в режим перемещения по карте. Это позволило во-первых видеть объект, который мы перемещаем, не закрывая его пальцем, а во-вторых уменьшить вероятность случайного перемещения.

Пожалуй, на этом гениальные озарения заканчивается, и начинается обширный список того, что было, что называется, “learned in a hard way”. За деревьями не видно леса, проект никак не хотел заканчиваться, и мы попали в тот самый вечный цикл, знакомый по статье о Starcraft — игра все время была “за месяц до релиза”. А поскольку до релиза оставался “месяц”, тратить время на усовершенствование редактора не хотелось, что стоило десятков, сотен потерянных впустую часов.

What went wrong, very very wrong.

  • Undo. В редакторе и поныне нет Undo. Почти нет — возвращается одна операция перемещения — и все. Казалось не столь важным, а реализовывать вроде бы долго — заводить общий пул для каждой операции, динамически выделять мегабайты памяти для сохранения масштабных изменений… А первоначально отсутствие Undo компенсировалось недостатком номер 2, о котором ниже. В результате многие часы (в общем итоге) были потрачены на восстановление объектов, случайно зацепленных большим, неуклюжим пальцем. Или на удаление случайно сдублированного “мимо” десятка объектов. Внимание эта проблема к себе не привлекала, поскольку возникала не то чтобы совсем часто, но оглядывась назад, c сожалением признаю — отсутствие данной операции потратило многократно больше времени, чем заняла бы ее реализация.
  • Массовое выделение. Да, объекты нельзя было выделять больше чем по одному. Не казалось важным, казалось сложным для реализации — та же самая проблема что и в первом случае. Фактически, это привело к тому, что в игре до финальной стадии отсутствовал copy/paste, а значит — каждый из порядка 50,000 объектов в игре был поставлен вручную, в свою уникальную точку — кроме тех случаев, когда они скопировались в рядом стоящую ячейку с помощью тех самых команд дубликации. Профитом здесь является бОльшая уникальность уровней — поскольку нельзя было копировать целиком куски уровня, все создавалось каждый раз заново. Но как недостаток — явный перерасход времени, причем в разы.
  • Анимация объектов. Все параметры задавались с помощью слайдеров, хотя кое-какие “хелперы” все-таки были. В результате, если нужно было, чтобы по триггеру с определенного расстояния срабатывала анимация — и заканчивалась ровно там, где нужно, и ни пикселем дальше, уходило по 20-30 итераций на ручную подгонку параметров. В результате бОльшая часть уровней не может похвастаться хитрой или интересной анимацией, и уровни большей частью статичны.
    Логичным и простым решением сейчас кажется простое перемещение объекта в редакторе, с автоматическим вычислением нужной скорости, но на тот момент столь простой мысли в голову не пришло.
  • Точность. Самым, пожалуй, большим бичом была следующая проблема — недостаточная точность перемещения объектов — невозможно было переместить объект в нужную точку — из-за тачскрина и пальцев в качестве устройства ввода. Для “решения” этой проблемы было реализовано две вещи — сетка (snap to grid), и невозможность переместить объект на нечетный пиксель (то есть, фактически, сетка с величиной ячейки = 2).
    Это частично решало проблему, но к сожалению некоторые объекты были “неправильного” размера, и к сетке не стыковались, кроме того иногда можно было забыть заранее включить сетку, и целая куча объектов оказывалась мимо этой самой сетки — а в результате приходилось либо фиксировать позицию объектов к сетке “ручками”, либо “забить” на сетку и играть в веселую игру “попади пальцем в пиксель по обоим координатам всего лишь с 15го раза”.
    Правильное решение, на которое ушло больше года, оказалось простым фиксом из пяти строчек — который по нажатию определенной кнопки снижал скорость перемещения объектов в несколько раз.
  • Хоткеи. Выяснилось, что самые частые операции это:
    — поворот объекта
    — изменение ориентации (flip) по осям x и y
    — отключение коллизий
    — изменение zIndex (порядок отрисовки, который задавался вручную)Для них требовалось от одного до трех тапов. Необходимо было выделить объект, а потом вызвать панель редактирования параметров, которая частенько была закрыта, так как закрывала приличную часть экрана, и соответственно непосредственно переключить объект. Много времени уходило на это, а разместить эти операции в виде отдельных кнопок не получалось — они не влезали на экран, место со всех сторон кончилось, а делать второй ряд не хотелось — это бы уменьшило область видимости. Для решения этой проблемы было принято решение “прикрутить” внешнюю клавиатуру. Был куплен переходник для USB клавиатуры (в лучших традициях Штирлица называющийся Camera Connection Kit), и потрачено несколько бесцельных ночей в попытках заставить ее работать. Получилось с помощью “хака” — невидимой текстовой формы величиной в 1 пиксель. И тут оказалось, что работать одновременно с айпадом и внешней клавиатурой — неудобно. Нужна третья рука — одна держит устройство, другая манипулирует объектами, третья нажимает кнопки.
    “Фича” осталась невостребована.
  • Интерфейс в целом. Не казалось важным или необходимым, но интерфейс, не сильно мешая в целом, сильно проигрывал в потенциале и расширяемости. В данный момент я, начиная новый редактор с нуля, первым делом позаботился бы о следующих вещах:

1. Удобные выпадающие меню, для выбора команды по отпусканию.
2. Панели, вылезающие из-за экрана по “свайпу”, подобно тому как вызывается панель “Notifications” на iOS.
3. Циклическая прокрутка набора кнопок — чтобы можно было выбрать нужные тебе конкретно сейчас операции, и таким образом вместить больше команд “быстрого доступа“.
4. Multitouch для частых команд типа flip, rotate, scale, zoom. Попытка мною предпринималась в самом начале работы, но я ей уделил недостаточно времени — были получены неудовлетворительные результаты и работа отложена до лучших времен, которые никогда не настали — а зря.

In the end.

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

Источник