Создание мультиплеерного 3D-шутера на Webgl без опыта и денег

Это первая часть истории о том, как маленькая команда веб-разработчиков разработала мультиплеерный 3d-шутер без опыта в геймдеве, больших денег и штата сотрудников.

Дисклеймер: некоторые описанные в статье решения могут вызывать фейспалм.




2011 год. С чего все началось


В 2011 году мы были маленькой питерской веб-студией из 4 человек. Тимлид/сеошник, программист (вернее считал себя программистом), дизайнер и менеджер по продажам. На тот момент тимлид и программист занимались сайтами уже 3 года, но особых успехов на этом поприще не достигли. Хотя мы имели уже несколько постоянных клиентов на продвижении и обслуживании, но львиную долю дохода съедали налоги, аренда офиса и прочие расходы. Оставшихся копеек на четырех человек явно не хватало. Хроническое безденежье и отсутствие перспектив угнетали. Дизайнер уже навострил лыжи, да и остальные члены команды едва держались. Вот в такой обстановке и пришла в голову потрясающая по наивности мысль: «чего это мы все для всяких дядь делаем проекты, а давайте свое что-нибудь сделаем, например, игру браузерную и запилим её во вконтакте». Все, кроме дизайнера, восприняли идею с воодушевлением.

Как большинство «начинающих» геймдевелоперов, решили делать ММОРПГ. Надо сказать, что ни у кого из нас не было опыта в геймдеве. Если не считать небольшой фришард lineage2, который содержал программист и допиливал там самодельные хроники. Допиливание в основном ограничивалось серверной геймдатой, на большее не хватало — ни ума, ни знаний. Так или иначе, некоторые представления об устройстве серверной части это дало. Опыт же администрирования и общения с контингентом игроков твердо убедили в одном: клиенту верить нельзя — все, что можно сделать на сервере, нужно делать на сервере.

Вернемся к нашему проекту.
Обязанности распределили следующим образом:
Тимлид — стал гейм дизайнером;
Менеджер — взял на себя звук;
Программист – остался программистом.

Изначально предполагалось, что это будет некая смесь фоллаута и мародера (на движке 7.62), с изометрией, но реалтайм.
Местом действия должен был стать постапокалиптический Санкт-Петербург.

Первые шаги


Техническая реализация представлялась тогда следующим образом:
Игровая локация состоит из img и div тегов.
Наложение друг на друга задавалось z-indexом, который рассчитывался исходя из положения объекта по оси y.
Персонажа не было, его обязанности тогда исполнял белый квадрат.
Связь с сервером через comet соединения.
Управление через клики мышью.

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

Препятствия


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



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

Обход препятствий


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

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


Оставались замкнутые области внутри объектов, в которые невозможно пройти, но это не сильно смущало

WebGL


Дошла очередь до визуализации персонажа. Сложность состояла в следующем: Предполагалось что персонаж может иметь 3 положения — стоя, сидя, лежа и все это умножалось на 8 ориентаций в пространстве.
Предполагались различные виды оружия: пистолеты, винтовки, пулеметы и различная броня.
Первая мысль — сделать это все на спрайтах, но даже с учетом новомодного css3 transform количество спрайтов представлялось колоссальным, а возможности по кастоматизации весьма ограниченными. Начали искать другие решения. Нужно было что-то, что рисовало бы персонажа налету.
Такое решение нашлось – WebGL.

Первым опытом стал конструктор игр CopperCube. Сделали экспорт пустой сцены с анимированным персонажем и воткнули ее целиком вместо белого квадрата. При беге включалась соответствующая анимация, персонаж поворачивался в пространстве, как угодно. Неплохо, а может всю сцену построить на WebGL?

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

Нужно было что-то более низкоуровневое, что позволило бы создать свою игровую механику, но при этом избавляло от работы с WebGL напрямую (в 3D-программировании тогда у нас в команде никто ничего не понимал).

Опробовав ряд библиотек, остановились на three.js. Несмотря на то, что с документацией тогда было чуть лучше, чем никак, в сети было огромное количество демок, где можно было посмотреть, как делаются те или иные вещи. Собственно, это и определило выбор.

Остаток года был потрачен на перенос клиента в 3D.



Так же были портированы редакторы объектов и карт.



2012 год. Понижаем планку


С момента старта разработки прошел уже почти год, но результаты пока не впечатляли. Геймдиз выдавал идеи, наброски интерфейса, описание персонажей и будущих локаций, но до воплощения дело так и не доходило. Внятного сюжета в начале тоже не было. Была общая идея — в следствии апокалипсиса, или внезапной неизвестной атаки, чистая вода стала на вес золота. А игру на этой почве решили назвать WasteWater (сточные воды).

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

Но самое главное — игрового контента у нас не было, более того пока не было даже представления где его взять.
Очевидное стало очевидным — ММОРПГ нашими силами нам никогда не сделать.
Тогда решили упростить все до командной стрелялки. В общих чертах игра теперь должна была выглядеть так:

