Я продолжаю работу над своей браузерной игрой про пиратов на Three.js. Пришло время добавить торговлю. Я подумал, раз у нас тут век пиратов, то и в политическом смысле обстановка должна быть весьма фривольной, то есть, без всякой богомерзкой демократии. А чего стесняться? Заходим в порт, а там нам, пиратам, сразу же предлагают приобрести пушечные ядра и выполнить заказы на транспортировку трупов оппозиционеров и доставку рабов. Еще можно отвезти ром на Тортугу или подбросить губернаторскую дочь на вечеринку на Райский остров. Или тайно эвакуировать беглого губернатора за хорошую плату. Действительно, для подобных дел правительству идеально использовать пиратов. В конце концов, рабы сами себе билет на регулярный рейс не купят, а оппозиционеры сами себя не похоронят. А проблему решать надо... Короче говоря, перевозить древесину и шелк, как в обычных играх - это скучно. Пусть будут этакие «девяностые», но в эпоху пиратов. Пираты выполняют не совсем законные задания правительства, а последнее закрывает глаза на их не совсем законные методы обогащения.

Какие бизнесмены, такой и бизнес...
Какие бизнесмены, такой и бизнес...

В игре появилась местная газета. Для пиратов подписка бесплатная. Газета будет содержать различные игровые оповещения.

Интересный нюанс

В предложениях работы в портах появляются заявки по перевозке с одного острова на другой неких провокаторов. Они нужны для создания в игре динамических событий. Через некоторое время после их прибытия в тот или иной порт для нас там появятся новые задания. Только не отправляйте их на один и тот же остров одновременно. А информацию о том, что где-то произошло то или иное событие, можно узнать в газете «The Pirate Times». Визуально - изменит цвет иконка сообщение. Можно открыть и почитать. Ну и направиться за заданием в нужный порт.  

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

Еще одна чрезвычайно важная новость. «Черная жемчужина» превратилась в «Черную устрицу». Да. Так, определенно, лучше. Потому что я художник, я так вижу.

«Наша команда»

О нашем продукте я рассказал. Теперь - о нашей дружной команде, о наших ценностях и о корпоративном духе... Ладно, шучу. Игру я делаю в одиночку. А для того, чтобы не терять мотивацию, в эти жаркие дни я иногда выходил работать на побережье Финского залива. И, надо сказать, тишина и гладь, а иногда и шум моря неплохо мотивировали к написанию игры про морских разбойников. Вот мой офис.

Наш офис и корпоративные ценности
Наш офис и корпоративные ценности

И тут меня понесло...

Когда я делаю игру, то, как правило, все начинается с атмосферы. Вот, кто-то вдохновляется придуманной им историей и создает визуальную новеллу, кто-то - главным героем и пишет игру про супермена, кто-то - коммерческими соображениями и выдает кликер на мобилку. А я вдохновляюсь атмосферой. Возможно, это глупо, но атмосфера в игре для меня - самое главное. Я, например, не люблю шутеры, однако, если в нем будет какая-то невероятно красивая локация, интересный живой мир, то я, скорее всего, буду очарован этой игрой и стану в нее играть. И это касается всех жанров. И наоборот, если в моих любимых автогонках будет некрасивая графика, неприятное управление или что-то еще, что мне не понравится, то я в это точно играть не буду, несмотря на то, что данный жанр мне в принципе близок. Так вот, игра про пиратов началась с того, что я собрал простую сцену, представляющую собой воду, небо и неподвижный кораблик. Мне понравилось, как это выглядит. И только потом я уже стал думать, как сделать из этого игру. «Корабль - это свобода. Смекаешь?» Если корабль - то пираты, острова, миссии, ну вы поняли... Идеи приходили по мере работы. Понимаю, что это неправильно, но я это делаю для себя и, возможно, для тех, кому это тоже понравится. О диздоке даже не спрашивайте: я еще понятия не имею, какой будет следующая, четвертая, из восьми миссий.

Еще об оптимизации

Теперь - о том, какие еще моменты мне удалось оптимизировать. Я начал эту тему в своей предыдущей статье. Продолжу.

Отражения

В игре, как вы понимаете, много воды. В прямом смысле. Ну, нет, вот не настоящей воды, а там - текстура, шейдеры, ладно... Собственно, это основная поверхность всех локаций. А в воде отражается все, что находится на суше. По сути, в воде еще раз рендерится вся сцена. Я подумал, а возможно ли отражать не всю сцену, а только отдельные объекты? Честно говоря, я не знал о слоях three.js. На информацию о них меня навел добрый человек на профильном канале в одном мессенджере, где я искал ответ на свой вопрос. Принцип очень простой:

//основная камера видит все слои до 1 (0, 1)
camera.layers.enable(1);

//камера зеркала видит только слой 1
mirrorCamera.layers.set(1);

//объект 1 виден во всех слоях до 1 (0, 1),
//то есть, в основной камере и в зеркальной
object1.layers.enable(1); 

//объект 2 виден только в слое 0,
//то есть, виден в основной камере, но не виден в отражении
object2.layers.set(0);

Таким образом можно исключить отражение в воде отдельных объектов. Более того, можно даже оперировать отдельными мешами одного объекта. Например, незачем отражать разные мелочи, которые за рябью воды все равно не видно. Либо они вообще находятся внутри модели и их тоже совершенно незачем обрабатывать в «зеркальной» камере. Свойство layers имеется как в корневом объекте, так и в каждом его меше.

В воде не отражаются некоторые канаты корабля
В воде не отражаются некоторые канаты корабля

А для того, чтобы не перебирать все меши всех объектов вручную с целью создать или не создавать их отражения в воде, я решил прямо в 3D-редакторе добавлять в имена мешей управляющие символы. Например, один из мешей корабля имеет имя «mrd_flo». Здесь «flo» - это пол (от floor), просто произвольное имя, а перед ним идет отделенный символом подчеркивания ряд управляющих символов. Например, «m» (mirror) - убрать отражения в зеркалах, «r» (receive shadows) - принимать тени: на пол должны отбрасываться тени от других объектов, «d» (double side) - двусторонний: этот пол должен быть виден как сверху, с палубы, так и снизу, из каюты. Другой меш имеет имя «md_wire». Здесь «wire» - просто имя (канат), «md» - не отражается в воде и материал его двусторонний. При загрузке каждой 3D-модели происходит перебор имен мешей и последним задаются все требуемые свойства.

Столкновение ядер со стенами

В предыдущей версии игры при стрельбе проверялись столкновения ядер с теми объектами, которые они могут поразить. Это - другие корабли, пушки, различные цели на берегу. Собственно, ранее я реализовал полезную возможность проверять столкновения ядра не со всеми целями, которые присутствуют на сцене, а только с теми, которые находятся вблизи от летящего ядра, перестраивая список ближайших объектов во время полета. Теперь несложно в этот список добавить и коллайдеры окружающих скал. Всего их в локации очень много, но ближайших к ядру в каждый момент времени окажется 2-3. Это не критично для производительности. Зато теперь ядра не пролетают сквозь скалы.

Сохранение игры

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

Геймпад

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

Разные мелочи 

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

Удивительные открытия

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

1. Фон для Safari.

В Apple Safari канвасу, на который выводится 3D графика, нужно задать какой-нибудь цвет фона:

scene.background=new THREE.Color(0x000000);

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

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

После загрузки текстуры Three.js заменяет материал, к которому, собственно, прикрепляется текстура. Я долго не мог понять, почему я не могу программно настроить материал по его uuid, если он уже загружен и присутствует в модели. Например, поменять его цвет или яркость или еще что. Вроде бы материал появляется, в нем можно менять значения, а эффекта не видно. Оказалось, я настраивал старый материал, который открепляется как только загружается текстура. А с ней создается новый материал и прикрепляется к модели вместо старого. Решение - изменять свойства материала только после загрузки текстуры.

3. Произвольный порядок следования мешей в сложный объектах

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

object.children[5].material.shininess=0.5;

Оказывается, меш, которому вы захотите задать какой-либо параметр, при очередной загрузке сцены не обязательно окажется с тем же порядковым номером (пять, как в примере). В children 3D-объекта он может стать абсолютно любым. Не знаю, связано ли это с тем, что Three.js подгружает объекты по частям и добавляет их к children, или еще с чем-то, но факт, что иногда (не всегда, даже очень редко) порядок меняется. Решение - искать child по имени, а не по индексу. Соответственно, предварительно при создании модели в редакторе, нужно озаботиться заданием уникального имени каждому мешу. Для парсинга пришлось написать функцию вида:

getObjectChildByName(object, 'meshname').material.shininess=0.5;

Продолжаем плавание

О том, как я буду продвигать игру, я еще особо не думал. Я разместил ее на некоторых сайтах (магазинах), где возможно размещение браузерных игр. Можно собрать исполняемый файл, чтобы разместить его в магазинах, подобных Steam. Больше я пока ничего толкового на эту тему придумать не могу. Впрочем, до релиза еще далеко.

