Новая Игра Со Старой Атмосферой На Three.js

Есть много любителей старых игр.

И они не прочь пролить скупую ностальгическую слезу и нет-нет, но сыграть в «Арканоид», «Пак-Мэн» или «Принца Персии», типа двадцать, тридцать, сорок или — вставьте нужное число — лет назад. В этом им могут помочь DOS-бокс и эмуляторы.

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



Новая игра со старой атмосферой на Three.js

Я подумал, а почему бы не создать новую игру в подобном стиле? Да, существуют различные ремейки и клоны.

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

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

А что, если представить, какой была бы новая часть старой игры, если бы она вышла после последней в серии? Я решил создать его.

Я взял 2D-платформер и добавил 3D-графику, сохранив классический вид сбоку.

Я построил новые лабиринты, придумал новые квесты, ввел задания и реализовал слоты для инвентаря.

Немного разнообразил ощущение пространства, добавив повороты на 90 градусов.

Возможно, в те давние времена, до тотального перехода игр в 3D с тремя степенями свободы, могло бы выйти нечто подобное.

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

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

Поэтому все это не будет сильно нагружать браузер.

Для вывода 3D-графики я выбрал свою любимую библиотеку Three.js (WebGL) с собственной оберткой.

Никакие другие библиотеки не используются, а код написан на чистом JavaScript.



Three.js и проблемы, с которыми я столкнулся

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

В случае со скриптовой библиотекой Three.js разработчики радуют нас обновлениями с сумасшедшей частотой — примерно раз в месяц.

На момент написания последней версии была номер 106. Казалось бы, это здорово.

(Нет.) Почему никто даже не думает об обратной совместимости? Когда разработчики Three.js переименовали свойство окружающего материала, я понял: «Хьюстон, у нас проблемы» .

Хорошо, допустим, мне не составило труда изменить слово «ambient» на «color» во всем моем коде с помощью поиска и замены.

Но когда устранили способность источника света создавать тень без самого освещения, я понял, что теперь посадка "Орла" существует реальная опасность, и база "Спокойствие" начинает медленно превращаться в базу «Бешенство» .

Однако, как оказалось позже, это было не так уж и плохо.

Дело в том, что в моей игре помимо запеченного света используется еще и динамическое освещение.

Количество динамических источников в 3D-сцене сильно влияет на производительность.



Новая игра со старой атмосферой на Three.js

Я включил в настройках игры выбор количества источников - от 1 до 7. И в зависимости от мощности видеокарты можно пробовать разные значения.

Также имеется массив, содержащий координаты и характеристики каждого источника — интенсивность, цвет и так далее.

Это работает следующим образом.

При перемещении по игровому миру в определенном квадрате вокруг игрока загорается указанное в настройках количество источников света с заданными характеристиками.

То есть источники света как будто следуют за игроком (вокруг него) в облаке.

Итак, Хьюстон, в чем наша проблема? Я докладываю.



Проблема номер 1: тени

Источники света создают тени.

Я заметил, что тени от точечного освещения потребляют гораздо больше ресурсов, чем тени от точечного освещения.

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

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

Это идеально подходит для моей игры и, как оказалось, действительно существенно экономит вычислительные мощности.



Новая игра со старой атмосферой на Three.js

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

Но вот в чем проблема: начиная с версии Three.js r73, направленный источник света больше не может только отбрасывать тень, он теперь всегда обеспечивает еще и освещение.

И свет от него распространяется внутри области, так же, как и тень.

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

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

Использование «справедливого» освещения с тенями во всех направлениях фатально влияет на производительность игры.

И они удалили нужное мне свойство .

onlyShadow направленного источника света просто потому, что так захотел автор движка.



Проблема номер 2: имена свойств

Я решил, что лучше остановиться на версии r71, где необходимое мне свойство освещения еще присутствовало.

