Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: HeroWO.js: открытая реализация «Героев 3» для браузера
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III
HeroWO
Хочу представить проект, над которым я работал три года.

Реализация «Героев меча и магии III: Дыхание смерти» для браузера

Сайт: herowo.game (запустить Tutorial)

Код: https://github.com/HeroWO-js
Число строк в проекте - порядка 100 тысяч.
Java​Script: клиент и сервер. PHP: конвертер карт, подготовка данных.

По клику на картинки можно посмотреть короткие ролики, если лень открывать сайт:

  • Готова половина заклинаний, половина интерактивных объектов на карте и практически все существа, артефакты, навыки, городские здания и все города (включая Conflux). Подробный список.
  • Сделан мультиплеер, причем без глобальных блокировок: игроки не только ходят одновременно (как в Age of Wonders), но и битвы проходят параллельно. Блокируются только отдельные объекты (так, что даже один игрок в теории может одновременно контролировать несколько битв).
  • Есть туман войны, причем в расширенном варианте (закрыто, открыт ландшафт, открыто). Это дополнение (открыт ландшафт), как и все остальные отличия от SoD, отключаемы (режим Classic в игровых настройках).
  • Есть простенький AI. Есть сохранение/загрузка.
  • Механизм звуковых эффектов написан, но не все данные найдены/заполнены (чисто техническая работа, как и заполнение препятствий для битв и многие другие подобные задачи).
  • Многие вещи заложены в коде, но не выведены наружу. Например, в битве могут участвовать неограниченное число сторон (как в Age of Wonders), на карте может быть сколько угодно уровней (хоть 3 как в AoW, хоть 5, хоть 10), есть запись реплеев (но нет проигрывания) и режим наблюдателя (observer, но пока отражаются только движения экрана карты и нет полезных кнопок, например, для отключения слежения). Вообще, движок модульный, и в перспективе позволяет вместо модуля «Героев 3» подключить модуль AoW или Disciples, с сохранением большей части функционала.
  • Многое сейчас запрограммировано неоптимально, из-за чего имеем чрезмерное потребление памяти и подлагивания. В особенности на это влияет размер карты; S-M, иногда L играются терпимо.
В рамках проекта был создан, опять-таки с нуля, собственный парсер и компилятор .h3m на PHP: h3m2json, с оглядкой на код h3mlib, который мне ни запустить, ни скомпилировать не удалось. h3m2json успешно конвертирует все 159 карт версии Complete.

Модификации

Актуальная версия «Введения в модификации»: https://forum.herowo.net/t/topic/47

Самая сильная часть движка - расширяемость. JavaScript был выбран как альтернатива C++/Java, на которых написаны другие проекты (VCMI, fheroes2). Используемый фреймворк (Sqimitive.js) позволяет модифицировать абсолютно все - к примеру, в нем не существует методов (любой метод - это потенциальное событие, на которое можно подписаться) и закрытых полей классов.

Но очень многие вещи не требуют программирования вообще. Вот некоторые примеры.

Система эффектов

В движке определено более 150 типов значений, влияющих на игровые механики, как то (в скобках - использование в SoD):
  • canCombat - возможность проведения битвы в данной точке (Sanctuary)
  • creature_attackAround - число клеток вокруг существа в битве, которые получают повреждения (Hydra)
  • creature_spellEvade - шанс избежать направленного заклинания (Dwarf)
  • hero_actionCost - цена движения по карте для героя (различные типы земли и дорог)
  • hero_experienceGain - мультипликатор получаемого опыта (навык Learning)
  • hero_walkTerrain - типы земли, через которые герой может пройти (лошадь, корабль)
  • hireFree - существа, которые присоединяются к герою бесплатно при посещении им жилища (первоуровневые жилища)
  • randomRumors - список слухов для таверны
  • town_spellCount - число заклинаний для города (Mage Guild, Library)
  • combatCasts - сколько раз герой может колдовать в битве за один раунд
  • creature_canControl - запрет на контроль существа в битве (военные машины, башни)
  • bonus_artifacts - список артефактов, получаемых в результате события (по таймеру, при перемещении)
  • ownable_shroud - число клеток, раскрываемых на карте вокруг шахт и других объектов, кроме городов и героев
  • quest_garrison - существа, с которыми герою предстоит биться при посещении объекта на карте (банки и жилища)
  • worldBonusChances - шансы возможных мировых бонусов (Week/Month of, Plague)