Лобби, где игрок мог заниматься такими делами как: покупка снаряжения, экипированием персонажа, прокачка скиллов.

Боевой режим, куда игрок попадал нажав красную кнопку «В бой».

Вид сверху оставили, а управление решили переделать на WASD. Забегая вперед, скажу, что WASD у нас получился «не как у всех». Если обычно при таком виде W это всегда вверх, а S всегда вниз, то у нас все относительно того, куда смотрит персонаж. Такое управление непривычно, но дает больше тактических возможностей и к нему привыкаешь через пару боев.
Геймплей должен был стать более динамичным, поэтому лежачие и сидячие положения персонажа были выкинуты.

Прежней осталась только ключевая фишка -все локации должны основываться на реально существующих в Питере местах.

Проблему отсутствия контента это никак не решало, но значительно сокращало минимально необходимый для старта объем.

Начали переписывать клиент. К лету был готов прототип лобби с рабочим инвентарем. Персонажа пока взяли из action quake (мод для q2, дедушка cs).



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



Была приделана стрельба, пока еще бесшумная и беспламенная, но мобов уже можно было косить очередями, а они научились больно кусаться в ответ.
Алгоритм атаки/выстрела так же был основан на отрезках и проверках на пресечение — брался условный отрезок от стрелка до максимальной дальности текущего оружия и проверялись коллизии. “Живые” объекты тоже обозначались в виде перекрещенных отрезков.

В общем к осени прототип был более-менее готов.



Контент


Тем временем геймдиз времени зря не терял и прочесывал сайты, где продавались готовые 3D-модели, в поисках подходящего нам контента. Ему удалось кое-что насобирать, но этого было недостаточно.
С уменьшением расходов у нас появились кое-какие свободные финансы и решили нанимать фрилансеров.
Первым заказом был новый персонаж с анимацией. И первый блин, как водится, вышел комом — взяв аванс исполнитель так и не показал ничего внятного к оговоренному сроку. Знали бы мы тогда с какими сказочными персонажами нам еще предстояло поработать…

К концу года мы нашли исполнителей, которые сделали нам персонажа и проанимировали его, но тут всплыла новая проблема. Дело в том что из 3DsMax, в котором была выполнена работа, на тот момент не существовало прямого экспорта анимации в three.js, поэтому пришлось использовать как промежуточный формат md2, который уже перегонялся в нативный json через онлайн-конвертор.

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



Экспортировать как-то по-другому не удалось получался запредельный объем с которым браузер просто не справлялся, выдавая «опаньки». Тогда мы не были морально готовы все опять переделывать, да и вообще не было еще четкого представления как переделывать, поэтому решили пока оставить как есть.

2013 год. Первые результаты


С 3D-моделлерами окружения нам тоже не везло. Сначала взялись за новое лобби, удалось сделать его с горем пополам — только со второго фрилансера.



Первая локация


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

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

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

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

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



Приложив титанические усилия, карту все-таки собрали.

Звук


Параллельно работе над картой шла работа со звуком. Была приобретена пара треков для лобби и боевого режима.
У автора этих треков заказали прочие игровые звуки: выстрелы, шаги и тому подобное.

Фоновую музыку просто повесили на тег audio, а игровые звуки реализовали через новомодное web audio api, которое на тот момент было еще сыровато и поддерживалось только в хроме и его родственниках, но уже предоставляло богатые возможности, в частности, позволяло позиционировать звук в пространстве в соответствии с положением его источника в 3D-сцене.

Преальфа


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



По итогам преальфы были сделаны следующие выводы


1. Систему анимации надо менять;
2. Система препятствий, построенная на стоп-отрезках, работает плохо: игроки зацепляются за малозаметные препятствия;
3. Сама по себе ручная обводка трудозатратна и не полностью соответствует в случае со сложными геометриями;
4. Отсутствует масштабируемость — приходится перебирать все имеющиеся на карте стоп-отрезки;
5. Террейн-мозаика из плейнов просаживает фпс, да и стыки видны повсюду;
6. Полное серверсайд движение персонажа на реальном интернете работает не так хорошо, как хотелось бы — визуально видна задержка между нажатием кнопки и реакцией игры;
7. Графон в целом «ниочень».

Итог


Стало понятно, что переделать нужно почти все. Но отрицательный результат — тоже результат. Главным образом все это дало хоть какой-то опыт и понимание, как делать не надо.

Следующие полтора года мы перерабатывали нашу игру, но об этом уже в следующей статье.

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

Скриншот из лобби 2015 г:



Скриншот с карты «Стрелка Васильевского острова» 2015г:



