Я делаю простую стратегическую игру 4X в космосе, где каждый узел является точкой интереса (планета, астероид и т. Д.).
Чтобы случайным образом создать карту, я бы следовал инструкциям ниже
Определите, сколько типов каждого узла будет иметь карта (например, 5 планет земного типа, 10 бесплодных планет и т. Д.)
Разместите каждый тип узла на карте.
Для шага 2 я хотел бы иметь четное распространение каждого типа узла. Так, например, я бы начал с размещения всех планет земного типа. Если я просто сделаю ранд (map.width, map.height), чтобы определить положение, я могу закончить кластеризацию всех планет земного типа, что даст преимущество игроку, начинающему в этой области.
Существуют ли какие-либо методы, такие как использование различных графовых функций или шумовых функций, которые могут генерировать последовательность (x, y) координат, которые разнесены друг от друга. Аналогично, есть ли способы генерировать координаты, которые близки друг к другу?
Ответы:
Проблема, с которой вы сталкиваетесь, заключается в том, что случайный выбор не различает, и это может означать, что он не совсем подходит для того, что вам нужно делать. Но есть по крайней мере один простой способ обойти это:
Разделите ваше пространство на сектора (например, если у вас есть область 100 на 100, и вам нужно сгенерировать 100 таких солнечных систем, а затем разделите вашу область на сетку секторов 10 на 10)
Выполните цикл по каждому Сектору и повторите шаг 3 (который, в свою очередь, будет повторять шаг 4 несколько раз)
Случайным образом определите количество планет для текущей солнечной системы (например, для диапазона от 3 до 7 планет, просто получите случайное число в диапазоне от 0 до 4 и добавьте 3) в текущем секторе (если у вас есть более одного солнечного система в секторе, это где вы бы создали еще один цикл)
Произвольно назначьте свои планеты в пределах текущей Солнечной системы, идентифицированной вашей петлей (вы также можете использовать случайные числа, чтобы увеличить минимальные расстояния между планетами); Здесь вы можете выбрать типы планет, которые также могут быть определены случайным образом с различными весами или любым другим методом, который вы предпочитаете использовать.
Вы также можете определить область «вне границ» вокруг края каждого сектора, чтобы предотвратить непосредственное соприкосновение планет из соседних секторов (просто в том случае, если они были расположены случайно рядом друг с другом), или. ..
Другое решение может заключаться в определении местоположения каждой солнечной системы и / или каждой планеты, чтобы просто выполнить быструю проверку близости к соседним секторам и соответствующим образом скорректировать (например, отойти от края на минимальное расстояние плюс случайное расстояние ).
источник
Лучший способ обеспечить равномерное распределение - это рассматривать каждый узел как своего рода физическую частицу. Сначала выполните случайное распределение по непрерывной плоскости (с плавающей точкой) xy. Применяя силы отталкивания между каждой отдельной парой отдельных частиц на плоскости, вы обнаружите, что они медленно разлетаются. В некотором смысле это похоже на разрешение столкновений, только нет фактического контакта, о котором можно говорить. Тогда просто преобразовать эту плоскость («растеризовать») обратно в целочисленную сетку. Вы можете просто сделать это из сетки с целочисленными индексами для начала, но может быть немного сложнее получить «хороший» результат - это зависит от того, насколько высокое разрешение вашей сетки ... чем выше, тем лучше , в этом случае.
Очевидно, вы также можете приложить какие-то силы к краям квадратной плоскости, иначе вы можете обнаружить множество частиц, «вымывающих берега». В качестве альтернативы вы можете создать поле намного больше, чем вам нужно, а затем сделать снимок небольшой области этого - это позволяет избежать вышеупомянутой проблемы.
Если вы хотите убедиться в обратном, то есть в том, что кластеризация действительно имеет место, посмотрите на «стандартное» или «гауссовское» распределение. Вот почему случайно сгенерированные звездные поля часто выглядят ненастоящими; они используют чисто случайное распределение, а не более натуралистическую модель распределения.
источник
Вы можете использовать простой алгоритм распределения Пуассона-диска, чтобы получить распределение "синего шума". Это приводит к точкам на плоскости, которые примерно одинаково разнесены друг от друга. Это работает не только в вашем примере 2D, но и в 3D, а также в неевклидовых пространствах, но вычисления могут быстро стать громоздкими.
Основная идея этих алгоритмов состоит в том, что вы начинаете с первой «начальной точки», а затем работаете сами, добавляя случайные или псевдослучайные точки в межтрубное пространство между максимальным и минимальным расстояниями, которые вы хотели бы получить, начиная с этой точки и устраняя их. те, которые лежат слишком близко друг к другу. Ваш алгоритм затем работает таким образом, пока либо не будет добавлено необходимое количество точек (что дает вам примерно круговое облако точек), либо пространство не будет заполнено.
Быстрый и изящный альтернативный алгоритм для генерации 2D такого шума, а также краткое обсуждение его свойств, можно найти в книге Даниэля Данбара и Грега Хамфриса из Университета « Пространственная структура данных для быстрой генерации образцов диска Пуассона». Вирджиния
источник