Почему и как я просрал LudumDare37

В этот раз были практически идеальные условия для участия в лудуме. Я отложил ВСЕ свои дела и взял отпуск на понедельник на работе. Даже вновь приобретённая жена согласилась кормить мой драгоценный организм пока я буду занят конкурсом. Этот пост и о том как я участвовал и о том, что нового даёт GameMakerStudio2, т.к. именно её я избрал для разработки.

Image result for Game Maker Studio 2

Стоить отметить, что я очень много спал. Работаю в ужесточённом режиме перед новым годом и сильно выматываюсь, так что два раза по 9 часов можно вычеркнуть.

Тема меня не порадовала. Во-первых, я не люблю темы от мобилкофагов которые стремятся ограничить управление, комнату, сюжет, игровой процесс напрямую — своими дурацкими «игра на одном экране», «две кнопки управления», «одна комната» и т.д. Во-вторых, подобная тема уже была, а меня, как человека привыкшему к эсплорэйшону одна комната ещё хуже одного экрана, честное слово! Вот маленький мир — хорошая тема. Тут и на один экран и на одну комнату и про микромир, что хочешь то и делаешь в своё удовольствие.

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

Я очень близко к сердцу принимаю все эти наезды по шаблону Кситилона, дескать у Хейзера все игры одинаковые — «Хуйня в темноте» и «Хейзеровский платформер». Поэтому вторым наброском должна была стать идея другого геймплея. Примерно неделю до начала лудума я лелелял идею объединить скроллшутер и стратегию. Что-то в духе скрошлутера с эсминцом, который умеет производить самолётики разных типов и игрок должен будет их переставлять, организуя боевую мощь перед очередной волной. Но опять же ебаная «one room» запорола и эту идею.

Так пришлось рожать идею по ходу дела. Одна из мыслей, за которую я ухватился связана с лифтом. «Лифт — это ведь тоже одна комната» — подумал я. В первоначальном виде Игрок должен был управляя лифтом перевозить людей с этажа на этаж не покоцавшись о препятствия в лифтовой шахте, которая по задумке значительно больше самого лифта. Игроку нужно было бы перепрыгивать с троса на трос самим лифтом. Но данная идея была лишена какой-то концептуальности. Делать игру на очки я не хочу.

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

elevator.jpg

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

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

Название и логотип игры я придумал сразу же.

logo.png

Итак, есть лифт, который перемещается по вертикальной шахте, аля вертикальные коридоры в первых двух частях metroid-а (+ Zero Mission). В шахте есть враги которых можно расстреливать. Но общая суть пока непонятна. Выбирая сеттинг, я вдохновился просмотренным накануне мультиком:

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

tree.png

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


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

Собака должна была гнаться за кошкой, которая стащила связку сарделек. В конце собака догоняет кошку, жрёт сарделки и падает сытая на седьмом небе от счастья. Это был вариант «на отъебись», т.к. основной целью участия я ставил не разработку игры как таковую, а попробовать Game Maker Studio 2.

Рисовать собаку я собрался ручкой. Затем сканировать и вставлять в игру. Графики по моим подсчётам должно было быть немного так что я за день должен был управиться. Но тут мне стукнула мысль нарисовать графон вручную для первой идеи с лифтом.


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

dogs.png

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

Здесь хочется подчеркнуть пару особенностей Game Maker Studio 2. Во-первых работа со слоями — это очень и очень удобно. Гораздо лучше чем работа с параметром depth. Легко было запутаться в глубине объектов и тайлов, да ещё и учитывать фоны. Теперь разработчик сам определят порядок слоёв и фон может встать даже в середине этот «торта», а не только внизу или вверху как было раньше. Кроме того слои есть разных типов и есть слой чисто для графики. Я ждал этого целую вечность. На этом слое можно располагать простые спрайты для антуража типа деревьев, травки, домиков. Если раньше нужно было создавать новый объект, назначать спрайт, задавать скорость анимации и т.д. То сейчас нужно создать спрайт, ему же задать скорость анимации и просто перетащить из дерева ресурсов на нужный слой в комнате. ВСЁ!!! Кстати, скорость анимации тоже наконец-то присвоили спрайту. Параметр image_speed остался и никуда не делся. Но он теперь только масштабирует скорость спрайтов. А скорость спрайта теперь указывается в самом спрайте и это — божественно! Анимацию спрайта можно смотреть не заходя в редактор спрайта и выставлять маску столкновения во время проигрывания анимации. Очень удобно.