Почему тогда не р72? Ведь свойство пропало только в версии r73. Потому что я уже написал довольно много кода для загрузки 3D-моделей, анимации и физики для версии r71. А в версии r72 изменилось большое количество названий свойств: типа -shadowMap сталshadow.map и т.д. В общем, переименовывать все это тоже не хотелось.

И разница между одной версией невелика.

Итак, мы остаёмся на версии r71.

Проблема номер 3: запекание теней



Новая игра со старой атмосферой на Three.js

Запеченный свет также выглядит по-разному в разных версиях движка.

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

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

Это еще одна причина выбрать версию r71.

Новая игра со старой атмосферой на Three.js

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

Отлично.

Направленный источник света создает только тень.

Я умею запекать и загружать тени в сборку на версии r71. И вот – самая главная засада.

Персонажи.



Проблема номер 4: скелетная анимация

Это то, с чем я боролся очень долго.

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



Новая игра со старой атмосферой на Three.js

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

Однако, хотя новые версии Three.js используют формат gltf 2.0, моя поддерживает только 1.0. Казалось бы, в чем проблема, ну конвертируй в 1.0 и заливай.

Оказалось, что не все так просто.

Судя по всему, существует несколько вариаций формата gltf 1.0. Мне нужен был такой, где помимо основного файла модели должно быть еще два файла с расширением *.

glsl. Но даже в этом случае формат основного файла может отличаться.

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

Мне также не удалось обновить старую версию Three.js для поддержки gltf 2.0: слишком глубоко эта поддержка завязана в коде, укоренена в математике, реализована по-разному в разных версиях движка.

В общем, как-то не получилось потренироваться с gltf. Я попробовал использовать формат .

dae для 3D-моделей.

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

Также были проблемы с текстурами.

Он хорошо работал с форматом .

md2. Персонаж сразу отобразился и все анимации работали корректно.

Но, насколько я понимаю, md2 — это формат модели для Quake 2 и кто-то реализовал его поддержку в Three.js просто ради интереса.

Я не смог найти, где взять модели в этом формате, а тем более спроектировать и сохранить в нем своего персонажа.

Я пробовал несколько других форматов.

Но то ли не было загрузчика для Three.js, то ли в них не было программ для создания сохранения своего персонажа, то ли они вообще не поддерживали скелетную анимацию.

Пришло время переименовать базу «Безумие» в базу «Отчаяние».

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

Но мне впервые не удалось повторить процесс преобразования персонажа из файла примера, поставляемого с Three.js, из исходного формата .

blend в .

json в 3D-редакторе Blender. Анимации были испорчены и вели себя как-то хаотично, да и десяток вариаций экспортера из Blender в json, каждая из них работала некорректно.

Более того, я также опробовал их на нескольких версиях Blender. Сам JSONLoader, то есть загрузчик модели в формате json, теперь удален из Three.js. Я решил поискать какая версия она больше не поддерживается, чтобы взять ее и образец 3D модели не из моей версии, а из той, где она еще была доступна.

Это оказался r88. И, о чудо! Мне удалось воспроизвести экспорт тестовой модели в r71 и в игре всё, включая анимацию персонажей, работало нормально! «Орел» благополучно приземлился на Луну.

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

Тут меня ждал облом.

Анимация, которую я отредактировал, вообще не хотела работать в игре.

Персонаж застыл в исходном положении.

Хотя другие анимации работали без проблем.

Но это что-то.

То есть теперь проблема заключается в моем незнании некоторых нюансов редактирования анимации.

Тогда я подумал — а что если спросить автора этого примера, как он это сделал.

Но докопаться до автора оказалось непросто.

У него нет личных контактов на Github. Поиск по нику и еще паре параметров привел его в его Твиттер, но личные сообщения там были закрыты.

Но оттуда я узнал, что он профессор какого-то американского университета, и зашёл на сайт этого учебного заведения.

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

Затем я вернулся на Github и просмотрел все его репозитории.

Здесь меня ждал успех.

Как я и ожидал, его пример хранился в отдельном репозитории.

