Отображение диапазона на гексагональной сетке

10

Здесь ситуация.

У меня есть гексагональная доска, и юнит на ней, со скоростью или значением перемещения 4. Различная местность имеет разные затраты. Когда я нажимаю на юнит, игра должна показывать мне диапазон хода.

Мое решение состояло в том, чтобы проверять каждый гекс в диапазоне 4, используя A * pathfinding, и если стоимость пути была меньше 4, тогда этот гекс находился в диапазоне. Наконец, игра хорошо показывает мне диапазон этого отряда.

Мой вопрос: есть ли другое решение для поиска диапазона по гекс-сеткам или квадратной сетке, потому что даже если я действительно горжусь тем, что я сделал в своем решении, я думаю, это немного преувеличено? :))

Что заставило меня задать этот вопрос? Я заметил, что когда единичная скорость равна 4, 6 или даже 8, время вычисления диапазона для моего компьютера было действительно хорошим, но когда скорость составляла 10 и более, я заметил, что мне нужно подождать несколько секунд, чтобы вычислить Ну, в реальных играх я не вижу ничего подобного, и мой A * pathfinding довольно хорошо оптимизирован, так что я думаю, что мое решение неверно.

Спасибо за любые ответы.

user23673
источник
1
Я согласен с Byte56, что алгоритм поиска в ширину является хорошим решением. Это не значит, что вы не должны пытаться быть креативными, но, насколько хорошо известно, это хороший алгоритм, который хорошо применяется.
theJollySin

Ответы:

11

Вы правы, что A * немного излишне, но ненамного. Вы не должны видеть задержки, как вы. А * на самом деле просто модифицированный алгоритм Диджикстры . Поскольку вы не используете конечную позицию (поскольку ваша конечная позиция просто «насколько вы можете пойти»), использование A * с добавленной эвристикой не требуется. Простого использования Dijikstra или простого поиска в ширину будет достаточно.

Например, Dikikstra будет распространяться равномерно по всем направлениям:

введите описание изображения здесь

(Простой поиск в ширину будет выглядеть примерно так)

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

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

MichaelHouse
источник
Вы можете найти расстояние между двумя узлами, используя BFS и принимая во внимание препятствия / различные веса?
Люк Б.
Стоимость перемещения между узлами по большей части должна быть предварительно рассчитана. Стоимость не рассчитывается с использованием BFS, BFS - это алгоритм обхода узлов. То, как вы определяете стоимость перемещения от одного узла к другому, не зависит от того, как вы пересекаете узлы.
MichaelHouse
Спасибо, теперь я понимаю, почему мое мышление было неверным, ключом к этому было утверждение «Так как вы не используете конечную позицию (поскольку ваша конечная позиция просто« насколько вы можете пойти »). В моем решении я У меня была конечная позиция, это был отряд. Я просто решил проблему с неправильного направления. Сначала я определил границу, а затем оттуда я вернулся к своему отряду, таким образом я, вероятно, много раз проходил через одни и те же узлы. когда моя скорость увеличивается, число вычислений также увеличивается. Как вы показываете, я всегда буду посещать узел один раз. У меня просто была неправильная точка зрения, действительно, спасибо, это сильно упростило.
user23673
4

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

for each -N  Δx  N:
    for each max(-N, x-N)  Δy  min(N, x+N):
        Δz = xy
        results.append(H.add(Cubex, Δy, Δz)))

Это создает границы, выровненные по шестнадцатеричной сетке:

введите описание изображения здесь

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

MichaelHouse
источник
1

Если кому-то это нужно, вот реализация C # алгоритма Пателя:

IEnumerable<Hex> GetRange(Hex center, int range)
    {
        var inRange = new List<Hex>();
        for (int q = -range; q <= range; q++)
        {
            int r1 = Math.Max(-range, -q - range);
            int r2 = Math.Min(range, -q + range);
            for (int r = r1; r <= r2; r++)
            {
                inRange.Add(center.Add(new Hex(q, r, -q - r)));
            }
        }

        return inRange;
    }
Аллан Хаугстед
источник