Но не всё так гладко как хотелось бы. Решил прикрутить свою систему управления. Загрузил нужные скрипты. Запускаю — игра валится. Во-первых, упразднили используемый мной globalvar. То есть теперь нужно писать по-старинке global.<имя>. Сделано это было то ли чтобы народ не путался. То ли чтобы было легче обрабатывать автокомплитом. Если первое — это вопрос организации имён. Я лично привык глобальные переменные писать в верхнем регистре, локальные — понятными словами, а переменные контекста короткими именами. Что касается автокомплита — это просто песня. Теперь там вываливаются все переменные: локальные, глобальные, контекстные, перечисления(enum), макросы. Кстати, теперь макросы объявляются прямо в коде через #macro <название_макроса> = <значение>. Но у меня не сработало, увы. Как и с глобальными переменными. Я там активно использую структуру данных типа «словарь». Видимо, эти структуры тоже глючат, ибо дальше чем в локальном контексте они не видны.

Ещё пара приятных моментов насчёт создания/уничтожения экземпляров из кода.
Функцию instance_create упразднили введя две другие: instance_create_depth(x,y,depth,obj) и instance_create_layer(x,y,layer,obj). На самом деле ничего страшного не случилось. Есть встроенная переменная layer позволяющая создавать объект на своём же слое. Можно указать имя слоя строкой. Это довольно удобная технология и не вызывает дискомфорта как я думал поначалу.

А вот функцию instance_destroy() доработали. Теперь можно указать в качестве параметра id объекта. Вместо конструкции with id instance_destroy() пишем теперь instance_destroy(id). Но и первый вариант так же остался рабочим. Плюс есть второй необязательный параметр указывающий выполнять ли события уничтожения для объекта. Тоже бывает полезно. Я на практике часто жалел что такой возможности нет.

Вот чего я не догнал так это камер. Зачем то виды разделили на виды и камеры. Вид — это то что отвечает за размеры выводимого изображения типа view_port. Камера — то что уже в самой игре и размеры вида в самой игре, она связана с видом. Далее изображение камеры масштабируется под размеры view_port-а. Не понял я смысла такого пассажа, но могу сказать точно что теперь вместо view_wview[0] нужно писать camera_get_view_width(view_camera[0]).


Почти весь понедельник я так же рисовал. Я нарисовал очень много графики, в том числе и анимированной.

images.jpg

А затем я всё это программировал. Так появилось пять видов оружия:

Плазма — просто стреляет по прямой не очень мощными патронами.

plasma.png

Пулемёт — очень быстро вразброс стреляет медленно летящими снарядами. Для тех кто не любит целиться.

autogun.png

Лазер — просто мощная хрень, которая бьёт по прямой.

laser.png

Бомбы — поставил и убежал. Взрыв должен повреждать игрока, но в прототипе ниже это не реализовано.

bomb.png

Вертушка — для ближнего боя. Дико мощная вещь, но не всегда применима.

blaze.png

Потом добавлю ещё и ракеты скорее всего.

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

weapon.png

Далее были придуманы и запрограммированы враги:

Мои любимые медузы атакующие электричеством в ближнем бою

medusa.png

Простые пушки

[КАРТИНКА ВРЕМЕННО ОТСУТСТВУЕТ]

Самонаводные камикадзеры

[КАРТИНКА ВРЕМЕННО ОТСУТСТВУЕТ]

Взрывающийся шипами цветок

spiker.png

Грибочек выпускающий газ

shrom.png

Копьё, которе летит по прямой генерируя электрический барьер (разрушаемый)

wiper.png

Подпрыгивающий шип

trapper.png

Шипованный блок

spikeblock.png

Каждый из врагов использует в качестве элемента кошачий глаз. Это специально сделано — для придания всем врагам единого стиля.

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