Эффект - это набор селекторов и модификаторов. Селекторы, в том числе тип (выше), задают условия применимости модификаторов. Селекторов сейчас порядка 70 штук, как то:
  • ifPlayer - номер игрока, к которому применяется эффект (Armageddon's Blade).
  • isEnemy - меняет смысл ifPlayer: номер игрока, для врагов которого применяется эффект.
  • ifZ - место происходящего события на карте (1 если подземелье).
  • ifDateMonth - номер месяца в игровой дате (timed event).
  • maxCombats - ограничитель эффекта числом битв, в котором участвовал герой (Foutain of Fortune).
  • whileOwnedPlayer - ограничитель: удаляет эффект, если определенный игрок перестает владеть объектом (доход с шахт).
  • ifGarrisoned - применяется только если данный герой находится в гарнизоне данного города (ограничивает возможность побега).
  • ifSpellLevel - проверяет уровень накладываемого заклинания (иммунитеты драконов).
  • ifRoad - событие происходит на клетке с дорогой определенного типа (расчет стоимости передвижений).
  • ifCreatureUndead - существо в битве является или не является Undead (Holy Word).
  • ifGrantedMin - сколько раз данный объект на карте уже был успешно посещен (Warrior's Tomb).
Для наглядности можно открыть herowo.io - это сайт для тестирования модов; под игровым экраном будет область с кнопкой Copy effects. В ней показаны эффекты, недавно созданные в ответ на игровые события.

Например, в поле ввода можно вставить такой эффект и нажать Create:

Код
{"priority": 344, "target": 47, "ifWorldBonus": 3, "modifier": [11, 10.0]}
  • target: 47 обозначает hero_actionCost. Эффект применяется, только если запрошено значение для этого типа.
  • ifWorldBonus: 3 срабатывает только, если в игре в данный момент действует состояние Plague.
  • modifier: [11, 10.0] читается так: при совпадающих селекторах (target и ifWorldBonus) изменить значение оператором 11 (relative, т.е. умножение) на величину 10.0 (т.е. на 1000%).
В результате, при наличии такого эффекта в мире, во время недели чумы все герои начинают передвигаться в 10 раз медленнее.

Можно добавить еще какой-нибудь селектор, например, "не применять к AI":

Код
{"priority": 344, "target": 47, "ifWorldBonus": 3, "modifier": [11, 10.0], "ifPlayerController": "human"}

А таким эффектом можно увеличить шанс возникновения чумы и ее силу:

Код
{"target": 154, "modifier": [16, {"3,PLAGUE,0.1": 100}], "priority": 500}

Правда, в HeroWO мировые бонусы определяются раз в день, а не раз в неделю, поэтому если мы не хотим, чтобы 6 дней в неделю из 7 был чума, нужно добавить селектор (день 1 = понедельник, неделя 1 = первая неделя месяца):

Код
{"target": 154, "modifier": [16, {"3,PLAGUE,0.5": 100}], "priority": 500, "ifDateDay": 1, "ifDateWeek": 1}



Вот пример поинтереснее, назовем его артефактом Hand of Midas:

Код
{"target": 146, "modifier": [17, "exp500", "exp1000", "exp1500"], "ifBonusObjectClass": 944, "priority": 10000}
  • target: 146 = quest_choices. Это значение вычисляется при взаимодействии с большинством объектов на карте. Результатом является список меток, из которых игрок может выбрать желаемое действие.
  • modifier - оператор 17 = diff; исключает из значения перечисленные элементы.
  • ifBonusObjectClass - тип объекта на карте (аналог class+subclass в OBJECTS.TXT). 944 = Treasure Chest.
  • priority задает порядок применения эффекта к финальному значению. Большое значение заставляет его применяться после стандартных.
Treasure Chest, он же сундук с сокровищами, ]стандартно имеет такие эффекты:

Код
    array_fill_keys($c_treasureChest, [
      ['quest_chances', $chances('ge500/32 ge1000/32 ge1500/31 chArtT/5')],
    ]),

    'ge500'     => [['quest_choices', [$append, 'gold1000', 'exp500']]],
    'ge1000'    => [['quest_choices', [$append, 'gold1500', 'exp1000']]],
    'ge1500'    => [['quest_choices', [$append, 'gold2000', 'exp1500']]],

Читается это так: при встрече с объектом класса treasureChest, бросить кубик с шансами: по 32% на исходы ge500 и ge1000, 31% на ge1500 и 5% на chArtT. В свою очередь, первые три дают игроку выбор между типами gold1000/1500/2000 и exp500/1000/1500. Описания этих типов, как и chArtT, для простоты я здесь приводить не буду, они есть по ссылке выше.

Так вот, наш эффект применяется после стандартных quest_choices, так что в результате вычисленное значение никогда не будет содержать exp500/1000/1500. Игрок будет всегда получать либо золото (без возможности выбрать опыт), либо артефакт.

Как вариант, можно было бы перекрыть не quest_choices, а quest_chances, получая из всех сундуков всегда только артефакты (или что-то другое, например, существ - как это сделано для Pandora's Box).

Банк данных

Банк данных HeroWO, по-заморски "databank" - хранилище независимых от карты данных. В основном получаются из TXT-файлов SoD (или модифицированных). Однако карта может менять их произвольно (в отличие от SoD, где допускается изменение только некоторых вещей - например, параметров героя, но не здания).

Например, можно добавить новое здание City Lights к Castle, которое, будучи построенным, будет раскрывать по 1 дополнительной клетке вокруг шахт и других объектов. Для начала добьемся нужного эффекта добавив, гм, эффект:

Код
{"target": 137, "modifier": 1}

137 = ownable_shroud, а 1 - это короткая форма записи modifier: [5, +1], где 5 = delta, то есть сложение результата с числом.

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

Добавим здание в банк данных. Для этого в папке с картой в формате HeroWO (это набор JSON-файлов, в том числе map.json) создадим папку databank, а в ней файл buildings.json с таким содержимым:

Код
[
  [
    {
      "-1": {
        "name": "City Lights",
        "description": "Increases scouting radius around mines and dwellings that you own.",
        "cost_gold": 1000,
        "cost_wood": 5,
        "cost_ore": 5,
        "require": [2],
        "town": [0],
        "image": [
          ["HALLTOWR", 0, 26],
          "TBTWHOLY",
          "TOTHOLYA",
          [], [],
          0, 0,
          50,
          "BOTGRAIL",
          false, false, false, false, false, false, false
        ],
        "effects": [false,false,false,true,false,false,false,false,false,false,false,false,false
,false,false,false,false,false,false,false,false,137,false,false,false,false,fal
s
e,false,false,false,2,false,false,false,false,false,false,false,false,false,fals
e
,false,false,false,false,false,false,false,false,false,false,false,false,false,f
a
lse,false,false,false,false,false,false,false,false,false,false,false,false,fals
e
,false,false,false,false,false,false,false,false,false,false,false,false,false,f
a
lse,false,false,false,false,false,false,false,false,false,false,false,false,fals
e
,false,false,false,false,false,false,false,false,false,false,false,false,false,f
a
lse,false,false,false,false,false,false,false,false,false,false,false,false,fals
e
,false,false,false,false,false,false]
      }
    }
  ]
]
  • "-1" - внутренний номер добавляемого объекта; начинается с -1 и растет вниз. Если 0 или выше, то вместо добавления заменяет стандартный объект.
  • require: [2] задает требования к постройкам. 2 = cityHall, то есть построить наш City Lights можно будет только при наличии предпоследнего улучшения для магистрата.
  • town: [0] ограничивает здание определенным типом города. 0 = Castle.
  • image - сложное поле, задает картинки для городского ландшафта, окна Hall и диалогов. Так как подходящей картинки у нас нет, указываем данные Skyship из Tower.
  • effects - запакованные эффекты, которые применяются к игроку, у которого есть это здание. Это самое важное для нас поле; его значение можно получить по кнопке Embed, но есть одна тонкость.


Тонкость в том, что запакованный эффект на самом деле задан так:

Код
{"target": 137, "modifier": 1, "ifPlayer": true}

Селектор ifPlayer имеет особое значение true; движок заменяет его на номер игрока, у которого есть постройка. Такой трюк работает со многими селекторами (например, ifObject = конкретный объект на карте, ifX = точка на карте), так что, например, наш Hand of Midas можно было бы прописать в эффектах артефакта, задав селектору ifObject значение true, что читается как "для героя-владельца артефакта".

Такой эффект будет давать 1 клетку на каждый город с City Lights. Если это нежелательно, можно использовать особое поле stack, запрещающее применять более одного эффекта данного типа к значению (например, оно используется для однократного применения бонуса морали к отряду).

Программирование модулей

Эффектами и изменениями в банке данных можно добиться очень многого. Практически вся механика объектов на карте (сундук, ресурс, артефакт, монстр, жилище, страж врат, колодец, мельница, фонтан и т.д. и т.п.) задана именно эффектами, а не кодом, так как это намного проще - движок сам следит за тем, когда применить эффект и как его сбросить.

Тем не менее, в HeroWO есть и система модулей (плагинов) на JavaScript. На herowo.io, кроме панели эффектов, есть панель подключаемых скриптов (кнопка Add script). Предлагаю нажать на нее и указать такой URL:

Код
https://herowo.game/pub/mod-ex-1.js

По этому URL находится такой скрипт:

Код
define([], function () {
  var coords = ''

  return {
    start: function (cx) {
      $('<button id=mybtn>')
        .text('Go')
        .insertBefore('#controls .map-size')
        .click(function () {
          coords = prompt('Enter X-Y coordinates to center on:', coords) || ''
          var pos = coords.match(/(\d+)\D+(\d+)/)
          if (pos) {
            cx.screens().forEach(function (sc) {
              sc.set('mapPosition', [pos[1], pos[2]])
            })
          }
        })

      $('<style id=mystyle>')
        .text(
          `
            #mybtn {
              display: block;
              background: red;
            }
          `
        )
        .appendTo('body')
    },

    stop: function () {
      $('#mybtn,#mystyle').remove()
    },
  }
})
  • define - синтаксис Require.js. В первом параметре-массиве задаются зависимости модуля, во втором - его код. В нашем случае зависимостей нет (вернее, мы используем глобальную переменную $ - jQuery; это не красиво, но для простоты пойдет).
  • Функция модуля должна вернуть объект с двумя методами: start и stop. Оба получают объект cx - Context, точка входа в работающий экземпляр движка.
  • В start мы добавляем в документ новую кнопку Go на верхнюю отладочную панель. По щелчку запрашиваем у пользователя координаты на карте и центрируем на них.
  • Также мы добавляем в документ CSS-стили, выделяя нашу кнопку.
Более сложный пример, где мы встраиваемся внутрь движка в виде экранного модуля (ScreenModule), рисующего пунктирную линию вокруг жилищ с существами, доступными для найма:

Код
https://herowo.game/pub/mod-ex-2.js



Код
define(['DOM.Common'], function (Common) {
  var Mod = Common.Sqimitive.extend({
    mixIns: [Common.ScreenModule],
    _map: null,

    events: {
      render: function () {
        this._map = this.sc.modules.nested('HeroWO.DOM.Map')
        var dwelling = this.map.constants.object.type.dwelling

        this.autoOff(this.map.objects, [
          'ochange_p_' + this.map.objects.propertyIndex('available'),
          function (n) {
            var id = this.map.objects.fromContiguous(n).x

            if (this.map.objects.atCoords(id, 0, 0, 'type', 0) == dwelling) {
              this._updateObject(id)
            }
          },
        ])

        this.map.byType.findAtCoords(
          dwelling, 0, 0,
          0,
          this._updateObject,
          this
        )
      },
    },

    _updateObject: function (id) {
      this._map.objectEl(id).classList.toggle('mymod-available',
        this.map.objects.readSubAtCoords(id, 0, 0, 'available', 0)
          .find(0, count => count > 0 || null) != null)
    }
  })

  var style = $('<style>')
    .text(
      `
        .mymod-available {
          outline: .1em dashed lime;
        }
      `
    )

  return {
    start: function (cx) {
      style.appendTo('body')
      cx.autoAddModule('mymod', Mod)
    },

    stop: function (cx) {
      $('.mymod-available').removeClass('mymod-available')
      cx.screens().forEach(sc => sc.unlist('mymod'))
      style.remove()
    },
  }
})
  • define объявляет зависимость на общий для экранных модулей класс с полезными вещами.
  • Common.Sqimitive.extend() - способ создания нового класса в фреймворке Sqimitive. Поля класса передаются в виде объекта; например, _map - новое поле, по умолчанию null, причем подчеркивание в начале обозначает, что к нему не следует обращаться снаружи от того класса, где оно определено (protected).
  • render - событие, на которое мы подписываемся; возникает однократно в жизни каждого модуля в момент отрисовки интерфейса. Есть и другие события, например, attach, которое вызывается раньше, в момент загрузки.
  • this.sc - ссылка на экран, в который добавлен наш модуль. Экранов может быть несколько - например, при игре в режиме hot seat. Из экрана мы получаем ссылку на модуль отрисовки игровой карты (adventure map).
  • this.map - ссылка на логическую карту (только данные). Содержит в себе данные игроков, объектов, эффектов, тумана войны и прочего.
  • this.autoOff() - подписывается на события в другом объекте, причем при удалении нашего модуля или этого объекта подписка отменяется.
  • ochange_p_N - событие, возникающее в хранилище данных объектов adventure map (это земля, дороги, сундуки, мельницы, города, герои - и в том числе жилища). Если точнее, оно возникает при изменении ("o"bject "change") поля ("p"roperty) номер "N" (в нашем случае - available).
  • function (n) принимает на вход номер (n) измененного объекта и получает по нему ID, проверяет тип объекта (мы не работаем с городами, например) и обновляет его.
  • После подписки на событие проходим по существующим объектам, применяя к ним начальное состояние рамки. map.byType - это тот же map.objects, только ограниченный нужным нам типом объектов; это быстрее, чем перебирать все подряд.
  • Так как все игровые объекты в данной версии - это DOM-узлы (из-за чего, собственно, и проистекает чрезмерное потребление памяти и подлагивания), то для изменения внешнего вида объекта наш _updateObject просто добавляет CSS-класс mymod-available в случае, если в поле-массиве available этого конкретного объекта есть хотя бы одно число выше 0. (available хранит число доступных существ для каждого типа существа в отдельности.)
  • Наконец, в start мы добавляем наш стиль к документу и наш модуль к каждому (autoAddModule) экрану в игровом контексте (cx).
Praktik
Идея интересная. Хоть и не совсем понятно для кого это сделано.
Протестировать не удалось, та как не играбельно вообще. Не получается даже героем походить.
А оно связано с лобби СОД?
Lokos
Цитата(Praktik @ 28 Dec 2022, 14:18) *
Идея интересная. Хоть и не совсем понятно для кого это сделано.
Протестировать не удалось, та как не играбельно вообще. Не получается даже героем походить.
А оно связано с лобби СОД?

Не знаю что у вас не получилось протестировать, лично у меня заработало даже с телефона. Потыкал, в бой зашёл, потыкал. Играбельно. Для кого это сделано? Как минимум для себя отвлечься например от основной работы. Как вариант в портфолио. Просто выражение любви к одной из любимых игр. По поводу лобби полагаю что нет. Хд функционал тут не накручен пока что. тот проект сырой что бы пускать в онлайн к ориджен соду.
Респект автору, работы ещё конечно туева туча, если ли какие нибудь сообщества что бы отслеживать прогресс. Гит не очень для этого подходит для юзеров все же.
Gong Zigoton
Цитата(Praktik @ 28 Dec 2022, 14:18) *
Протестировать не удалось, та как не играбельно вообще. Не получается даже героем походить.

Ну, в целом, я соглашусь, что достаточно неиграбельно. Как бы герой ходит, но это "10 fps experience", конечно же.

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

Ну, если Убейсофты не запретят. А так да, норм.
HeroWO
Цитата(Praktik @ 28 Dec 2022, 14:18) *
Идея интересная. Хоть и не совсем понятно для кого это сделано.

А для кого VCMI сделано? И другие? Потенциально может развиться в полноценный проект, не связанный рамками оригинальной игры. Моды существуют, значит интерес есть.

Цитата(Praktik @ 28 Dec 2022, 14:18) *
А оно связано с лобби СОД?

Никак.

Цитата(Gong Zigoton @ 28 Dec 2022, 18:34) *
Цитата(Praktik @ 28 Dec 2022, 14:18) *
Протестировать не удалось, та как не играбельно вообще. Не получается даже героем походить.

Ну, в целом, я соглашусь, что достаточно неиграбельно. Как бы герой ходит, но это "10 fps experience", конечно же.

Это преувеличение или действительно так? У меня обычный ноутбук 5-летней давности. Открыл два окна в Chrome, запустил мультиплеер. Работает не без проблем, конечно, но отзывчивость нормальная и вполне играбельно, даже когда записываешь видео. Замок работает, битва работает, шахту взял. Ну, и ролики в шапке я ведь как-то записал.



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

Цитата(Gong Zigoton @ 28 Dec 2022, 18:34) *
Так что да, лет 20 работы в одиночку и, быть может, каждый сможет бегать в герои 3: СоД версию на телефоне и в браузере.

Почему обязательно в одиночку?

Цитата(Lokos @ 28 Dec 2022, 17:24) *
Респект автору, работы ещё конечно туева туча, если ли какие нибудь сообщества что бы отслеживать прогресс. Гит не очень для этого подходит для юзеров все же.

df2 есть, а так пока больше ничего.
Gong Zigoton
Цитата(HeroWO @ 28 Dec 2022, 22:33) *
Цитата(Gong Zigoton @ 28 Dec 2022, 18:34) *
Цитата(Praktik @ 28 Dec 2022, 14:18) *
Протестировать не удалось, та как не играбельно вообще. Не получается даже героем походить.

Ну, в целом, я соглашусь, что достаточно неиграбельно. Как бы герой ходит, но это "10 fps experience", конечно же.

Это преувеличение или действительно так? У меня обычный ноутбук 5-летней давности. Открыл два окна в Chrome, запустил мультиплеер. Работает не без проблем, конечно, но отзывчивость нормальная и вполне играбельно, даже когда записываешь видео. Замок работает, битва работает, шахту взял. Ну, и ролики в шапке я ведь как-то записал.



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

У меня телефон хоть и андроид, QR-коды не читает, спасибо, не надо. И фиг знает, то ли видеокарты отсутствие мешает, то ли код у вас как-то лучше работает, но у меня менюшка тупит дольше, чем на вашем видео. Примерно на 1-2 секунды задержка на всё. Зато карта быстрее загрузилась. Бой же точно также работает. И это тоже можно отнести в "относительно неиграбельную" категорию.

И да, то, что работает - не значит, что оно работает. Фактически - может быть. Но играть в 10 фпс или в 800 на 600, когда игра поддерживает 1920 на 1080 (привет Path of Exile, оптимизация неиронично становится лучше с каждой лигой. А вот баланс ровно на столько же пунктов падает, пробивая дно за дном) - это не очень клёво.

Цитата(HeroWO @ 28 Dec 2022, 22:33) *
Цитата(Gong Zigoton @ 28 Dec 2022, 18:34) *
Так что да, лет 20 работы в одиночку и, быть может, каждый сможет бегать в герои 3: СоД версию на телефоне и в браузере.

Почему обязательно в одиночку?

Потому что вы пока что работаете один. А я привык прикидывать худшие, но минимальные варианты. Очевидно, что самый фиговый - если никто работать не будет. Но если никто не будет, то, полагаю, очевидно, что никто и не сделает. Поэтому и минимальный вариант - один человек из пока что заявленных 1.
hippocamus
У меня на ноуте (винда 11) открылась хорошо. Быстрые действия пропускают кадры.
Например, на коне по карте прокатиться - сначала пауза, потом со средины начинает двигаться со шлейфом предыдущих кадров.
То есть графика страдает (что и неудивительно - javascript вообще не об этом) - но так всё работает норм.
feanor
И чому я так ору с названия?
Очень хорошо, больше ремейков, хороших и разных
void_17
В...вау... Такой объем работы в одиночку....

Очень неожиданно. Даже не знаю что написать.
Эпических масштабов работа! barb_metal.gif

upd.: Можно было бы кстати сразу на С++ писать, благо с недавних пор есть компилятор LLVM в webassembly. Так все работало бы в разы быстрее
HeroWO
Цитата(Gong Zigoton @ 28 Dec 2022, 23:23) *
Цитата(HeroWO @ 28 Dec 2022, 22:33) *
Цитата(Gong Zigoton @ 28 Dec 2022, 18:34) *
Так что да, лет 20 работы в одиночку и, быть может, каждый сможет бегать в герои 3: СоД версию на телефоне и в браузере.

Почему обязательно в одиночку?

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

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

Задачи по проекту есть разные, на любой вкус:
  • Самое простое - заполнить пробелы в банке данных, например, звуки. Найти пробелы можно или поиском "XXX" по файлам databank-*.php, или посмотрев здесь. Выглядит достаточно очевидно, например, для звука на карте рядом с жилищем воздушных элементалей:

    Код
    //    array_fill_keys($c_airElementalConflux, ['sound' => 'XXX=ID:dbs:']),

  • Проверить/сравнить поведение с каноном, например, расчет урона, величину бонуса к защите действием Defend и прочее. Это тоже не требует программирования и обычно понятно описано. Список.
  • Мелкие изолированные задачи с программированием. Самая мелкая - исправить построение путей в pathfinder (сейчас он строит хоть и оптимальные, но не всегда прямые пути, что выглядит неважно).
  • Чуть более крупная и сложная - рисовать мини-карту на canvas, а не узлами в DOM. Это резко сократит число узлов и улучшит поведение страницы.
  • Еще крупнее - рисовать всю приключенческую карту на canvas. Это сократит еще больше узлов. Аналогично с картой битвы и меню.
Конечно, задач очень много, есть и менее важные, например, проигрывание реплеев, улучшение AI, предзагрузка ресурсов...

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

Цитата(hippocamus @ 29 Dec 2022, 23:26) *
У меня на ноуте (винда 11) открылась хорошо. Быстрые действия пропускают кадры.
Например, на коне по карте прокатиться - сначала пауза, потом со средины начинает двигаться со шлейфом предыдущих кадров.
То есть графика страдает (что и неудивительно - javascript вообще не об этом) - но так всё работает норм.

JS сам по себе ни при чем. Дело в методе рисования карты (плюс, я подозреваю, у вас еще рисунки не сразу загрузились - следующее движение может быть уже плавным). Переделать на canvas, т.е. на ручное рисование 2D-графики, реально, просто для меня было важно закрыть весь функционал, пусть и не оптимальным образом, и я экономил время на всем, чем мог.

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

Цитата(feanor @ 30 Dec 2022, 22:32) *
И чому я так ору с названия?

Штирлиц еще никогда не был так близок к провалу... wink.gif

Цитата(void_17 @ 01 Jan 2023, 19:04) *
В...вау... Такой объем работы в одиночку....

Очень неожиданно. Даже не знаю что написать.
Эпических масштабов работа! barb_metal.gif

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

Цитата(void_17 @ 01 Jan 2023, 19:04) *
upd.: Можно было бы кстати сразу на С++ писать, благо с недавних пор есть компилятор LLVM в webassembly. Так все работало бы в разы быстрее

Смысла нет - VCMI именно так и делает. Если и стоило начинать новый проект, то на иных принципах. И, опять же, не в JS дело - по крайней мере, можно точечно переписать тормозящий функционал на wasm, его там будут единицы процентов от общего объема кода, зато сохранится расширяемость модами и простота разработки.
Mefista
*OwO intensifies*
Doctor Tea
Прекрасная работа. Респект.
Но хотелось бы обратить внимание на баги. Тыкаешь на шахту - герой до нее еще не дошел, а флажки уже перекрасились.
HeroWO
Цитата(Doctor Tea @ 06 Jan 2023, 20:56) *
Прекрасная работа. Респект.

Благодарю!

Цитата(Doctor Tea @ 06 Jan 2023, 20:56) *
Но хотелось бы обратить внимание на баги. Тыкаешь на шахту - герой до нее еще не дошел, а флажки уже перекрасились.

Да, это есть во многих местах. При совершении действия его эффекты вступают в силу моментально, тогда как визуальный отклик вроде движения героя по карте происходит в отложенном режиме, с лагом по времени относительно состояния игрового мира. В битве это реализовано как положено, но в основной карте есть только рудементарная поддержка (как то поэтапное перемещение героя, но не смена флагов или раскрытие тумана войны). Это следует считать не багом (т.к. поддержка в ядре есть), но недоделанным функционалом. Хотя для игрока все одно, согласен.
void_17
Цитата(Mefista @ 02 Jan 2023, 02:19) *
*OwO intensifies*


А я вот увидел "херово"...
https://www.youtube.com/watch?v=-X4hthSOyqA
HeroWO
У проекта появился Discord-сервер: https://discord.gg/UcGCNhJEUx
...форум: https://forum.herowo.net
...и несколько роликов с демонстраций возможностей на YouTube-канале: https://www.youtube.com/@PlayHeroWO
HeroWO
Приглашаю всех, кому интересна разработка игр, оценить мою статью на Хабрахабре о суровых буднях работы над движком HeroWO:

О, «Герои»? Дайте две! Как я писал очередной браузерный клон легендарной стратегии, в который уже почти* можно играть


hippocamus
Цитата
Z-координата (глубина/дальность от глаз пользователя) вычисляется неясным образом. Вначале я думал, что она зависит от порядка следования объектов внутри .h3m и их координат, но после многочасовых экспериментов с редактором карт я оставил попытки разобраться, как же именно она определяется, так что текущая формула выглядит не очень. Кто знает, расскажите!

В общем, обычно, чем ниже основание объекта (больше Y) - тем позже он отрисовывается (то есть, он ближе к игроку).
Но есть объекты, имеющие флаг "элемент ландшафта" - шахты, блоки цветов, холмиков. Они отрисовываются первыми (то есть любой объект без этого флага их загородит, отрисовавшись поверх).
HeroWO
Цитата(海马 @ 19 Apr 2023, 00:34) *
В общем, обычно, чем ниже основание объекта (больше Y) - тем позже он отрисовывается (то есть, он ближе к игроку).
Но есть объекты, имеющие флаг "элемент ландшафта" - шахты, блоки цветов, холмиков. Они отрисовываются первыми (то есть любой объект без этого флага их загородит, отрисовавшись поверх).

Да, про это я знал, но оказалось, что алгоритм еще учитывает наложение объектов друг на друга, как мы выяснили из исходников VCMI:
https://github.com/vcmi/vcmi/blob/develop/c...Handler.cpp#L73

* * *

На Хабрахабре вышла вторая статья по истории разработки и внутренностях движка HeroWO:

Карта, золото, «Герои»: продолжаем разбираться в технико-исторической части HeroWO.js — браузерного клона культовой игры


VAS_SFERD
Шикарный сделано, очень большой объем работы.
Честно говоря, всегда считал и считаю динамические языки, вроде js, очень обтекаемыми. В том смысле, что им не хватает строгости.

Тиринг и лаги прорисовки связаны с рисованием через DOM?

Какой браузер рекомендуется для игры в эту игру?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.