У меня есть боты в прямоугольной формации с рядами и столбцами. Проблема возникает, когда бот добавляется или удаляется из пласта. Когда это происходит, боты должны перестроиться так, чтобы прямоугольная формация была примерно такой же пропорции и была настолько прямоугольной, насколько это возможно. Как это сделать?
Некоторые идеи:
Когда бот добавляется или удаляется, используйте новое общее количество ботов и желаемое постоянное соотношение сторон, чтобы вычислить новую ширину и высоту формации, которая наиболее точно соответствует этому соотношению сторон. Затем каким-то образом переставьте ботов, чтобы они соответствовали новым размерам.
Когда бот удален, переместите бот, который был позади него, на свое место и продолжайте, пока не дойдете до конца формирования. Затем выровняйте задний ранг как можно больше, перетасовав ботов в задний ранг.
Другая идея, которая совершенно отличается, состоит в том, чтобы подражать тому, как структуры молекул остаются вместе. Сделайте так, чтобы каждый бот был окружен четырьмя другими ботами, привлекая четырех ближайших ботов и отталкивая остальных. Отбросьте все боты (включая четырех), которые находятся слишком близко, чтобы обеспечить разделение, используя закон обратных квадратов. Вам также понадобится дополнительная сила для формирования всей структуры. Но это звучит очень вычислительно дорого.
ОБНОВЛЕНИЕ : Итак, изучая ответ Сарама, я придумал хорошую общую функцию, которая дает хорошие размеры.
Сначала я решил приведенное ниже уравнение для ширины и высоты, а затем округлил ответы.
width/height=aspect ratio of your choice
width*height=number of bots
Это дает вам ближайший целочисленный прямоугольник к этому соотношению сторон для вашего количества ботов. Ближайший прямоугольник будет в половине случаев слишком большим, а в половине - слишком маленьким (конечно, иногда это будет правильно, но кого это волнует). В тех случаях , когда прямоугольник представляет собой немного слишком большим, ничто не должно быть сделано. Задний ранг в итоге будет почти полным, что идеально. В тех случаях , когда прямоугольник представляет собой немного слишком мал, у вас есть проблемы , потому что маленькие крошечные переполнения придется идти в свой собственный ранг создал ранг лишь несколько ботов на нем, который не выглядит красиво. Есть также случаи, когда разница велика(больше, чем половина ширины), в этом случае добавьте или вычтите один ранг, чтобы уменьшить разницу. Затем, когда прямоугольник слишком мал, добавьте один столбец, чтобы сделать его чуть больше. После этого похоже, что у бэк-ранга всегда будет как минимум вдвое меньше ботов, чем у других.
ОБНОВИТЬ
Как только вы получили размеры, сравните их с текущими размерами. Если фасад нового измерения больше, для каждого ранга выведите попсовых ботов с ранга ниже и подталкивайте их на текущий ранг до тех пор, пока число ботов этого ранга не станет равным фронтажу. Продолжайте этот алгоритм, пока не доберетесь до заднего ранга. Используя этот алгоритм, боты будут эффективно вписываться в новое измерение. После этого я просто толкаю нового старого на задний план. Алгоритм немного отличается для случаев, когда новый фронт меньше, но вы можете это выяснить!
Далее есть еще две проблемы. Удаление и более гибкий метод сложения, при котором новые боты не обязательно присваиваются бэк-рангу, но какая позиция ближе к ним в момент их добавления.
Ответы:
Другая техника заключается в том, чтобы имитировать то, что использовалось наполеоновскими батальонами (и, вероятно, так же далеко, как греческие фаланги, если не дальше).
Фронтаж обычно поддерживается постоянным, и когда человек падает (в любом ранге, кроме спины), его заменяет человек, идущий прямо за ним и выходящий вперед. Задний ряд перетасовывается сержантами, чтобы обеспечить по несколько человек на крайнем фланге каждого фланга, а в остальном заполнить равномерно.
Фронтаж уменьшается только тогда, когда обратный ранг падает ниже заданных плотностей. Аналогично, когда задний ранг переполнен, статисты сначала начинают заполнять дополнительный ранг с обоих флангов, а затем увеличивается фронт.
При изменении фронтажа я предлагаю, чтобы ваши боты выдавали с заднего ряда на оба фланга при увеличении фронта, и с обоих флангов на задний ряд при уменьшении фронта.
Если я правильно понял, что вы ищете «военное» впечатление, и ваши бот-организации выглядят как фаланги, я считаю, что эта упорядоченная перестановка - лучший способ достичь этой цели.
Обновление .
Один из простых способов управления задним рядом состоит в том, чтобы разделить отряды заднего ряда на три отряда: по одному на каждом фланге и один в центре. В зависимости от того, является ли фронт четным или нечетным, а также от того, совпадает ли число блоков в задней строке с 0,1 или 2 модулями 3, существует ровно шесть вариантов управления.
В качестве дополнения к вышесказанному, рассмотрите расстояние между последними единицами (ами) каждого отряда задней строки, как только заполнение упадет ниже порогового значения, как это:
xxx.x .... x.xxx.x .... x xxx
или это:
xx.xx..x.xxx.x ... xxxx
Немного больше работы, для еще лучшего внешнего вида.
Обновление № 2 :
дополнительная мысль о глубине пласта. Удар залпового огня в сочетании с современным штыком сделал глубину 3 или 4 достаточной в конце 18-го и начале 19-го века. (Британцы редко сражались в 2 рядах, вопреки распространенному мнению, до конца битвы; с одной стороны, они делали свои линии слишком длинными, чтобы быстро образовать квадрат.) До этого было обычным иметь большую глубину, возможно, до 8 или 10 для греческой фаланги с Сариссой. Выберите глубину, которая создает впечатление, которое вы хотите.
В реальной жизни армии стараются поддерживать фронт отрядов как можно дольше, за счет увеличения хрупкости отрядов, поскольку это упрощает раскладку поля битвы. Цезарь в Фарсале преднамеренно уменьшил глубину своего отряда, чтобы увеличить фронт, чтобы он соответствовал силе Помпея. Как говорится в цитате: «Мы выигрываем или умираем сегодня; у людей Помпея есть другой выбор». (что Цезарь умело и тщательно обеспечил, конечно).
источник
Предполагая, что единица представляет собой линейную структуру данных (например, список ) ботов.
Сначала вы должны добавить / удалить бота в / из структуры данных и определить новое количество ботов в юните.
Затем вы должны определить новое количество строк и столбцов, используя https://en.wikipedia.org/wiki/Integer_factorization .
Конечно, это не всегда возможно из-за простых чисел . Когда новый размер блока простое число, вам нужно использовать следующий больший размер блока, который не является.
Затем просто переберите структуру данных, назначив ботов по строкам и столбцам.
Для размещения ботов просто выполните итерацию по структуре данных, назначив каждому боту смещение позиции от позиции юнитов на величину, определяемую строкой и столбцом, в котором находится бот (или установите эту точку в качестве цели для движения ботов).
Чтобы сделать юнит с центром в одном углу , положение бота определяется как
unitPosition + heading * columnNumber * botSeparationDistance + rightVector * rowNumber * botSeparationDistance
Чтобы сделать юнит с центром в середине , положение бота определяется как
unitPosition + heading * (columnNumber * unitSeparationDistance - 0,5 * (numberOfColumns * botSeparationDistance) + rightVector * rowNumber * botSeparationDistance - 0,5 * (числоOfRows * botSeparationDistance)
где заголовок - это вектор, указывающий в направлении, в котором стоит устройство, а правый вектор - вектор, ортогональный направлению .
BotSeparationDistance можно настроить так, чтобы боты стояли дальше или ближе друг к другу.
Если вы чувствуете фантазии, вы можете компенсировать последнюю строку бот на rightVector * 0,5 * (numberOfColumns - actualNumberOfBotsInRow) к центру их на формировании .
источник
Я бы сохранил возможные позиции на графике с большими значениями, являющимися меньшими прямоугольниками.
Каждый раз, когда робот удаляется, ищите всех остальных роботов и находите его в узле с наименьшим значением. Используйте алгоритм A * или BST, чтобы найти путь от минимального значения до свободного места. Если нет робота с меньшим значением, чем удаленный, ничего не делайте.
Вы также должны быть в состоянии контролировать, как прямоугольник распадается, делая это. Например, на приведенном ниже графике, когда робот покинет нижний со стороны, придет заполнить его место.
Здесь убирается тот, что в 3.8, так что тот, что в 2.5, приходит и занимает свое место.
Другой пример. Здесь 2.8 удаляется, поэтому наименьший узел 2.2 занимает его место.
Возможно, вам нужно кольцо узлов со значением 0, которое вы никогда не заполняете снаружи, чтобы ваш алгоритм поиска пути нашел дыру.
Хороший учебник по A * можно найти здесь .
источник