...

воскресенье, 21 октября 2018 г.

Как мы настольную игру с удаленным управлением сделали — Часть 2

В прошлый раз я рассказал вам о технической составляющей нашей «умной» настольной игры, с какими проблемами столкнулись и что получилось в итоге.

image

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

Первую статью можно найти тут: Как мы настольную игру с удаленным управлением сделали — Часть 1

Внимание! Много картинок дальше.
В комментариях к прошлой статье правильно заметили, что лучше делать не игру, а платформу, на базе которой уже можно создавать игры, используя доступные механики. Изначально мы так и планировали, но в результате поняли, что сделать что-то в отрыве от игры у нас не получится. Просто из-за отсутствия опыта в геймдизайне или знакомых геймдизайнеров, которые смогли бы нам подсказать какие механики должны поддерживаться.

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

Мобильное приложение


Как я писал ранее, все управление платформой ведется через мобильное приложение, которое соединяется с ней по протоколу BLE.
Несколько гифок

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

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


В самом начале мы столкнулись с проблемой, что данные, которые уходят от приложения, теряются. Выяснили, что при использовании BLE максимальный размер пакета, который может быть отправлен, составляет 20 байт. Поэтому все исходящие по BLE данные мы разбиваем на пакеты по 20 байт, в заголовке которых прописывается параметр “Gate”. Данный параметр помогает Arduino понять к какому именно компоненту платформы относится данный пакет. Со стороны Arduino обработка этих пакетов элементарна:
if (NewCommandReady) {
    switch (CurrentGate) {
      case 1:
        processLEDCommand();
        break;
      case 2:
        processDriverCommand();
        break;
      case 3:
        processMagnetCommand();
      case 4:
        //тест       
        break;
    }
       //команда обработана
    NewCommandReady = false;
  }


После того как мы разбили потоковую передачу данных между смартфоном и BLE-модулем на передачу пакетами по 20 байт данные перестали пропадать, но часто приходили на Arduino в искаженной форме. Оказалось, мы не учли, что у серийного порта Arduino есть буфер в 64 байта. При переполнении буфера данные терялись, а последующие искажались. Увеличение размера и создание своего собственного буфера помогало не всегда. Пришлось поверх транспорта BLE писать протокол-обертку для надежной отправки и получения данных.

Из-за использования такого “протокола” обмен данными немного замедлился проверками целостности передаваемых данных, однако для игры более критична надежность — будет обидно если отображение AOE некоторой способности будет не полным или герой не будет перемещен при подтверждении хода на мобильном телефоне.

Для отображения объектов на игровом поле мы использовали принцип слоёв в оконных подсистемах ОС:

  • Каждый объект или действие, которые подсвечиваются (герои, препятствия, путь перемещения героя, доступная область применения способности и остальные) использует свой собственный слой.
  • При наложении слоев (например область АОЕ поверх доступной области применения способности) запоминается первоначальное состояние светодиодов. В результате есть возможность вернуть оригинальный цвет, когда верхний слой пропадает.

Основной объем передаваемых данных между мобильным приложением и платформой — перекраска светодиодов. В целях оптимизации было добавлено пару алгоритмов:
  • Для перекраски диодов используется буфер, в который вносятся изменения до того момента когда эти изменения должны быть отображены на физической доске.
  • Перекраска одного светодиода в рамках одной и той же команды исключается.
  • При перекраске (например смещение области АОЕ-способности на 1 клетку) анализируется текущее состояние светодиодной доски. В случае, если цвет светодиода в новом состоянии не отличается от предыдущего — никакие команды на Arduino для его перекраски поступать не будут.

Игровой процесс