И не просто копия того, что я уже видел в примерах Three.js, а пример, заботливо снабженный инструкциями (видимо, для студентов).

Скачал архив и по инструкции все повторил.

Ура! Это маленький шаг для человечества, но гигантский скачок для одного человека и его игры!

Нет проблем, Хьюстон!



Новая игра со старой атмосферой на Three.js

Теперь я понимаю, что если я буду придерживаться этого формата, этих инструкций и этих версий Three.js, JSONLoader и Blender и делать все единообразно, то я смогу создать и загрузить в браузерную игру любого своего персонажа.

Еще одним плюсом было то, что, несмотря на использование старой версии движка, вы можете использовать новейшую версию 3D-редактора Blender и создавать любых персонажей с анимацией.

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

Да, я заметил еще одну проблему с новой версией Three.js: во время игры при прокрутке экрана почему-то постоянные зависания.

И это не связано с повышенным потреблением ресурсов – процессор и видеокарта загружены не на 100%.

А в старом r71 такого безобразия нет. Теперь осталось только создать персонажей с анимацией для игры в 3D-редакторе.

И, конечно же, геометрия уровней.

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

Но пока я скомпилировал только бесплатную демо-версию на Webkit и выложил ее в популярные магазины приложений.



Немного об игре

Имя.

Я назвал игру «Перси Ланкастер».

Здесь все очевидно: «Я художник, и я это вижу так».

Как создавалась графика .

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

Затем я смоделировал плоскости полов и потолков.

Это создало коридор, по которому игрок мог ходить.

Разнообразили локации разными текстурами.



Новая игра со старой атмосферой на Three.js

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

Это лишь общий вид коридора.

Я решил создать пересекающиеся коридоры.

При повороте достраивается одна стена другого коридора, поворачивается вся конструкция, а затем удаляется стена первого коридора.

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



Новая игра со старой атмосферой на Three.js

На самом деле со статичной графикой проблем нет; они легко экспортируются в json из любого 3D-редактора.

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

Производительность.

При разрешении экрана HD, то есть 1280х720, моя не очень мощная видеокарта GT-730 загружена примерно на 35-40%, а процессор Xeon E5440 примерно на 30%.

Думаю, это более чем приемлемый результат. ОПЕРАЦИОННЫЕ СИСТЕМЫ.

На данный момент демо-версия доступна только для Windows в виде сборки Webkit. В будущем планирую запустить браузерную версию.

Я сталкивался с тем, что не во всех браузерах прокрутка экрана плавная.

Мне все еще нужно поработать над управлением и вызовом функции вывода графики.

Тем временем я остановился на версии Webkit 26.0. Он мало весит и все на нем работает отлично.

Звук.

Звуки частично взяты из бесплатных библиотек, частично сгенерированы.

В общем, они по-прежнему созданы «чтобы быть».

Пока я особо с ними не заморачивался.

Видео.

Полный демо-уровень.



Планы

Я планирую пойти на краудфандинг и на собранные деньги нанять 3D-моделлера, который создаст для него нормального персонажа и анимации.

Всё-таки графика не моё.

Но теперь я знаю, как внедрить персонажа в свою игру.

Также я планирую запустить версию браузера для последних версий Chrome и Firefox. Открою вам секрет, мне даже удалось запустить игру на MS Edge, но почему-то пропали объекты, на которые были наложены запеченные текстуры теней, я пока не разобрался.

Далее я начну отладку для браузеров на Linux и Android, а если получу у кого-то на тестирование устройства Apple, то и для браузеров на iOS и MacOS. В далёком будущем — написание собственной библиотеки для работы с WebGL, типа Three.js: мне не нравится, что они вдруг переименовывают свойства и удаляют нужный мне функционал.

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



Новая игра со старой атмосферой на Three.js

Теги: #игры #Разработка игр #JavaScript #webgl #threejs #canvas #nw.js #веб-программирование

Вместе с данным постом часто просматривают: