Игра для РЖД: complete story

    image

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

    Кстати, на сайте Канобу еще неделю будет длиться конкурс с билетами на Игромир в качестве приза.
    Ссылка на игру
    и на внеконкурсную версию (без обертки Канобу)


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

    Эта статья не является hello-world для HTML5-игры в стиле crappy bird. Мы говорим о реальном проекте с точки зрения разработчика, о кране сжатых сроках, о написании игры с кучей хаков, о нервировании огромной цепочки заказчиков сдачей проекта в последний день, без запаса по времени. Хотите чистого кода — идите на github и мучайте наше детище сколько хотите. Код лежит под лицензией MIT, но весь арт сюда не входит.

    Как РЖД печётся о безопасности мы знаем по огромным экранам на вокзалах. Лично я думаю, что если бы эти ролики не были зацензурены, и были выполнены в стиле mortal kombat, эффект был бы гораздо больший (Poezd wins. Fatality).



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

    ТЗ был расписан достаточно прямо: должен быть генерируемый уровень, вид «сверху-сбоку», поезд соответствующий стилю РЖД, 6 видов препятствий и 3 супер героя, объясняющих как не надо себя вести на путях. Всё это должно работать на адекватных браузерах, на PC и планшетах. В качестве супер героев были выбраны Супермен, Человек-Паука и «тот парень из из GTA San Andreas»…

    Думаете мы использовали свой супер-движок, который может рендерить всё на DIV либо на CANVAS2D либо SVG и прорисовывающем только те места где что-то менялось? Думаете мы взяли свою super-CMS для генерирования страниц и менеджмента скриптов? Нет, мы взяли самый лёгкий рендерер на свете — pixi.js, самый лёгкий на данный момент сборщик скриптов — gulp+browserify, самую простую библиотеку для single-app — angular.js, самый тупой бэкэнд — node.js, самую тупую нарезалку спрайтов — shoebox, самый простой в использовании 3d-редактор — blender, самый тупой редактор многоугольников — physicseditor, самый лучший скелетный 2d-animator spine. Инфраструктурых вопросов у нас не возникало. Мы вообще технически не выделялись.

    Был составлен халявный план:
    0) поезд будет проезжать целый экран, и останавливаться на станции, пока генерируется следующий экран.
    1) надо чтобы был путь с фиксированной кривизной на поворотах, который можно удлинять и у которого можно получать координаты шпал.
    2) путь надо уметь проверять на самопересечения. Используем простую сетку, храним в каждой клетке кто её пересекает. Мельче сетка — больше вероятность что пути начнут пересекаться.
    3) путь должен заканчиваться где-то справа экрана, чтобы его можно было продолжать при генерации следующего экрана.
    4) должен быть тупой алгоритм который перебирает такие пути и выбирает покрасивее и подлиннее.
    5) результат можно заполнить разными объектами (деревьями и камушками).
    6) поезд можно зарендерить в 32 кадра. Выглядит это не очень, но «доворот» спрайта до нужного угла прямо в игре всё решает. Это удалось сделать довольно быстро, соотношение результат/время было офигенным, на демку можно было медитировать:

    первая демка

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

    вторая демка

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

    От одного из промежуточных результатов всех в прямом смысле тошнило: на свой страх...

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

    Ну и процесс слияния и раздвоения путей тоже добавил мороки. Мы нередко начинали ходить по кругу:
    image

    Переключение стрелок в итоге зарезали, и это нас всех очень расстроило.

    Равно как и товарища, похожего на героя из GTA. Наверху решили что он слишком «быдловат»:
    сэмки есть?

    Дальше пошли препятствия (в прямом смысле, их надо было делать согласно ТЗ). Вот тут мы отомстили по полной программе и показали то как мы можем чинить препятствия: наш «арт-директор» ушёл в августовский отпуск и из-за длительной переделки генератора так и не успел согласовать многие моменты с заказчиком. Я регулярно подходил к компу, перечитывал пункт про препятствия, до меня не доходило что с этим делать, и в итоге тратил время на оптимизацию игры (разные 2d/webgl варианты, запихивание спрайтов в атлас), вместо того чтобы разобраться с художниками и уточнить сценарий. Недовольство по поводу отсутствия существенных апдейтов переходило по цепочке, начиная с главного заказчика, и останавливалось на kanobu.ru, которые терпели, но вели себя с нами совершенно корректно. За неделю до сдачи этот тупик совместными усилиями разрешился, был составлен подробный сценарий, нарисованы идиоты и другие элементы препятствий. В намеченный договором день всё работало как надо.

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

    Уже после запуска проекта выяснилось что на многих устройствах генератор слишком тормозит и не успевает построить путь спереди. Выход оказался тривиальным — поменяли json-формат карты на бинарный и сгенерировали на серверной стороне 100 тысяч экранов. Это стало возможно поскольку игра разделена на node.js модули и собирается с помощью browserify. Игрок начинает на случайном экране в первой половине, и до того момента, как кешированные экраны кончатся и придётся вместо подгрузки экранов с сервера задействовать генератор пройдет очень много времени :)

    Этот подход дал неожиданный эффект: на «дальнем востоке» появились очень кривые дороги.
    image

    Из-за того, что в бинарке мы писали float а не double, на экранах с огромной x-координатой (десятки миллионов) стало не хватать точности координат, рельсы стыковались с ошибками в 1-2 пикселя. Да, Дальние Земли начались у нас гораздо раньше чем в майнкрафте. Та же ошибка стала проявляться при прорисовке рельс
    Кривизну дальневосточных рельс исправил переход от глобальных координат к локальным относительно экрана.

    Чтобы начинать с любого места, вся дорога делится по десяткам экранов, и хранится в разных файлах. При этом конечные сегменты рельсы надо дублировать и в предыдущем и в следующем файле, иначе не получится начать езду не с первого файла. И вот эту дублированную рельсу мы забывали удалять при загрузке очередного десятки экранов, а поскольку координаты рельс расчитывались несколько извратно чтобы не заехать в дальний восток, результат выглядел просто шикарно:
    image

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

    Перспективы у игры отличные: на основе получившегося генератора можно сделать много новых проектов. Можно добавить приколов и реализма, которого все так жаждут (если поезд не задавит идиота, то хоть охрана выйдет и отомстит).
    Можно расписать о том что мы сделали инновационный искусственный интеллект, который генерирует пути для РЖД, выиграть какой-нибудь приз в стартаперских тусовках, найти инвестора…

    P.S. Специально для хаброжилов с сегодняшнего дня где-то около 2015-ой отметки стоит небольшая пасхалка.
    P.P.S Статья случайно была опубликована изначально на ГТ, давно не постились ;)
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 21
    • +4
      Так стрелки всё-таки есть где-то или убрали?
      П.С. Поворот поезда определённо нравится. Чего нехватает во всех Tycoon-ах.
      • 0
        Убрали возможность переключать стрелки, путь по которому едет поезд берётся от балды. Во второй демке эта возможность есть.

        Поворот поезда сделан в стиле древних стратегий, CnC, red alert, правда там не было трюка с доворотом спрайта до нужного угла.
      • +2
        Вообще, странно, вроде все в детстве хотели железную дорогу, а реально игр теперь на ЖД тематику (ну типа СимСити, только с упором на ЖД) совсем немного выпущено…
          • +2
            Как же много я играл в неё в детстве! :)
            • +2
              Видимо, тема поездов актуальна всегда. Вот буквально 3 дня назад мы зарелизили ремейк шортлайна — train-valley.com
              • +1
                А вот их младший браузерный брат: railway valley 2

                image

              • +1
                А я сразу заностальгировал по Tycoon.
              • +1
                Их как раз немало для такой узкой ниши, имхо. Есть OpenTTD для ностальгирующих, Sid Meier's Railroads для тех, кому нужны няшные паровозики, Train Simulator для тех, кто в детстве мечтал быть кочегаром, и Train Fever для тех, кому важна экономическая составляющая. Куда больше?
              • +2
                Хм, дизайн поезда взяли с электропоезда Ласточка, а электрификации в демках не видать. Дизельные Desiro выглядят немного по-другому.
                • +1
                  А это РЖД попросили сделать человечков, которые бегом догоняют движущийся поезд, так сказать, для большей реалистичности?
                  • 0
                    Именно:) В ТЗ было что-то вроде «поджидают в кустах и забираются на ходу»
                    Изначально мы планировали их пускать когда поезд притормаживает или останавливается на станции…
                  • 0
                    Ждем образовательную статью, как написать бота для этой игры :)
                    • 0
                      Надо либо вклиниться в логику и следить за появлением препятствий, либо вклиниться в рендеринг (pixi) и следить за появлением маркеров препятствий, отсылать им мышиный клик.

                      Гораздо более интересно подменить 2д на 3д :)
                    • +2
                      Я хоть и любитель всего флешового, но эта статья, пожалуй, лучшая на хабре про html5/webgl, где хочется похвалить автора.

                      Спасибо за адекватную и нормальную статью и игру, а не поделки из серии «Флеш говно потому, что вот hello world на html5». От всей души плюсую!
                      • 0
                        Большое спасибо!

                        Хотел написать ответ, но почему-то вышел список ссылок на другие проекты :)

                        Да, флеш никак не говно, как минимум потому что на нём есть танчики, рисуют ниндзю, и autodesk scaleform.
                        На флеше я помню замечательные вещи от Nicklaus Liow (The Game, Reimagine: The Game), правда он потом на HTML5 перешёл (nothing to hide), но он вообще много чего меняет, он известный транс.

                        Кстати, чисто по webgl впереди всех сейчас лондонские товарищи из ga.me и playcanvas.com, но это возможно до тех пор пока artillery.com не выйдут из закрытой альфы. Среди 2d-движков конечно pixi.js (YAY!) и libgdx (java, люблю её).

                        Поскольку часть ресурсов у нас рендерилась в блендере, то я попробую это всё засунуть в playcanvas в качестве демки :)
                      • 0
                        Равно как и товарища, похожего на героя из GTA. Наверху решили что он слишком «быдловат»:

                        Это зависит от контекста,
                        мне вот тоже так показалось (что лишком «быдловат»).
                        А какова его роль в игре?
                        • 0
                          Просто объяснять игроку, что лихачить на жд путях — не самое умное занятие.
                          Текст финальный для него так и не был утвержден, но никакого налета ганстерщины не предполагалось.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.