Спасибо за внимание.
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 23

    +3
    Вы молодцы. Да еще какие.
      0
      Неплохо, ребята!
        0
        Прикольно. Спасибо. Жду проду.
          +1
          Спасибо за рассказ!
          Знали бы мы тогда с какими сказочными персонажами нам еще предстояло поработать…
          Не хочется наступать на те же самые грабли — было бы интересно услышать какие-нибудь подробности об этом опыте (хочется знать, на что обращать внимание, когда следует насторожиться, как отличить хорошего исполнителя и т.п)
            +1
            В следующей статье, постараемся подробнее описать эти случаи.
            +1
            А на какие средства вы существовали все это время? Засчет наработанных клиентов по поддержке сайтов?
              0
              Да на них, плюс иногда сайты делали.
              –4
              Статья интересная НО…

              патчфайдинг для персонажа

              Поиск патчей? Wat?
              pathfinding -> path + finding (читается как «пас» а не «патч») — путь: pathfinding поиск пути.

              Террейн

              Сколько можно уже коверкать «ландшафт»?

              Вот именно из-за таких ляпов статья выглядит как попытка на быдлокодить и не воспринимается серьзно независимо от качества самого продукта.
                –1
                Да, давайте минусуйте, «Террейн» как и «терраин» расползается как зараза.

                патч файндинг это что? новая зараза как и «плеин»?

                Минусующие, хотя бы аргументируйте свою позицию.

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

                  0
                  Исправил на патфайдинг, так по гуглу вроде правильнее, согласен что патч здесь не уместен, но общий смысл предложения был ясен.
                  Насчет «заразы» не соглашусь, это все же профессиональный сленг, который есть в каждой профессии.
                    +1
                    Тогда что такое пат?
                    чем вам не нравится «поиск пути», «алгоритм поиска пути»…

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

                    Сами прочитайте:
                    Все лето ушло на боевую систему. WASD-управление прикрутили поверх старой системы мышко-указательного управления: поиск пути для персонажа был отключен, а точка клика эмулирована перед персонажем на определенном удалении. Если игрок перемещал мышь или персонаж достигал расчетных координат, то точка рассчитывалась заново. Поиск пути же пригодился для мобов. Их модели тоже были взяты из какого-то q2 мода. Было написано примитивное AI, гонявшееся за игроком, ну а всю основную работу по достижению цели делала система поиска пути. Несмотря на всю примитивность, наблюдение за этой искусственной жизнью завораживало.


                    Тоже самое с ландшафтом.

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

                    p.s.: сам не без греха с терминологией, однако стараюсь исправлять где замечаю за собой такое, просто в данном случае всё впечатление от статьи смазанное получилось.
                      +1
                      Русский аналог — сусанинг. От Сусанин. Поиск пути.
                  0
                  Извиняюсь за не скромный вопрос, а демо где можно посмотреть?
                  Признаюсь честно, всю статью не читал, читал лишь интересные куски, но ссылку не нашел.
                    0
                    Тут ссылки размещать не очень красиво, что бы найти нас Вконтакте в поиск вбей WasteWater
                      0
                      ВКонтакте через поиск ничего не находит.
                      Через поиск Google нашлось вот это. А под ним прямая ссылка на приложение.
                    0
                    Совершенно не понимаю мыслей и настроя людей, которые пытаются при таком стартовом капитале(опыт, деньги, команда) пытаться делать такие крупные проекты. Ведь если было желание и немного свободного времени, то за это время можно было сделать кучу прототипов, более простых, а некоторые из них довести до ума и даже что-то заработать. В 2012 году и конкуренция была меньше и в общем-то много что дешевле было.

                    Я говорю с позиций человека, которому так же интересно было погрузиться в геймдев в свое время. Да и сейчас еще только в начале нахожусь. Но никогда даже мыслей не было попытаться начать с такого монстра. Я даже не очень могу понять смысла разработки с точки зрения образовательного подхода. Просто не знаю, выходит ли сейчас что-то вменяемое на подобных рельсах.
                      0
                      А где вы там монстра то увидели?
                      Обычный шутер. Без наворотов. Для web.
                      Разве что стек не обычный, до недавнего времени, но сейчас многие пытаются на js игры делать.
                      –1
                      Почему не Unity? Мазохизм?
                        +2
                        Во первых, Unity далеко не панацея.
                        Мне вот он не нравится и работать с ним неудобно.
                        А во вторых, вы на даты в статье смотрели?
                        Unity можно считать приемлемым только после выхода 5-й версии, в которой они убрали всякие «странные» ограничения free версии.
                        А так как на проектах кросплатформенность не всегда нужна, то и бороться с глюками unity только ради web не всегда оправданно.
                          0
                          Не подходил Unity для того что мы хотели сделать. Плагин ограничивал
                            0
                            Чем ограничивал? Уже не одна ммо и сетевой шутер выпущены на Unity. Похоже, что ваша статья о том, как вместо того, чтобы делать игру, мы делаете движок. История не нова
                              0
                              50 мегабайт, получались бы маленькие и однообразные карты. А у нас Питерские локации около гектара.
                              Про сетевые шутеры я знаю, а вот про ммобраузерное на юнити как то упустил.
                          0
                          Rust, Crowfall, Battlestar Galactica Online

                          Only users with full accounts can post comments. Log in, please.