Итак, вы решили сыграть. Ниже я опишу как это выглядит со стороны:
  1. Вставляем вилку в розетку и включаем игру.
  2. При каждом запуске происходит автоматическая калибровка для определения точного количества шагов шагового двигателя для перемещения на 1 клетку.
  3. Параллельно подключаем смартфон к игре с помощью Bluetooth.
  4. В мобильном приложении каждый из игроков выбирает героя, которым он хочет играть. После того как все сделали свой выбор, нажимаем “START”.
  5. Каждый из героев имеет свой цвет. Игра автоматически подсветит клетку, куда необходимо поставить фигурку вашего героя.
  6. Игра происходит последовательно. Первый ход делает игрок, который первым выбирал героя, второй — второго и т.д.
  7. У каждого героя есть определенное количество Очков Действия (ОД), которые можно тратить на перемещение по арене или применение способностей.
  8. Каждая способность имеет своё время восстановления, которое исчисляется в раундах. В рамках мобильного приложения есть 2 понятия: Ход — промежуток от начала до конца текущих действий игрока. Раунд — сумма ходов всех игроков, участвующих в игре. На данный момент ход одного игрока ограничен 30 секундами.
  9. На поле расставлены препятствия, через которые игрок не сможет пройти или применить большую часть способностей. Сейчас они просто подсвечены красным цветом на игровом поле, но в будущем у них будет физическое воплощение.
  10. Перемещаться полю можно с помощью специальных способностей, которые есть у каждого героя. Например телепортация мага. В отличии от стандартного перемещения, когда игрок прокладывает маршрут своего героя клетка за клеткой, при использовании данных способностей игрок указывает только конечную точку. В результате возникает необходимость в алгоритме по поиску кратчайшего пути к указанной точке, минуя все объекты, с которыми возможна коллизия (фигурки других героев, фигурки препятствий и т.д.).

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

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

  11. После смерти героя игра автоматически передвигает его фигурку в “домашнюю зону”. Домашняя зона — клетка, в которую помещается фигурка в начале игры. У каждого игрока она своя. После старта игры в домашнюю зону нельзя войти или применить туда способность. Это сделано для того, чтобы нельзя было подловить игрока на возрождении. Для игрока, чей герой потерпел поражение, игра заканчивается на 1 раунд. После он вновь вступает в бой.
  12. На данный момент побеждает тот игрок, чей герой последним остался на поле, победив соперников. Но условие может быть и другим, например побеждает тот, кто набрал N фрагов первым.

Это игровой процесс, который работает в текущей версии. Из-за недостатка опыта в геймдизайне, возможно, мы не видим очевидных косяков или возможностей. Например, всегда мучительно ожидать своего следующего хода. В текущей реализации время ожидания может достигать 1,5 минуты. В следующей версии прототипа мы планируем добавить считыватели RFID-меток, которые позволят разнообразить геймплей. Например использовать карты с RFID-метками, которые можно применять вне своего хода.

Миниатюры


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

За основу она брала наших же домашних животных. Так, у нее дома жил огромный и злобный кот по кличке «Пират» — именно он лежит в основе миниатюры Воина.

Через пару недель мы получили наши первые скетчи.


Из статей по производству настольных игр я понял, что в России дела с созданием миниатюр достаточно плохи и многие заказывают их в Финляндии или Германии.

Прежде чем заняться производством миниатюр нам было необходимо сделать мастер-модели каждого героя, которых вполне достаточно для прототипа. Сперва мы хотели делать их из полимерной глины, но оказалось, что среди наших знакомых нет миниатюристов, а делать на заказ было слишком затратно на тот момент. Поэтому мы решили, что сперва будем печатать их на 3D-принтере. Для этого наш знакомый сделал нам 3D-модели наших первых героев в Zbrush.


С помощью FDM-печати распечатать фигурки приемлемого качества у нас не получилось, что было вполне ожидаемо.

К счастью у моей жены на работе есть SLA 3D-принтеры.

Стереолитография (SLA) — это технология 3D-печати, позволяющая с помощью источника света, слой за слоем, с помощью процесса фотополимеризации, преобразовывать жидкие материалы в твердые объекты. Толщина слоев, во время печати по технологии SLA, в несколько раз меньше чем во время печати с помощью FDM, следовательно и качество готового изделия получается выше.

Через несколько дней нам отдали наши первые миниатюры.


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

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

Итого


На данный момент мы занимаемся улучшением физических характеристик платформы и надежности всех компонентов. Фанеру заменим на поликарбонат и ABS-пластик, усовершенствуем крепление компонентов платформы между собой и сделаем игровое поле съемным, чтобы можно было его поменять на поле другого форм-фактора (например гексагональное). Следующим шагом будет создание полноценного MVP, который не стыдно показать людям.

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

Спасибо всем за вашу критику/советы/проявленный интерес. У нас возникли идею по поводу создания версии без использования механики, но с возможностью определять положение и тип фигурки на поле. Думаю следующую статью напишем уже после создания MVP.

Let's block ads! (Why?)

Комментариев нет:

Отправить комментарий