Сделал сайд-скроллер уровень "Оседлай турбину". Турбина старая, пыхтит с трудом. Такого типа уровней запланировал где-то 10-15%%. Сделаю еще три уровня и начну собирать демку игры - попытаюсь найти издателя.
Действие турбины похоже по механике на Flappy Bird, однако придется пару раз приземлиться на платформы, чтобы пройти. Как вам?
Не так давно (год назад на самом деле) я приобрёл необычную игровую консоль Playdate.
Вот он наш герой поста
Она такая маленькая, жёлтая и имеет крутилку (крэнк или иногда в дословном переводе с испанского кривошип). Ах да, у неё еще экран монохромный. Не чёрно-белый - чёрно-белый экран умеет показывать оттенки серого
Оттенки серого, но не те
- монохромный умеет показывать только чёрное и белое. Точнее, не совсем белое, а что-то что не чёрное.
Пример меню с выбранным пунктом "Настройки". Как видишь, белый не совсем белый
Playdate это неповторимая смесь примитивизма и современных технологий. На первый взгляд можно подумать «ну и кто в такое играет?». Однако я щас без преувеличений скажу, что уже для Playdate сделано более 800 игр. То есть, в отличие от миллиона неизвестных консолей, которые сегодня создаются для тех, кто вспоминает детство за сегой и дэнди, пардон, нинтендой, у Playdate реально есть активное сообщество.
Какую игру я хотел сделать? Примитивные головоломки я отбросил сразу же. Хотелось сделать что-то драйвовое, чтобы прям был экшон как в GTA - машины там, физика, стрельба. Значит, нам нужна машина! Понятное дело, игра будет двухмерная. Если машина, значит, она должна ездить, и желательно не с идиотским видом сверху как в GTA2 (справедливости ради уточню, что я прошёл всю GTA2, и посмотреть это можно на ютубчике), а чтобы была перспектива, чтобы было красиво. Так как никакого 3D не ожидается, а для управления у нас есть крестовина (D-Pad на английском). Значит, нам нужна машинка в восьми направлениях. Дав задачу своей художнице я получил вот такое:
Машина, на которой игрок будет кататься в игруле
"Так, стоп, а какой сеттинг у игрули?" спросишь ты. Сеттинг простой - мы катаемся на внедорожнике вооружённым пулемётом по пустыни в Австралии и, как настоящие любители дикой природы, отстреливаем живность: эму и кенгуру. Справедливости ради уточню, что живность нас тоже пытается грохнуть. То есть, жанр игры "выживальщик" наподобие Vampire Survivors.
Так как у Playdate только два цвета, нам нужно постараться чтобы создать ощущение нахожения в пустыне. Потому сначала сконцентрируемся на реквизите, который нас будет окружать. Конечно же это кактусы, небольшие песчаные насыпи и перекати-поле.
Ах-да, забыл упомянуть: размер экрана у нас 400 на 240 пикселей. То есть, ну очень маленький. Значит, объектов на экране должно быть минимум чтобы понять что происходит.
Перейдём к самому вкусному - к коду.
На Playdate официально можно разрабатывать на двух языках программирования: C и Lua. Так как Lua я не переношу как и все скриптовые языки (я лично за С++ во всех нормальных играх), значит будет сишка. Не сказать, что я фанат сишки, но это лучше луы. А что делать с отсутствием объектно ориентированного программирования? Будем симулировать и выкручиваться по возможности, потому что 10 лет работы на ООП языках (Swift, C++, C#) чётко отформатировали мою голову под объектно-ориентированное мышление.
Первый шаг в написании игры это файл main.c, в котором нет функции int main, зато есть системный колбэк ("обратный вызов" или "звони назад")
int eventHandler(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg).
Эта функция это единственная прослойка между Playdate и моим кодом. Она вызывается на любой "чих", точнее, событие. Первый аргумент PlaydateAPI* playdate это указатель на непосредственно API операционной системы девайса. PlaydateAPI это структура, которая состоит из структур, которые хранят сишные указатели на большое количество функций (нарисовать, что-то, открыть файл, показать fps и т.д.). Второй аргумент это наш тип "чиха", точнее, события:
Объявление перечисления PDSystemEvent
На третий аргумент arg пока пофиг - он нам не нужен.
Код игры можно воткнуть прям в файл main.c, но я так не хочу. Не потому что это считается зашкварно - то что как считается это вещи очень субъективные, и вряд ли они когда-то меня останавливали от самых сумасшедших вещей в коде. Я вынесу код отдельно потому что я хочу чтобы он был распределён красиво и удобно, модульно, но не слишком. То есть, чтобы лично мне было понятно где что искать, но чтобы не упарываться в оформление структуры ради оформления структуры как это делают Java-разработчики. Потому вся логика катания машины по пустыне будет аккуратно сложена в файл с супербанальным названием Game.
Game будет имитировать класс, он будет создан при получении события о старте игры, и будет удаляться в событии об окончании игры. А указатель на этот объект будет храниться где? Правильно: в статичной памяти.
Окончательный вариант файла main.c
То есть, игра создаётся в событии `Init` (строка 21), потом вызывается у игры функция GameSetup (строка 22) для единоразовых стартовых действий опосля создания (тут можно поспорить, что эти вещи можно сделать в той же функции GameCreate, но спор оставим тем, кто любит спорить вместо написания кода). Далее я прикручиваю вызов функции GameUpdate к тику игры. Напрямую я это сделать не могу так как функция обновления имеет сигнатуру int (*)(void *), а мне нужно int (*)(Game *), потому я создаю функцию-прослойку rawUpdate, которая принимает void *userData, кастит его в указатель на Game и руками вызывает GameUpdate.
Отлично, с мэйном всё понятно. Теперь давай глянем что есть в самом Game. Но сначала позволь проспойлерить и показать что получилось чтобы ты не зевал от кода.
Откатимся назад в прошлое. Сишка кажется нормальным языком, но ровно до того момента, когда тебе нужно работать с динамическими объектами: строками и массивами. Оказывается, что чтобы передать массив в функцию нужно иметь два аргумента: указатель на данные и целое число равное количеству объектов, лежащих по тому самому указателю один за другим в памяти как поезд. Ну либо можно хранить объекты в статичной памяти, там всё проще - объявил статичный массив и пользуйся. Одно но - у статичного массива константный размер, и этот размер должен быть известен в момент компиляции. Чем это чревато? Тем, что если ты объявил массив, скажем, кактусов, размером, скажем, 100 штук, это значит, что в игре 101 и более кактус быть уже не может. И так с любым статичным массивом.
Забавный факт: когда несколько лет назад слили исходники GTA3 и GTA Vice City там динамические объекты (машины, пешеходы, пикапы (броня, спрятанные пакеты, буйства, оружия, деньги)) как раз хранились в статичных массивах. И количество пикапов, например, ограничивалось числом 512. То есть, если в игре устроить заварушку чтобы вокруг валялось много денег, оружия и прочих пикапов в количестве 512, то при появлении нового один старый пикап тут же будет пропадать даже если ему ещё рано пропадать (деньги и выпавшее из врагов оружие пропадают по таймауту).
Вот я так не хочу. А хочу я чтобы у меня был один объект массива без отдельно указателя на данные и отдельно размера, потому что если таскать везде два аргумента представляя что это один, это верный способ свихнуться. А если мне нужно два массива - будет два объекта. А все детали (указатель на данные, размер, прочее) должны быть аккуратно спрятаны внутри, как это сделано в ООП языках. В С++ для таких целей есть std::vector, в Swift - Array, в C# - List. В сишке ничего такого нет, значит надо придумать!
Долго томить не буду, вот что получилось:
Заголовочный файл массива
Заголовочный файл имеет предобъявление структуры Array, которой по факту не существует, и API для создания, взаимодействия и уничтожения массива. Важная деталь: так как это сишка у нас нет деструкторов как в С++/C# или deinit-функций как в Свифте, которые автоматически вызываются когда область видимости массива заканчивается. Значит, нам надо вызывать функцию-деструктор руками. То есть, на каждый вызов ArrayCreate где-то должен быть один вызов ArrayDestroy. А что будет если забыть вызвать ArrayDestroy? Правильно: утечка памяти. Я чувствую себя программистом-дауншифтером. Но я сам так решил: начал танцевать с дьяволом - жди окончание песни.
Теперь давай я покажу тебе реализацию:
Файл Array.c
Тут у нас есть структура ArrayImpl. И мы в функции ArrayCreate создаём именно инстанс структуры ArrayImpl, а не Array (та самая несуществующая структура), однако указатель на созданные данные нагло кастим в указатель на Array. Зачем так делать? Честно скажу, я это подглядел у команды SQLite в исходном коде SQLite. Таким образом мы разделяем интерфейс и прячем реализацию, то есть, делаем её приватной в языке программирования, где приватности нет (я про слово private говорю, которое есть чуть ли не в каждом известном мной объектно-ориентированном языке программирование, за исключением Свифта самой первой версии - там уровни доступа не сразу завезли). Логика в том, что весь API массива принимает указатель на Array, а внутри этот указатель кастуется в указатель на ArrayImpl, который хранит реальные данные нашего массива.
А, кстати, что же хранит ArrayImpl? На последнем скриншоте мы видим, что там не два поля как это бывает у сишного массива, а больше:
1) int itemSize - это размер одного хранимого объекта в байтах. Этот размер нужен чтобы знать сколько байт выделять когда мы пытаемся засунуть в массив один объект (push_back в векторе на C++, append в Свифте у массива и Add в C# у листа). Ты возразишь "но ведь С++ вектор не хранит это поле, значит можно в нашем случае тоже как-то его избежать!". Однако, С++ на самом деле хранит это поле, просто не в виде явного члена класса, а в качестве параметра шаблона: std::vector<T> имеет параметр шаблона T, от которого в любой функции внутри класса std::vector можно вызвать sizeof(T) и получить заветный размер одного объекта. Однако в сишке шаблонов нет. Вот прям совсем нет. Примерно как нет воздуха на Луне. Потому приходится передавать один дополнительный параметр int itemSize, который позволит нам во время жизни массива знать размер одного элемента. Нет, конечно в сишке есть макросы, которые при достаточной сноровке можно использовать как шаблоны, однако я имею аллергию на макросы, так что макросов не будет.
2) Указатель на функцию realloc. Это может выглядеть избыточно, и по факту так оно и есть, однако у PlaydateAPI (помнишь, я тебе в файле main.c показывал указатель на такую структуру?) есть свой указатель на функцию realloc, который, как мне подсказывает мой копчик, равен системному вызову realloc из стандартной библиотеки Си, и который можно вызвать вот так playdateApi->system->realloc. То есть, нам разработчики намекают использовать их realloc вместо системного. Что ж, это нетрудно. А вторая причина - передача функции realloc по указателю позволяет покрыть вызовы этой функции юнит-тестами, то есть, сделать мок или прокси этой функции, и это невероятно удобно. Правда, я до сих пор не покрыл массив юнит-тестами, но когда-нибудь я обязательно это сделаю, честно-честно!
3) void *data это непосредственно указатель на данные. Почему именно указатель на void? Потому что массив по своей природе универсален: он способен хранить и int'ы, и кастомные структуры, а значит нужен указатель какого-то общего типа, что-то вроде object в C# или AnyObject в Свифте. И тут сишка нам щедро предлагает указатель в пустоту. Любой сишный прогер знает, что указатель на void это произвольные данные. В нашем случае это данные массива. Массив может хранить N объектов, а значит в этом состоянии у него указатель data будет указывать на кусок памяти в минимум N * itemSize байт идущих подряд если только N не равен 0. А если массив пустой, то data равен NULL.
4) int capacity это ёмкость данных. Ёмкость равняется количеству объектов, которые умещаются в объём выделенных данных, которые лежат по адресу data.
5) int size это количество реальных объектов, которые лежат по адресу data. "В чём отличие size от capacity?" спросишь ты. Тут логика та же, что и у std::vector в C++ - capacity в некоторых случаях может отличаться от size. Например, если в массиве было 4 объекта, и мы один объект удалили чтобы осталось 3, мы не будет выделять новый участок памяти под 3 элемента, а старый освобождать. Мы просто уменьшим size, но оставим capacity как есть. Это, во-первых, быстрее, чем перераспределять память (особенно если в массиве лежит больше тысячи объектов), во-вторых, если после удаления мы решим снова добавить объект, то память вновь не придётся перераспределять, так как ёмкости массива хватит. Да. безусловно если помимо этого одного мы добавим ещё один, то придётся осуществить перераспределение чтобы выделить больший кусок памяти, но тут мы уже ничего сделать не сможем, кроме как заранее оптимизировать пытаясь предсказать какая ёмкость лучше. Но это уже не ответственность массива - это ответственность того, кто этим массивом пользуется.
Итого я расписал как устроена внутрянка массива. Не будем забывать мою цель - мне нужен аналог std::vector из С++ или Array из Свифта удобный настолько, насколько это возможно в сишке. Так что давай я покажу как устроен API у массива.
1) ArrayCreate (на прошлом скриншоте есть) - эта функция создаёт объект массива. Она принимает itemSize и указатель на функцию realloc. Задача функции - выделить память под ArrayImpl, присвоить все стартовые поля ему и вернуть созданный указатель, но в качестве Array*, а не ArrayImpl*. Количество объектов у только что созданного массива всегда равно нулю. Возможности создавать массив из литерала как в С++ (auto myArray = {1, 2, 3}), C# (var myArray = new int[]{ 1, 2, 3 }), Swift (let myArray = [1, 2, 3]) и даже Objective-C (NSArray *myArray = @[@1, @2, @3]) нет, так как это просто синтаксический сахар над несколькими операциями (создание и заполнение), и негоже такое в сишке иметь.
2) ArrayClear - функция очистки массива.
Исходный код функции ArrayClear
Это не уничтожения массива, а именно опустошение хранилища если количество хранящихся объектов в массиве больше нуля. Название я полностью взял с std::vector::clear из С++. Можно было взять removeAll из Свифта, но к clear я больше привык. Суть функции: мы берём полученный аргумент и кастуем его в указатель на ArrayImpl. Если data у полученного объекта не равна нулю, т.е. если массив непустой, то мы дропаем дату и запоминаем, что capacity и size равны нулю. Ну а если массив и так пустой, то мы не производим никаких операций с памятью.
3) ArrayGetSize - самая простая функция, которая возвращает размер массива.
Исходный код функции ArrayGetSize
Просто кастуем указатель и возвращаем хранящееся значение size.
4) ArrayGetObjectAt - получение объекта. В "нормальных" языках у нас есть оператор "квадратные скобки", а тут у нас сишка, так что любое действие это просто функция.
Исходный код функции ArrayGetObjectAt
Функция возвращает адрес, то есть, указатель на нужный объект по указанному индексу в массиве. Так как храниться может внутри что угодно, то возвращаем мы уже известный нам указатель на void. А задача клиента будет уже скастовать этот указатель в указатель правильного типа: если в массиве лежат int'ы, то надо будет скастовать в int, если float - то во float, если кастомная структура или union - ну ты понел. И тут, понятное дело, можно легко спутать тип потому что мы люди, а люди ошибаются. Как страхуются от таких проблем в других языках? В С++ всё так же шаблонами: если std::vector<T> имеет T равный int, то и operator[] будет возвращать T и только T. В Свифте то же самое, только там не шаблоны, а дженерики - шаблоны на минималках, в C# тоже дженерики. А в сишке мы дауншифтим, смирись с этим и не выпендривайся! Ах да, если индекс переданный в функцию оказался за пределами доступных объектов (меньше нуля или больше либо равен размеру массива), то мы просто вернём нулевой указатель. В троице моих упомянутых выше языков в этом случае бросается исключение, но в сишке исключений нет, да и как по мне без исключений код приятнее, потому что исключения это тот же оператор goto, от которого нас так яростно отучивали 20 лет назад. Потому мы возвращаем NULL. А если индекс валиден, то мы хитрой арифметикой указателей вычисляем правильный адрес и возвращаем его.
5) ArrayGetMutableObjectAt - это копия прошлой функции, но возвращающая неконстантный указатель на объект. Почему это важно выделить в отдельную функцию?
Исходный код функции ArrayGetMutableObjectAt
Язык у нас, конечно, не самого высокого уровня, однако константность в нём есть полноценная, а константность это штука, которая невероятно повышает читаемость кода (я особенно привык объявлять константы вместо переменных во время работы на Свифте, а потом когда в плюсовом проекте везде втыкаю const иногда встречаю возмущенные ревью "ну и нахуа ты везде свой бесполезный const понапихал 🗿"), однако константы почему-то максимально игнорируются программистами на сишке, что я лично не одобряю никак.
6) ArrayPushBack - добавление объекта в массив. Аналог std::vector::push_back из C++, Array.append из Свифта и List.Add их C#.
Исходный код функции ArrayPushBack
Это самая навороченная по логике функция массива. Объект передаёт константным указателем на void. Тут нам сначала нужно проверить умещается ли новый объект в уже имеющуюся ёмкость (capacity). Если умещается, то мы просто копируем его в data со сдвигом равным старому размеру помноженному на размер объекта (itemSize), а количество байт для копирования тоже равны размеру объекта (itemSize). Важно при вызове ArrayPushBack передавать адрес объекта, а не сам объект, а то будет ошибка: ArrayPushBack(myArray, &myValue). Неудобно, согласен, зато универсально, потому что в таком массиве можно хранить и структуры, и базовые типы.
7) ArrayDestroy - последняя на сегодня функция массива. Эта функция, как ты уже знаешь, уничтожает массив, то есть чистит его из памяти. Любой массив рано или поздно окажется тут, где закончится его путешествие по этому бренной жизни, точнее, по материнской плате. Эта функция это Вальгалла всех массивов. В неё мечтает попасть каждый массив, а те, кто не попадают, те остаются болтаться в утекшей памяти.
Исходный код функции ArrayDestroy
Тело функции крайне банально: сначала вызываем ArrayClear чтобы почистить объекты если они есть, а далее дропаем массив из памяти словно он никогда и не существовал.
Заключение
Признаюсь, стилистику имитации объектов я взял в CoreFoundation - это такая сишная либа от Эпла, которая имеет API очень похожий на Objective-C, на основе которого позже появился Swift. Это, кстати, не единственный способ имитации ООП в сишке - ещё я пользовался либой GTK+, но там API немного отличается, в частности, там всё обмазано макросами, а на них у меня аллергия.
Разработка Gone Rogue, игры про вора в мире-антиутопии, близится к завершению. Значит пришла пора поделиться с вами историей ее создания.
Я решил разделить статью на три главы – по главе на каждый год разработки. Причем, каждая глава затрагивает свою обособленную тему: выбор жанра игры, поиск команды, размышления о геймплее. Надеюсь, что вышло достаточно разнообразно и интересно.
Глава 1. Ошибка планирования.
Для справки, мой багаж знаний на начало разработки: десяток недоделанных игр на Delphi и бейсике (как сейчас бы сказали «прототипов»), которые я периодически пытался делать еще со школьных времен. Несколько месяцев обучения Unity, почти год обучения моделированию в Blender.
В феврале 2020 года мой кризис нереализованного потенциала («А часики-то тикают») достиг своей цели – я решился на осуществление мечты всей моей жизни – создание собственной игры. Так как вопрос финансового успеха не был так важен, то жанр и сеттинг будущей игры зависел полностью от моих желаний и возможностей.
Жанр игры я выбирал примерно таким образом. Игра обязательно должна быть в 3D (не зря же я целый год учился 3D-моделлированию). Хоррор – моветон. Стратегию делать слишком долго (а об использовании сторонних ассетов я тогда даже не задумывался – ведь игра должна быть полностью своя!). Игры от первого лица предъявляют большие требования к качеству моделей и текстур, да и жанр лично мне не очень-то интересен. RPG – наоборот, интересный жанр, но опять-же, это история на несколько лет разработки.
В подобных размышлениях прошло несколько дней. И вот однажды на меня снизошло озарение (я четко помню этот момент – я тогда мылся в душе). В моей памяти всплыл симулятор ограблений «Ва-Банк!», за которым я провел десятки часов в свое время. Мне хватило нескольких минут, чтобы оценить все преимущества разработки подобной игры:
1. Простота: стилизованная графика без претензии на реализм, компактные уровни, небольшое количество контента.
2. Интерес и профессиональный вызов: создание собственной системы ИИ для охранников, рпг-подобной системы прокачки навыков, придумывание локаций-головоломок и т.д.
3. Относительная уникальность: с выхода игры «Ва-Банк!» в 2001 году у нее так и не появилось прямого наследника, и мне захотелось создать его самому (хотя, как можно увидеть по результату, современной теории геймдизайна пришлось подкорректировать эти планы, осовременив большинство игровых механик).
Но определение с жанром и механикой геймплея – это только полдела. Для игры ведь еще нужно подобрать интересный сеттинг и нарратив. Моей первой мыслью было воссоздать эпоху США 1930-х годов: гангстеры, мафия, контрабанда, сухой закон и все в таком духе. Даже теперь этот сеттинг меня привлекает и выглядит вполне подходящим. Но на этом моменте я задумался – а смогу ли я придумать интересный сюжет и воссоздать правильную атмосферу? Или у меня получится поверхностный пародийный пересказ Крестного отца?
Я был уверен, что
реально интересное произведение можно написать только на тему, в которой сам
хорошо разбираешься и которую любишь. Я еще раз покопался в памяти и понял, что
у меня действительно есть одна тема, о которой я очень хотел бы высказаться: «разрушительное
влияние тоталитаризма и милитаризма на общество». И эта тема очень удобно
объединялась с моим любимым жанром антиутопии. «Приключение вора в карикатурном
тоталитарном обществе, находящемся в состоянии постоянной войны» – звучит
интригующе. В качестве игры для нарративного референса была выбрана We Happy Few, в качестве
книг-референсов «1984», «На западном фронте без перемен» и десяток других, в
качестве основного жанра – сатира.
Создать игру я планировал примерно за полгода (на тот момент даже этот срок казался мне довольно большим). Как вы уже могли догадаться, в этом и заключалась моя «ошибка планирования» – люди склонны слишком оптимистично смотреть на свое будущее, особенно пытаясь предугадывать какие-либо сроки.
За разработкой игры я проводил все свое свободное время во время отпусков и выходных, по 4-6 часов после работы в будние дни. Не вдаваясь в подробности хочу отметить, что разработка шла с переменным успехом в зависимости от выполняемых задач: я мог по 14 часов в день с воодушевлением программировать ИИ врагов, а затем целую неделю лениво ковыряться над созданием нескольких 3D-моделек или анимаций.
Спустя полгода у меня еще оставались недоделанными некоторые геймплейные механики, не говоря уже о наполнении игры контентом. «Небольшая игра с компактными локациями» оказалась не такой уж и небольшой. В первую очередь меня обманул внешний вид игры «Ва-Банк!»: графика и анимации, которые казались нормальными в 2001 году, для создания в современном качестве требовали в разы больших усилий и времени (о выборе ретро-стилистики я тогда почему-то не задумался). Более-менее играбельный «вертикальный срез» был получен только спустя 14 месяцев с начала разработки.
К тому моменту я успел пройти через несколько стадий выгорания и решил для себя так: выложу видео геймплея в интернет, и если мой прототип никого не заинтересует, то тут-же заброшу ее разработку (ведь даже проигрывая, люди склонны повышать ставки до самого конца, хотя зачастую было бы разумнее вовремя сдаться, смирясь с небольшими потерями (в моем случае – потраченный год времени)).
Глава 2. Командная работа.
В мае 2021 года я заявился на форум геймдевру вот с такой записью геймплея:
На нем можно увидеть, что были готовы основные механики взломов и краж, взаимодействия с объектами, ИИ охранников, и большая часть UI в черновом виде. Для меня тогдашнего игра воспринималась как нечто потрясающее, хотя для меня сегодняшнего (как и для вас) игра выглядит до жути коряво. Это к вопросу восприятия собственного творчества, которое на начальных этапах обязательно искажается эйфорией от получения простейших результатов в движке игры: «Мой кубик научился ходить! Это просто какая-то магия! Я Творец! В это уже можно играть.».
В общем, одновременно с публикацией этого видео, я объявил о наборе команды для помощи в разработке игры. Вы удивитесь, но буквально за неделю я получил более десятка откликов и вскоре основной состав команды был собран.
Здесь можно сделать отступление и сформулировать очевидный вывод: чем больше работы вы проделаете самостоятельно перед началом поиска команды, тем выше шанс собрать хорошую команду (либо у вас уже должно быть хорошее портфолио). Например, почти все модели персонажей в нашей игре сделаны человеком, который успел поработать над такими играми, как Dragon Age II и We Happy Few (вот это совпадение). Не думаю, что он согласился бы поработать в нашей команде, если бы я объявился на форуме с постом типа «Есть концепт игры на двух страницах, суть токова…».
В конечном итоге, сформировался состав из 7 человек: я (программист, геймдизайнер, сценарист), два 3D-художника, два 2D-художника, аниматор и композитор.
Настало время отступить от хронологии и рассказать, как организована наша работа. Не знаю, может это просто везение, но нам удавалось неплохо работать без мэйлстоунов, отчетности, планов и графиков. У нас даже не было ни единого созвона с каким-либо обсуждением. Я большинство реальных имен узнал только когда делал титры к игре. По сути, наше сборище – это гибрид между полноценной командой и фрилансом.
На фриланс это все походит из-за того, что непосредственно с движком игры работаю только я. Я просто говорю ребятам, что мне требуется для игры (скидываю текстовые описания и референсы). А они без лишних вопросов выполняют свою работу, скидывают мне результат, а я уже встраиваю все это в проект. С кем-то у нас договоренность на символическую оплату, кто-то работает за процент от продаж и для своего будущего портфолио.
Но есть во всем этом и немалая часть от командной работы. Всеми своими наработками я обязательно делюсь со всей командой – раз в 1-2 недели я скидываю свежий билд игры и рассказываю о проделанной работе. Один из 3D-художников почти переквалифицировался в тестировщика и по нескольку часов обкатывает каждый новый билд. Благодаря его стараниям у нас получается очень вылизанный проект (качество и отсутствие багов – довольно распространенный отзыв на нашу игру).
Работа с командой помогает мне оперативно получать фидбек сразу после внесения изменений. Несколько раз это помогло вовремя вернуть меня с небес на землю и избежать действительно серьезных геймдизайнерских просчетов (например, у меня были попытки излишне переусложнить рпг-составляющую игры). Также чувство причастности к команде дает мне дополнительную мотивацию – я просто ставлю перед собой цель «К концу недели я должен доработать уровень и показать его ребятам» и двигаюсь к ней (не без ошибок планирования, разумеется). И я думаю, что моя целеустремленность также подбадривает остальных членов команды.
Как итог, я бы выделил два основных плюса «гибридной командной работы»:
1. Большую часть времени вы работаете как инди-одиночка. Вы можете уделять время и силы любому компоненту игры, пока не доведете его до желаемого уровня. Вам не нужно тратить время на совещания и утверждения, чтобы внедрить какую-либо механику или перестроить дизайн уровня. Проект получается более гибким, живым и самобытным.
2. От команды проект получает результат работы настоящих профессионалов, который никогда в жизни не смог бы сделать одиночка. Это поднимает качество игры на совершенно иной уровень (сравните мое первое видео и свежий трейлер).
Минусы в нашей организации, конечно, тоже присутствуют. Основной – это то, что вся разработка завязана на мне, и если у меня мало свободного времени, то и разработка движется медленно. Полноценной командой такую игру можно было бы сделать и за год. Второстепенный – вся команда завязана на мне и периодически отнимает у меня много времени (особенно в первые месяцы, когда я чаще чувствовал себя менеджером проекта, а не разработчиком).
Глава 3. Цена фидбека.
Прошел почти год интенсивной разработки, и вот мы плавно подошли к февралю 2022 года. Нет, речь пойдет не о том, о чем вы подумали. В феврале наша игра приняла участие в фестивале демо-игр в Steam. Тут я бы хотел выделить три момента:
1. Я очень торопился поучаствовать в фестивале, т.к. планировал выпуск игры на весну-лето 2022 года (удивительно наивный господин). Поэтому пришлось участвовать с довольно сырой демо-версией, с багами и непроработанным визуалом.
2. Но! Сама подготовка демо-версии к определенному сроку очень хорошо влияет на темпы разработки. Мотивация «не обосраться» ускоряет разработку на 200%, проверено.
3. Если бы не эта демо-версия, то игра бы не стала такой, какой она получилась сейчас. Благодаря ей мы получили не очень много обратной связи, но каждый отзыв был на вес золота. Даже небольшой комментарий мог заставить взглянуть на проблему совершенно под иным углом. Ведь взор разработчика всегда «замыливается» и очевидно-неудачные механики или кривой дизайн уровней быстро перестают казаться таковыми.
Так что, очередной очевидный совет для инди-разработчиков: всегда прислушивайтесь к любому фидбеку. Даже если отзыв с первого взгляда кажется какой-то неподходящей глупостью, остановитесь на пять минут, сядьте в спокойной обстановке и хорошенько его обдумайте. После таких «медитаций» я, чаще всего, признавал наличие проблемы и начинал искать способы ее устранения. Аналогично следует поступать, просматривая летсплеи и стримы по своей игре.
Не вдаваясь в скучные подробности, проанализирую основные изменения в игре, сделанные по результатам полученного фидбека:
1. Часть игроков жаловалось на неудобное управление. Я не сразу догадался, что проблема не именно в управлении, а в неудобной камере, которая на тот момент была привязана к главному персонажу и двигалась по всем трем осям. Я понял, что надо это менять. В итоге камера получила полу-изометрическую перспективу с фиксированным видом сверху-внизу. Затем игрок получил возможность перемещать камеру отдельно от персонажа и при необходимости осматривать весь уровень, чтобы следить за перемещениями охранников и планировать свой маршрут. Таким образом, игрок стал получать гораздо больше информации, играть стало спокойней и приятней.
2. Если все в целом одобрительно отзывались об интерьерах домов, то уличные локации многим казались большими и пустынными. Поэтому была проведена работа над оживлением мира: добавлено много новых уличных объектов, симуляция ткани для флагов, визуальные эффекты вроде тумана и бликов уличных фонарей, всякая живность (птицы, мухи, крысы).
3. Главный герой научился прятаться за ящиками и предметами мебели, снижая при этом свою видимость и получая шанс остаться незамеченным, даже будучи загнанным в тупик. Для игроков это расширило диапазон доступных действий и маршрутов.
4. Убрана неоднозначная механика взлома замков с помощью случайных QTE-проверок. Вместо нее был добавлен «запас концентрации», который снижается при взломе сложных замков.
Это довольно показательное изменение, и вот почему. Механика QTE была добавлена в самом начале разработки после очень недолгого обдумывания: «Чем бы мне разнообразить процесс взломов? А добавлю-ка я QTE, почти как в Dead by Daylight!». С тех пор почти два года в моем подсознании зудела мысль, что с этой механикой что-то не так. Она не интуитивная, случайная, ужасно балансируемая. Но в мое сознание так и не могла пробиться мысль, что нужно ее поменять. Пока я не увидел всего одно сообщение: «Игра нормальная, но QTE здесь лишнее».
5. Чтобы упростить освоение игры, у нас стало визуализировано, озвучено или подписано практически все, что не было до этого: радиус обзора собаки, сложность запертого замка, скрытость или видимость игрока, панель быстрого доступа, информация о текущих заданиях, непрочитанная записка, нераспределенные очки умений…
Заключение.
Игра находится в финальной стадии разработки и уже практически готова. Мы даже приступили к локализации на основные иностранные языки (правда, с помощью машинного перевода). Так что, если среди вас есть люди, заинтересовавшиеся проектом и желающие помочь нам хотя бы с вычиткой и редактурой текста – ждем ваших предложений, вы бы нам очень помогли.
И еще одна важная для нас новость. Мы наконец-то перебороли свою
социофобию и завели аккаунт в твиттере: https://twitter.com/Slandermax
Привет! На связи та самая студия геймдизайна, от которой давно не было вестей.
Полгода назад мы разразились серией статей о том, как мы кардинально изменили свою жизнь после начала пандемии и начали делать игры. Сегодня мы хотим подвести итоги по нашему первому проекту, игре Plague M.D., вышедшей в Appstore, GooglePlay и Steam. В этой и следующих статьях приведем статистику продаж, расскажем о попытках выйти на китайский рынок, опыте работы с маркетологами и, конечно же, о новых проектах.
Итак, начнем с статистики. Самый прибыльной площадкой стал Steam. За полгода мы заработали чуть больше 17 000 $ (50% из этой суммы бессовестно забрал Гейб и налоговые службы) , из которых большая часть пришлась на короткий промежуток после релиза и на новогоднюю распродажу.
Может быть кто-то из наших читателей помнит, что изначально проект планировался как мобильная игра, но столкнувшись с реалиями мобильного рынка мы быстро переобулись и выпустились в Steam. И это было супер правильное решение. Результаты продаж в GooglePlay и Appstore скромные: 2500 $ за весь период в Google и меньше 2000 $ в Appstore. Почему так вышло? Мы выделили несколько причин, но основная - способ монетизации.
Много ли примеров игр, успешно зарабатывающих на мобильном рынке без системы микротранзакций, подписок, рекламы и прочих вещей, от которых мы отказались еще на этапе разработки? Немного. Рынок заточен именно под такие продукты, и ничего нам, романтикам, пришедшим на мобильной рынок с крафтовой поделкой, не помогло исправить ситуацию: таргет давал результаты ниже средних, маркетолог рекомендовал срочно делать приложение бесплатным и набивать его рекламой, чтобы выручить хоть какую-то конверсию, а мы недоумевали почему игра получилось местами такой хардкорной и недружелюбной к пользователю: совсем плохо для мобильного рынка.
Не последнюю роль сыграло и то, что в google мы выложились раньше всего, и львиную долю хейта за баги и паршивую оптимизацию принял на себя рейтинг продукта именно в Google Play
Рейтинг в Steam при этом пострадал значительно меньше. Оно и понятно, к моменту релиза мы успели выкатить пару обновлений, исправить самые надоедливые баги.
Сейчас продажи на всех площадках идут на спад. На Steam еще осталось изрядное количество вишлистов, которые можно конвертировать в продажи, если выкатить пару-тройку обновлений, но учитывая что команда уже врубилась с головой в следующий проект, чумной доктор, похоже, будет похоронен в ближайшее время распродажей с 50% скидкой.
Какие выводы? Я приведу короткий список из самых разных областей.
1. Следующие игры мы будем делать под ПК. Если и выпускать их на мобильный рынок, то позже, не торопясь и не возлагая на продажи особых надежд. 2. Платить блогерам за PR продукта ценой в чашку кофе - тупая затея. Посмотрите обзоры на Plague M.D. на YouTube - за некоторые из них мы заплатили денег. Лучше бы потратили их на алкоголь и бесчинства. Внимательно смотрите, как блогер работает с аудиторией. Самые классные обзоры и летсплеи сделали ребята, которым мы ничего не платили, максимум дарили ключи. Они сами были заинтересованы в игре, и результат был соответствующим. 3. Не выпускайтесь в Google и Appstore с багованным продуктом. Потеряете рейтинг на начальном этапе - потом не отмоетесь. 4. Пока ваша команда состоит из полутора землекопов - всегда лучше научиться что-то делать самим, чем искать кому передать работу на аутсорс за деньги. 5. Берегитесь выгорания. Общайтесь с коллегами и контролируйте нагрузку друг друга. Совмещение в одном лице нескольких должностей, отсутствие выходных и высокий темп - залог протекающего чердака. Больше денег потом потратите на лечение нервных тиков.
6. Начинайте процесс выкладки в магазины, оформления страниц и подготовки документации сильно заранее! Месяц - минимум, а лучше - больше.
7. Не недооценивайте возможность расширить аудиторию с помощью локализации. Хорошую часть продаж мы обеспечили, переведя игру на турецкий язык, не заплатив ничего: нам написала стримерша из Турции и предложила совершенно бесплатно перевести игру. На упрощенный китайский игру нам перевели энтузиасты, ведомые исключительно желанием языковой практики. На немецкий и французский перевели своими силами.
8. Не игнорируйте мероприятия и события индустрии. Врубившись в бесплатную онлайн-конференцию "Хочу в геймдев" от ВШЭ, мы, сами того не ожидая, заняли первое место и выиграли PS5. Это сильно подняло наш боевой дух, а страница игры в Steam обзавелась симпатичной нашлепкой.
Мы хотим сказать огромное спасибо всем кто нас поддержал словом или рублем. Повиниться, что не обслуживали игру должным образом. Должно быть, часть нашей аудитории ждала полноценное DLC, новых уровней и персонажей: хочу верить, что это состоится, когда трава будет зеленее а команда не такая голодная.
В следующей статье расскажем о нашем новом проекте.
Всегда мечтал стать разработчиком игр. Но что то пошло не так. И не так давно методом проб и ошибок я все-таки выпустил свою первую игру.
На что-большое я нерешился, решил сделать маленьку и простую игру. А что может быть проще - кликер😁 выбрал тематику, в моем случаии это кролики. Что может быть проще кликай по морковкам и собирай урожай. Сделал. Как-то скучно. Решил сделать деревню кроликов🐇 Ферма с морковкой уже есть. Нужна лесопилка, ну тогда уже добавим шахту и кузницу. И по итогу у нас 4 вида ресурсов:морковка, дерево, камень, железо. А зачем нам ресурсы? Правильно прокачивать домики. А и еще склад добавил. Все идея есть механику тоже продумал. Остался вопрос за графикой. Часть гафики купил на стороних ресурсах. Часть сам рисовал. Кроликов сам рисовал. Так сказать мой первый опыт.
Историческая справка: увы, в далеком-далеком будущем человечество так и не нашло себе новый дом во вселенной. Планета за планетой звездный исследовательский флот открывал одну непригодную для жизни глыбу за другой. Солнце медленно угасало, на Земле становилось все холоднее, энергетические ресурсы планеты были истощена. Тогда и был найден энергетический элемент Q444.
Даже с учетом его дорогостоящей транспортировки, цена получалась вполне приемлемой. Найден он был на планете, которая по сути являлась очередной безжизненной глыбой, покрытой толщей снега и льда. Условия на планете были суровые, но добычу, крайне важного элемента для выживания человечества, наладить в конце концов получилось, хотя это и стоило многих жизней.
Вернемся непосредственно к игре.
В Cyberwinter всего один доступный для сбора и использования ресурс - элемент Q444. Месторождения элемента географически не фиксированы, планета согласно своим собственным законам выталкивает периодически в случайном месте на поверхность целые области этого элемента из своих недр. Собирать элемент с поверхности в 1000 раз дешевле, чем вести раскопки, поэтому пришлось смириться с этой особенностью.
Для сборов элемента Q444 был разработан специальный вид техники - харвестер. Эта медленная, но достаточно прочная машина отлично справляется со своей задачей.
От регулярных доставок элемента Q444 на Землю теперь зависит дальнейшая судьба человечества. Главная цель любого представителя нашего вида в мире Cyberwinter - это не допустить даже малейшего сбоя в отлаженной до мелочей системе.
Q444 так же является и основным топливом на самой планете-источнике. Все здания, вся техника, все оружие заряжается очищенной и переработанной версией добываемого элемента. Харвестер не только собирает ресурс с поверхности планеты, но и на лету перерабатывает его до необходимой формы. Поэтому после сбора, прямо из харвестера можно заряжать остальную технику, здания или что-то еще.
На планете один за другим возводят терраформеры. Несмотря на ее крайне низкую пригодность для заселения, нельзя списывать со счетов доступность Q444. За тысячу лет, согласно первых расчетов, климат планеты будет скорректирован до необходимого минимума. Тогда звездный флот начнет массово перевозить "излишки" человечества с Земли на Cyberwinter. И уже с новой площадки исследовательский флот продолжит поиски следующего пристанища для нас…
Надеюсь, вам было интересно. Всем спасибо за внимание и хорошего вам инди!)
П.С. В прошлом посте я писал о своем подходе к интерфейсу в игре. Я получил так много полезного фидбека, что до сих пор не опробовал и половины всего, что мне показалось интересным из предложенного.) Хочу сказать всем, кто откликнулся, большое спасибо!
И у меня снова проблема, коллеги: незнаю как визуально обыграть элемент Q444, когда он лежит на поверхности планеты. Текущую реализацию можно увидеть на гифках. По сути, это просто двумерные квадраты разных размеров и повернутые под разными углами, желто-коричнего цвета из палитры игры. Меня очень расстраивает текущий вариант, но ничего интереснее я пока не придумал. Если у вас есть мысли по этому поводу, прошу поделиться со мной в комментариях. Всем заранее низкий поклон и вселенский респект! )
Итак, здравствуйте, пользователи Пикабу! Меня зовут Андрей, я ученик 11 класса и вот уже 2,5 года я пишу свою игру. В этой статье я бы хотел поделиться с вами своей историей: от идеи до релиза.
Да, это я:)
НАЧАЛО ПУТИ
Итак, начнем! Долгое время мы с друзьями пытались снимать мини-сериалы на ютубе. Как вы можете догадаться, ничего успешного из этого не вышло. И вот в один день мне пришла мысль: "К черту это все, все равно наши видео только знакомые смотрят, хочу сделать игру!" То было лето 2021 года, я переходил в 9 класс. Друзья идею поддержали, и я тут же начал изучать движок Unity и язык C#. Давным-давно мне уже приходилось с ними сталкиваться, но дальше колобка, прыгающего по стыренным из интернета платформам, дело не дошло. В принципе, первое, что я сделал - было повторение того колобка, чтобы узнать базовые механики и интерфейс Unity.
Это, определенно, шедевр!
АРКАДЫ, РЫЦАРЬ, 2 СКЕЛЕТА
Спустя пару недель я решил, что экспериментального опыта мне достаточно(разумеется, я ошибался) и пора сделать что-то более серьезное, но все же простую аркаду. Это должен был быть платформер про рыцаря и темный замок со скелетами и призраками(в плане сеттинга мне сильно подсказала игра "Rogue Legacy"). Казалось бы, обычная детская игрушка, но в моей задумке было написание 5 сложнейших уровней, в которых поражение приводило бы к перепрохождению уровня целиком. В конце нас бы ждал босс - лич!
Рыцарь, выполненный в стиле голова = тело
К проекту я отнесся серьезно. Были созданы концепты, сценарий, план. С появлением спрайта рыцаря, я начал его анимировать. Большую часть кода брал из своих наработок с колобком. И вот тут начались первые проблемы: команда! Рисовать я не умею, но у меня есть друзья, которые занимаются рисованием и в будущем планируют становиться дизайнерами. К таким, в том числе, относится и моя сестра. В начале процесс рисования платформ, ловушек и концептов шел более менее оперативно, но чем дальше - тем медленнее. Однажды, я дал сестре задание нарисовать новые концепты рыцаря в более реалистичном и мрачном стиле.
Выбранный в итоге концепт
Задача была выполнена аж спустя неделю, но ничего. После выбора концепта я сразу же попросил перенести его в спрайт. Прогресса в этом плане так и не было, но он мне и не нужен был, так как случилось неожиданное озарение.
ИДЕЯ ИГРЫ
Я всегда был фанатом настольных игр. Одной из них была "Особняки безумия" по мотивам рассказов Г. Ф. Лавкрафта. Это интерактивная игра, в которой мы играем за сыщиков, которые должны разгадать тайну мистических явлений того или иного места. Создавать поле и двигать прогресс нам помогает приложение, которое говорит, какие части поля нужно добавить, каких монстров нужно выставить, а также контролирует игровые события, мешающие или помогающие прохождению.
Игра "Особняки безумия"
Так вот однажды отец мне сказал: "А почему бы не сделать такую же компьютерную игру? Просто взять и перенести все механики на компьютер, но со своим сеттингом и историей. Пусть сыщики по заброшкам ходят и исследуют их". На что я ответил: "Ага, скажи еще, что это блогеры". И неожиданно для меня услышал: "Да, пусть это блогеры будут".
Эта идея озарила меня. Я тут же ринулся накидывать идеи, рассказал все команде со словами: "Нафиг рыцаря, делаем игру про блогеров, которые по заброшкам ходят". Как ни странно, но она поддержала эту мысль, т.к. эта идея звучала более оригинально, нежели просто рыцарь и скелеты.
ПРИКЛЮЧЕНИЯ НАЧИНАЮТСЯ
Итак, этот момент можно считать началом истории той игры, о которой говориться в названии. Что мы имели в начале пути: 1 программист и сценарист в одном лице(то есть я), 2 художника, 1 музыкант и еще 2 человека, которые очень хотели помочь в разработке, но не знали как. Честно скажу, что оптимистичный настрой был только у меня, хоть я и всеми силами пытался убедить команду в перспективе проекта. Я начал писать сценарий как истории, так и геймплея.
ПЕРВЫЙ КОНЦЕПТ
Было решено, что игра будет в 2D с видом сверху, где главному герою предстоит искать предметы, чтобы выбраться из паранормального места или победить зло. Также в игре была боевка, которая проходила в формате мини-игр типа армрестлинга или покера в "Ведьмаке" или, например, раннер, который по сути являлся той самой игрой, каких пруд пруди в Play Market. История должна была проходить в старинной усадьбе царской России, в которой кто-то проклял ее владельцев и слуг, из-за чего все стали призраками или же иными существами и предметами.
ГЛАВНЫЙ ГЕРОЙ
Главный герой - блогер, который является пародией на самого известного белорусского блогера, чье имя вы уже можете угадать. Один из художников, отлынивая от уроков, нарисовал первое изображение персонажа.
Первое изображение героя
Было решено назвать его Володей Ватманом. В дальнейшем моя сестра переработала и немного переосмыслила образ, внеся в него много важных отличительных атрибутов, которые до сих пор являются неотъемлемыми компонентами образа, а именно рыжие кудрявые волосы, красная шапка, которую он не снимает и красно-белые кроссовки.
Итоговый вид Володи Ватмана
ПРОЧИЕ ПЕРСОНАЖИ
В итоговой версии я выделил еще несколько важных персонажей, которые сильнее влияли на историю и геймплей. Вкратце расскажу о нескольких из них.
Константин Краснов - сын графа и главный антагонист игры. Именно он наложил на усадьбу проклятье, став при этом бессмертным и вечно молодым человеком.
Баров - повар усадьбы. После проклятья он, в отличие от большинства, стал человеком-свиньей. Изначально его звали Тельцов и был он человеком-быком, но о причине изменений чуть позже.
Евдокия - горничная. По задумке это должен был быть первый призрак, которого встречает игрок. Именно она подсказывала бы герою и помогла попасть на 2 этаж дома.
Константин Краснов
ПЕРВЫЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Лично мне не было тяжело с подготовкой к ОГЭ, но я не мог сказать то же самое о своей команде. Конечно, времени было мало, что приводило к низкой производительности. Игра полностью в 2D, а рисунки выходят раз в 2 недели, и то в лучшем случае. Прошел год, программной части было написано много, а вот спрайты практически полностью отсутствовали. Единственной локацией, которая была проработана полностью был маленький винный погреб.
Винный погреб
Эта проблема привела меня к принятию решения, на которое я долго не решался. Я решил полностью перейти на 3D. Звучит забавно: не хватает спрайтов, зато модели будут? Как оказалось - да, будут. В этом мне помогли low poly модели от Synty Studios. Так вся игра стала 3D, за исключением интерфейса. Даже головоломки были адаптированы и переработаны под трехмерное измерение. Кстати, одной из проблем стала нехватка нужных моделей. Так, например, ни в одном наборе не было модели минотавра, но была модель свиньи-мясника, из-за чего Тельцов преобразился в Барова!
Скриншот из альфа версии игры
ВТОРОЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Кто бы мог подумать, но писать каждую мини-игру с проработкой отдельных механик - не тривиальная задача. Многие интересные идеи просто "посыпались" из-за сложности реализации и моего желания выпустить игру как можно скорее. Так была убрана система здоровья и стресса и ивенты, приводящие к изменению этих характеристик, система боя, вариативность действий в разных ситуациях, мини-игры стали частью головоломок... В итоге игра стала простым квестом, о чем я не сильно пожалел, так как изначальной идеей и был квест, но с дополнительными фишками.
ТРЕТИЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Став "идеологом" игры, я взял на себя руководительские обязанности. И что я скажу: это невероятно тяжело. Те 2 человека, которые хотели помочь, практически в самом начале ушли из проекта, хоть и помогли в сочинении нескольких загадок. Один художник разработал первые концепты, создал план дома, из-за чего достоин места в титрах, но по причине тяжелой учебы, решил прекратить свое участие. Потеря художника - это ужасно, особенно когда работа над кодом идет значительно быстрее, чем над иконками и портретами. Так нас осталось трое: я, моя сестра художник и друг музыкант. Вообще мы думали, что написать музыку в игру будет практически нереально, однако с этой задачей нам удалось справиться, сохранив стилистику игры в саундтреке.
Наша команда в стилистике игры
Тем не менее, руководить 2-мя людьми - тоже непростая задача. У каждого своя занятость, разный уровень мотивации, так что новые портреты, иконки и интерфейсы появлялись нерегулярно.
ЧЕТВЕРТЫЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
БАГИ! Чертовы баги! Их было настолько много, что по неопытности приходилось переписывать целые механики. Особенно сильно я мучался с инвентарем. Вначале он был под кнопкой инвентаря, потом оказался внизу экрана. Вначале было ограниченное количество предметов на сетке, которая видна полностью и без сортировки, потом пришлось сделать иконки крупнее, добавить странички и написать сортировку. Но самое главное: ячейки стали появляться динамически, так что теперь количество предметов в инвентаре может быть любое.
Было
Стало
ПЯТЫЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Назову это чем-то вроде "разочарования в игроках". Мне с детства нравились квесты, мне всегда казалось, что чем сложнее и запутаннее квест - тем лучше. Однако, дав сторонним людям поиграть в игру, оказалось, что пройти ее полностью удалось только 1 человеку - такому же ценителю квестов, как и я. Остальные, зачастую, даже в дом пробраться не смогли. Это привело к тому, что мне пришлось изменять некоторые элементы геймдизайна: менять расположение предметов, подсвечивать слабо заметные предметы, добавлять наводящие символы. Самым масштабным решением было добавление заметок и описания предметов в отдельном меню, где игрок может всегда сориентироваться, какие цели у него выполнены, а какие нуждаются в размышлениях. Как ни странно, это помогло. Люди стали без проблем заходить в дом и даже проходить игру до конца.
Меню заметок
ШЕСТОЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Возвращаюсь к теме багов, но не простых. Когда уже все было готово к релизу, я передал игру тестировщикам, которые издевались над игрой как могли. Они закликивали кнопки в неподходящий момент, бились во все углы и стены, из-за чего проваливались за текстуры. Один раз даже удалось пройти сквозь стену в запертую комнату, недоступную в альфа версии, но имеющую заготовки, тем самым проспойлерив финальную часть игры. Кучу раз я собирал проект в надежде, что это последний раз, но тестировщики умудрялись найти новые дыры.
Добро пожаловать в бездну!
СЕДЬМОЙ КРУГ ПРОИЗВОДСТВЕННОГО АДА
Настало время публикации. А куда выкладывать будем? Конечно, изначально все ориентировались на Play Market, но, как известно, сейчас доступ к аккаунту разработчика недоступен в России. Первой альтернативой стали Яндекс игры. Однако это решение было отброшено по нескольким причинам:
Всем думаю известно, что творится на этой платформе и какая у нее аудитория. Через неделю игра уже утонет в каком-то барахле.
Проблема со сборкой WebGL версии в Unity(игра появлялась, но не загружалась).
Решение пало на новую платформу от МТС - AppBazar, которая еще находится в бета-версии. Она публикует приложения под андроид, так что нужна была обычная apk сборка. Единственное что, проект в бета-версии, из-за чего аудитория крайне низкая, и о нашей игре могут узнать разве что из сторонних источников. Однако проект приложения крайне перспективный.
Вначале хотели прикрутить донаты в виде добровольных пожертвований разработчикам, однако плагин в нашей версии Unity отказывался работать, так что эту идею мы отложили. В общем, выбор платформы и настройка игры под нее тоже требовали определенных заморочек. Когда выйдет полная версия - планируем немного переработать управление и интерфейс для ПК и выложить в VK Play и/или Steam.
РЕЗУЛЬТАТ РАБОТЫ
Вот несколько скриншотов из альфа-версии игры:
Статуя у входа в усадьбу
Диалоговое окно
Диалог с персонажем
Повар Баров
Картина
ИТОГИ И ЛИЧНЫЕ ВЫВОДЫ
Итак, выпущена альфа-версия игры и есть заготовки на полную. Я открыл для себя новые фишки в программировании, получил опыт руководить командой, написал интересный сценарий. Конечно, все это было получено потом и кровью, кучей ошибок и провалов, но что нас не убивает - то делает сильней. Сейчас я начал читать литературу по программированию и геймдизайну, в будущем надеюсь связать жизнь именно с разработкой видеоигр. Создание новых интерактивных историй меня сильно вдохновляет, хоть их разработка и включает в себя просто безумные процессы с кучей трудностей, которые придется преодолеть всей команде.
Всех с наступившим Новым годом! Мне предстоит сдать ЕГЭ и поступить в вуз, но я надеюсь, что завершу наш проект уже в этом году. Желаю всем крепкого здоровья, счастья, успехов в жизни и чтобы интернет во время каток был стабильным;)