D:\sideБлогGeekParty №6: Slimes! Дневник разработки

⚠️ Обращайте внимание на даты.
Этот блог больше не ведётся с 17 января 2023, и на тот момент с написания этой страницы (25.01.2014) прошло 8 лет.

GeekParty. Не новое для меня мероприятие, но на сей раз куда более интересное. На нём я работал “в своей среде”, в GameMaker Studio, и потому был готов почти ко всему, что можно осилить за гейм-джем. Что же, я даже не переоценил свои силы на этот раз. Тема этого GP ­- файтинги. Такие игры, где есть два персонажа и они друг друга мутузят, пока кто-то из них не склеит ласты или не упадёт без сознания. И прочие подобные вариации.

Скажу честно – тема мне не понравилась. Я помнил свой прошлый опыт на GP4, где был куда более простой жанр: визуальные новеллы. Где необязательно было выделяться механикой и иметь красивую анимацию. И там я просидел до самого конца, закончив буквально минут за 10 до дедлайна, после чего бежал со всех ног к мосту, который должны были развести, изолируя меня от острова, на котором я живу. Мероприятие мне, тем не менее, понравилось, хоть и оставило своеобразный след из опыта. Когда я узнал тему нынешнего GeekParty, я сразу усомнился в том, хочу ли туда идти. Думал долго. В конце концов, мне позвонили и предложили в этот день сходить и проведать друга, которого забрали в армию против медицинских показаний и из-за них поместили в госпиталь. Я согласился, конечно, не идти к нему у меня причин не было.

Но всё сорвалось. Я пришёл на место встречи с другими сочувствующими и узнал, что в связи с некими праздниками (Татьянин день, или день снятия блокады, я так и не узнал) в госпиталь не пускают посетителей. Ну что же, ладно! Решил провести этот день с пользой, упаковал ноутбук и поехал на GeekParty, ещё толком не зная, что я там буду делать.

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

Итак, старт дан. И я понимаю, что я ничего не понимаю. Кхм, точнее, что у меня нет идей о том, что делать. Я не очень социальный тип, и снова работал один, без жалоб и сожалений об этом. С чего начинается любая работа над игрой? С идеи? Идей не было, пришлось этот шаг отложить и перейти сразу к рисованию черновых спрайтов. Я открыл Inkscape и нарисовал круг. На минуту задумался, переключился в редактирование контуров и сплющил нижнюю половину круга, получив объект формы, подозрительно напоминающей слизней из Terraria. А эти слизни там – самый страшный кошмар и самое лютое веселье любого новенького игрока. Я помнил, как они воевали, и решил это реализовать.

Базовая идея была проста и представляла собой боевую систему Mario, силой упиханную в файтинг. Противники пытаются прыгать друг на друга, пытаясь задавить весом. Тут меня заинтересовала физическая сторона вопроса. А как эти слизни вообще прыгают?

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

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

  1. Она позволяла совершать простейшие действия с разной силой, разной степени выраженности.
  2. Она совмещала возможность удара с возможностью уклонения (блокирование не рассматривалось, но появилось).
  3. Она была очень проста, и её интуитивность под сомнение не ставилась (а зря).

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

На тот момент у меня была стрелочка, указывающая из центра слизня на точку, куда центр тяжести был смещён. Ради смеха, я попробовал заменить кончик стрелочки, как впрочем и саму стрелочку, на что-нибудь. Скажем, бело-прозрачный градиентный круг. Получилась сияющая сфера где-то на слизне, что, честно, не смотрелось. Не было понятно, что это и зачем. Тогда я поступил наоборот и повесил поверх слизня “затемняющий” круг (bm_subtract, смешивание вычитанием), что дало ощущение, что та часть слизня, где центр тяжести, ощутимо плотнее остальной его ткани. Интуитивно. Годится. Оставил и жил с этим почти до самого релиза. Почти.

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

  1. Dash, рывок в сторону. Основной способ передвижения, так слизень ползает по ровной поверхности. Оттягиваем центр в сторону (право/лево), дёргаем в другую сторону, летим куда хотим. В основном предназначен для уклонения и смены позиции для последующих манёвров, поскольку может применяться одновременно с ними.
  2. Leap, прыжок или скачок. Тут понятно, оттягиваем центр вниз, запускаем вверх, по инерции летим за ним.
  3. Drop, и тут у меня с переводом возникли трудности. Лучшее, что я придумал – “давилка”. Это в основном боевой приём, призванный сделать ещё более опасным падение на противника сверху. Как? Упасть на противника сверху на большой скорости. Потому что урон зависит от скорости, о чём я сейчас и расскажу.

Как я предполагал осуществлять бой, которого тогда не было? Очень просто. При столкновении слизней определить их скорости, и тот кто движется в этот момент быстрее, и наносит урон, равный по величине разности скоростей (скалярной разности, модулей векторов скоростей: это скорее ошибка, но хуже она игру не сделала). Такая боевая система отличалась одной забавной деталью: чтобы заблокировать идущий на тебя удар, необходимо направить удар навстречу. Скажем, если на вашего слизня падают, прыгнуть в противника. По меньшей мере, это погасит часть урона, а в лучшем случае может даже повредить противника. Но это были только планы. Хотя проблем с ними не возникло.

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

Дальше на очереди была боевая система. И я не сразу придумал, каким образом реагировать на столкновение двух слизней. По идее, они должны были отскакивать друг от друга, как резиновые мячи, но это создавало некоторую неоднозначность в физике, которую я писал руками. Была возможность подвесить противника в воздухе или зажать у края сцены, и он не особенно бы мог с этим что-то сделать. Не годится. Определение столкновений у меня, спасибо GMS, уже было, и я решил реагировать на его обнаружение… никак. То есть, если столкновение “сейчас есть, а раньше не было”, то считать, что был удар. Система получилась достаточно простой и делала всё то, что от неё требовалось, не сбивая с толку игрока. Отлично! Продолжаем в том же духе.

Реализация нанесения урона сюрпризов и неожиданных багов не принесла. Она работала именно так, как задумывалось. Но потом я начал придумывать, как отображать здоровье слизней. Хелсбары отображать мне не очень хотелось (банально и не вписывается в картинку), поэтому я попробовал обойтись слизнями же. Я снижал им яркость цвета смешивания по мере того, как они теряли здоровье. Так, перед смертью они становятся почти чёрными. И тут я воткнулся… в HTML5. Который не умеет нормально смешивать цвета и скорчил мне интересный баг: при получении урона слизень внезапно меняет цвет на какой-то совершенно другой. Был синим – стал жёлтым, потом зелёным, потом умер. Пришлось заменить смешивание на дополнительную чёрную маску с меняющейся прозрачностью. Чем прозрачность маски меньше, тем темнее на вид слизень. Это в HTML5 успешно работало, потому что с прозрачностью там как раз проблем нет.

Итак. На тот момент у меня было удобное управление, работающая боевая система, один баг (ерундовый, который я потом поправил), анимированные слизни и полное отсутствие фона. Фон Алексей предложил найти в Google, выбирали его на пару. Случайно выбранный оказался SVG’шкой (родной формат Inkscape, в котором я рисовал всю графику), и был объявлен достоянием общественности, т. е. авторским правом не защищён. Невероятное везение, хотя надо отметить, что фон довольно простой. Затратив на него полчасика, я мог бы нарисовать нечто подобное и самостоятельно, но заниматься этим просто не хотел. Я потратил примерно минут 5 на его приведение в масштаб слизней (сильно увеличил дерево, чтобы слизни не казались гигантами) и водрузил в игру. Смотрелось весьма прилично и дожило до самого релиза.

Дальше пошли украшательства, просто полезные для игры. Сначала появилось подобие уплывающего логотипа, куда же потом добавилось и управление, и моя подпись, и основная цель игры. Затем, опять же по предложению Алексея, я нарисовал для слизней глаз, который отклоняется в сторону, противоположную центру тяжести. У этого вышел неожиданный эффект: в бою слизни частенько поглядывают на противника своим единственным глазом. Эта же черта сделала их внешний вид более “живым” и в какой-то мере “милым”. Ёрзающий во все стороны глаз хорошо передавал панику слизня, бьющегося насмерть. Затем, тоже по предложению Алексея, я сделал индикацию того слизня, на которого пришёлся удар. Классическим способом, который я знал, но почему-то не вспомнил: подсветить на долю секунды на манер фотовспышки. Это однозначно определяло для сторонних наблюдателей, кто кого стукнул. Для игроков это было немножко более очевидно, потому что они непосредственно управляли слизнями и представляли скорости. Но даже если нет – ударенный слизень немножко темнел в соответствии с эффектом, описанным выше.

Визуальная модель слизня получилась не такой уж простой. 5 частей. Сначала сам слизень, затем затемняющая маска (здоровье), затем ядро (центр тяжести), потом “фотовспышка” (рисуется всё время, но видна только в момент удара, быстро становится прозрачной) и поверх всего глазик.

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

Итак. Что получилось? Приблизительно за 4 часа я собрал основную играбельную часть, а оставшиеся два с лишним часа (и перерыв на бутерброды) полировал игру вещами, которые в ней обязаны быть. Собирал звуки при помощи Bfxr (швейцарский нож из области аудио для геймджемов), пробовал другие вариации спрайтов, рисовал глаза (О_О), подсказки. В релиз моя игра ушла первой из всех на мероприятии, что приятно и здорово отличается от прошлой GP (№4, июнь 2013), на которой я свою игру релизил последним. И по ходу дела перекидывался весёлыми фразами о происходящем с сидящим/лежащим (диван, удобно) за тем же столом Ромой Роговым. Кстати, вот его работа. Стоит увидеть.

Так, ладно, теперь порция ссылок.