Комментарии (52)


  1. RollingBrock
    02.10.2022 23:41
    +11

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


    1. sergej_pipets
      03.10.2022 15:23

      Примерно так писалась небезизвестная "Elite"...


      1. RollingBrock
        03.10.2022 23:00

        И Dwarf Fortress, и майнкрафт, и много чего ещё, да. Что обнадёживает.


  1. ninJo
    03.10.2022 00:16
    +7

    На ithch.io ещё можно выложить и продвигать игру как инди. Многим нравятся именно инди игры


    1. Kempston Автор
      03.10.2022 00:25
      +2

      Да, на itch я в том числе как раз выложил.


  1. Robastik
    03.10.2022 02:49
    +15

    этакие «девяностые»

    лорда Напального

    Не так уж и много для атмосферы 90-х)

    Если всем персонажам и событиям дать названия современных мемов? Прям вообще всем. И не только отечественных. ЛГБТ-пираты, Slaves Lives Matter, Vessel Model 3, вна Торгугу, - чтобы один сплошной анекдот.


    1. Kempston Автор
      03.10.2022 09:15
      +4

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


    1. matabili1973
      03.10.2022 14:39
      +3

      Ну есть же классика:

      корованы


  1. hunnuh
    03.10.2022 07:01
    -18

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


    1. Kempston Автор
      03.10.2022 09:16
      +16

      А мы ее и не обсуждаем. И еще ни капли ненависти нигде не было.


      1. Wesha
        03.10.2022 20:41
        +3

        И еще ни капли ненависти нигде не было.

        Анекдот советских времён:

        — Будет ли третья мировая война?
        — Да что вы, конечно, не будет. Будет такая борьба за мир, что камня на камне не останется.


        1. tvr
          03.10.2022 21:31
          +3

          Ажно олдскулы свело:))


  1. Kekmefek
    03.10.2022 07:19
    +2

    У меня мечта, сделать многопользовательскую игру типа Порт-Рояль.


    1. marcbook
      03.10.2022 07:58
      +11

      А в ней можно будет грабить корованы?


      1. Kempston Автор
        03.10.2022 09:17
        +1

        Можно. Как только я добавлю другие корабли. Одни из них можно будет грабить, а другие сами будут грабить.

        ps Думал, это комментарий - ко мне.


        1. withkittens
          03.10.2022 11:59
          +5

          Я джва года хочу такую игру!


        1. marcbook
          03.10.2022 19:43
          +1

          Красивое!


      1. ekhaskel
        04.10.2022 12:49

        корованы нельзя. коров нельзя обижать


        1. Wesha
          05.10.2022 05:09
          +1

          Так погонщиков ограбил, а коров распряг и отпустил на волю. Коровы одобряе.


          1. ekhaskel
            05.10.2022 16:59

            А - ну тогда другое дело. Если кОрОваны из коров (а другой смысл слова "кОрОваны" мне в голову не приходит; подумать же о безграмотности пишущего слово "кОрОваны" мне не позволяет врождённая вежливость), и при условии что коровы не пострадают - то тогда, наверное, дело богоугодное.. Но вот одна проблема - игра вроде морская. Я пока не могу придумать, где парусник может повстречаться с коровами в корованах..


            1. tvr
              05.10.2022 17:13

              где парусник может повстречаться с коровами в корованах..

              Морские, они же Стеллеровы коровы.
              Их как раз во времена парусного мореходства всех и пожрали.


              1. ekhaskel
                05.10.2022 17:19

                Согласен. Спасибо за идею. Будем считать что корованы - это стада стеллеровых/морских коров. Осталось придумать как их можно грабить. (всё таки охотиться и грабить не совсем одно и то же)


                1. tvr
                  05.10.2022 17:27

                  Короче — морские кочевники пасут и перегоняют корованы морских коров на новые пастбища/продажу. Тут из тумана набигают пираты и грабят их. А специально обученные косатки (помогающие пасти коров) участвуют в отражении набега пиратов.


            1. SerjV
              05.10.2022 18:37

              другой смысл слова "кОрОваны" мне в голову не приходит; подумать же о безграмотности пишущего слово "кОрОваны" мне не позволяет врождённая вежливость

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


    1. tvr
      03.10.2022 21:47

      У меня мечта, сделать многопользовательскую игру типа Порт-Рояль

      Я тебе трейлер и часть саундтрека принёс, сюжет и реализация за тобой — всё по честному, как у нас, у джентльменов и принято. Слава и сокровища — пополам :))

      P.s. в качестве стартовой композиции/заставки/интро рекомендую классичнейшую весчь:


    1. GrumbaL
      05.10.2022 13:27
      +1

      Есть POTBS, вроде пока "на плаву".


  1. Admz
    03.10.2022 07:59
    +4

    Я думал статья про российскую действительность...


    1. darklord1984
      03.10.2022 11:13
      +1

      И я так же думал.


  1. alex_kag
    03.10.2022 08:28

    Перечитал и не понял, так где можно посмотреть игру?


    1. Kempston Автор
      03.10.2022 09:09

      А вот здесь

      русскоязычная: https://m3d.me/game/sb/h2/?lang=ru

      англоязычная: https://m3d.me/game/sb/h2/


      1. grayking
        03.10.2022 11:49

        У меня при нажатии на кнопку "старт" появляется логотип "13 черепов" на черном фоне. Больше ничего не происходит. Ждал более 10 минут.


        1. Kempston Автор
          03.10.2022 11:50

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


          1. grayking
            03.10.2022 12:00

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


            1. Kempston Автор
              03.10.2022 12:01

              А какой браузер и операционка?


              1. grayking
                03.10.2022 12:06

                Google Chrome, Версия 106.0.5249.91

                Windows10


                1. Kempston Автор
                  03.10.2022 12:19

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


  1. v1000
    03.10.2022 08:33
    +2

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


    1. Kempston Автор
      03.10.2022 09:19
      +2

      Да. Есть такое. Это - от моей низкой квалификации 3D-моделера. Я планирую улучшить модельки чуть позже.


      1. RiSilver
        04.10.2022 22:01
        +1

        Тут скорее проблема не в самих моделях, а в текстурах. Можно оставить лоу поли но добавить детали в текстуры. И кстати да, при ручной раскраске можно обойтись без затрат на свет и тени. В разумных пределах )


        1. Kempston Автор
          04.10.2022 22:35

          Да, согласен. Плюс - запечь тени. Количество полигонов увеличивать не хотелось бы.


  1. Galcifer
    03.10.2022 09:17
    +3

    Очень крутой проект, еще и в одиночку - мое уважение) Отдельный плюсик в карму за проработку последствий, не так часто встречаешь это в играх. Первое, что вспомнил это Ведьмак 3 и Dishonored.


  1. Areek
    03.10.2022 11:32
    +2

    Если не секрет, а для каких целей трупы перевозить надо? Там что, клан некромантов у власти на Острове смерти, что трупы закупают?)

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


    1. Kempston Автор
      03.10.2022 11:53
      +1

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


      1. svob
        03.10.2022 13:22
        +2

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

        Жители экваториальных островов по идее могут использовать некоторые кости в быту или для производства украшений. И в своих мрачных колдовских обрядах.

        А еще трупы иногда использовались как биологическое оружие. Для этого человек должен был умереть от инфекционной болезни.


        1. tvr
          03.10.2022 14:52
          +1

          Между прочим, трупы в свое время бывали и товаром в Европе.

          Да и в Новом Свете тож — см. «Приключения Тома Сойера», глава IX :))


          1. svob
            03.10.2022 14:59

            Вот он - потенциал для развития параллельных линий сюжета!


  1. rqdkmndh
    03.10.2022 21:40

    Очень интересно получилось! В каком формате 3D модели используются?


    1. Kempston Автор
      03.10.2022 22:20

      В json и fbx. В последнее время перехожу на fbx, потому что, в отличии от json там поддерживается light/shadow map, в общем, более, чем один мап на материал. А модельки с запеченным светом и внутренними тенями все-таки выглядят намного лучше. Но сейчас таковых в игре пока не много.

      Однако, fbx дольше разворачивается, видимо, из-за конвертации. Думаю, как это оптимизировать. Возможно - загрузить fbx в некую пустую сцену, взять оттуда json этой модели, но уже со множеством мапов, а потом сохранить... Пока руки до этого еще не дошли.


  1. Ul3ainee
    05.10.2022 17:42

    Можно грабить коровеллы?


    1. Kempston Автор
      05.10.2022 19:25
      +1

      Пока нет. Но обязательно будет можно. Это в ближайших планах.


  1. Mishootk
    05.10.2022 18:41
    +1

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


    1. Kempston Автор
      05.10.2022 19:25

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