Здесь я расскажу про работу с тайлами в Game Maker Studio 2. Дело в том, что тайлы теперь — не расчерченный фон, а абстрактный ресурс, использующий спрайт (кстати остались только спрайты, фоны упразднили как вид ресурса). Загружается спрайт и затем расчленяется на тайлы. Причём! Можно задавать анимированные тайлы. То есть составлять анимации из самих тайлов вручную назначая кадры. И можно делать авторасстановку. Ну знаете такую штуку как край стены, который приходится особенно в платформерах выставлять вручную. А тут взял — пометил какой тайл чему соответствует и поехал. Я часа полтора потратил на то чтобы нарисовать такой тайлсет из 47 тайлов. Зато потом наступает блаженство. Самое интересное что с одного тайлсета можно сделать разные паттерны расстановки тайлов. Там же можно сздавать «кисти» из тайлов — набрасывать элемент-заготовку и прямо ими рисовать. Например, домик. Это очень удобно, т.к. такие заготовки легко модифицируются на лету, можно создавать библиотеку заготовок. В общем, работа с тайлами теперь на самом высоком уровне.

Где-то в 12 ночи я умудрился всё запрограммировать. Очень в этом помог новый интерфейс Game Maker Studio 2. Есть общее рабочее пространство workspace на котором красиво аккуратно располагаются все окошечки не перекрывая друг друга. Нажимая на ресурс он либо открывается на пустом месте либо на нём фокусируется камера передвигающаяся по этому рабочему пространству. На каждый объект выделяется 4 окошка:
1) Основное окно с инфой что за спрайт использует объект, видимый, постоянный и т.д.
2) «Семейное положение объект» — кто родитель, кто дети.
3) Список событий
4) Редактор кода или драг-н-дроп.

И здесь замечательно несколько вещей. Во-первых, действует драг-н-дроп на спрайты и родительские отношения. Во-вторых, у родителей теперь можно указывать не только родительский объект, но и указывать потомков! Это очень удобно. В-третьих, если тип проекта был выбран как КОД, а не Драг-н-Дроп то при редактировании события не нужно ебать мозг выбором кнопки «кусок кода» — сразу открывается редактор кода и всё. И в-четвёртых, окошко редактирования кода общее на все события одного объекта. Код для каждого события открывается в новой вкладке этого окошка.

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

Следующие 4 часа я вёл отладку игрового процесса. Смирившись с получаемым качеством я записал все звуки. Было 5 утра. Я ещё успевал создать саму игру. Все части были готовы и оставалось расставить все компоненты по местам. Но тут начался пиздец. После того как я вставил звуки игра начала падать. Прямо таки APPCRASH виндовый хуй знает почему. Я уже попробовал и вычислить ресурс который всё ломает — один хуй. Даже пустая комната падает. Было 6 утра. Я плюнул и лёг спать.


Что я вынес из этого всего?

1) Хочешь сделать проект — делай на проверенных инструментах, а не бетта-движках.

2) Рисованая графика вполне ничего. Именно такая, чёрно-белая. Рисуешь, сканишь, выравниваешь уровни, удаляешь белый фон и расчленяешь на кадры.

3) Запись звуков тоже хорошая идея. Причём как оказалось они в целом неплохо вписываются даже в рисованую игру. По крайней мере приглушённые взрывы так записывать идеально.

4) Game Maker Studio 2 даёт довольно много новых интересных возможностей которые реально ускоряют разработку: классно организованное рабочее пространство, хороший автокомплит, хороший интерфейс управления спрайтами и тайлами, хороший редактор комнат, слои для разных типов ресурсов

5) Есть и недостатки: убранный globalvar, общая сырость (не работают словари, рантайм падает), непонятное введение камер и видов, нет настроек для звука по умолчанию. Так же немного раздражет смена масштаба. Если уменьшить комнату и вызвать менюшку для объекта то она будет в таком же масштабе как и всё остальное.

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


Уже на следующий день после завершения конкурса я разобрался в чём было дело, почему проект падал. И набросал постджемовский прототип с одной боковой пещерой.

Управление:

Стрелки — двигаться
Z,X — стрелять влево/вправо (стрелять можно только находясь рядом с генератором поля оружия)С — действие (для стыковки с гнездом для управления лифтом)

Лифт едет автоматически вверх или вниз при помощи двух верхних гнёзд.
Передвинуть генератор поля оружия можно двумя нижними гнёздами.

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

Умереть пока нельзя хотя жизни показываются при повреждении на дроне которым управляет игрок.

Возможны застревания в стенах и неадекватная реакция врагов.