bsivko:Разница между вычислением с помощью волны от всего региона и наименьшим расстоянием по прямой между двумя точками составляет менее (sqrt(2)+1)/sqrt(5) - 1 (там более хитрая формула, но это одна из близких верхних оценок), а это менее 8%.
Это, наверное, замечательно, но... ну и что? :) Какая разница, какая между ними разница?
Свищи на полуровня даже не рассматриваю, и любые алгоритмы, к ним приводящие - тоже.
Возможно для игры нужны только горизонтальные/вертикальные(/диагональные) коридоры
?
Ещё, насколько я себя помню в настоящих кавернах, там просверлы от рек и прочих не прямые.
Дело в том, что ты не видил результат реализации. Из-за выбранной мною методы, просверлы предельно короткие. А из-за того, что разрешение уровня низкое, выглядят они вполне естественно. Более того, они не воспринимаются как нечто чужеродное - это просто часть уровня. Нет никакой разници в том, как выглядит "естественно" полученная каверна и две каверны, соединённые алгоритмом.
Посверлы кстати при некоторых реализациях могут самопересекаться. В том числе в этих:
Вчера мне пришла в голову последовательное соединение ближайших регионов по ближайшим точкам.
Нет, в этих как раз немогут. При соединении ближайших регионов по ближайшим точкам - никак не могут.
В названии темы и в первом сообщении написано, что требуется найти найкратчайшее расстояние.
Расстояние может считаться по-разному. В связи с этим и уточнение.
Да, надо найти наикратчайшее расстояние. Когда спросили как это считаю я, я ответил что суммой квадратов. Почему ты решил, что это условие?
Потому что обладаю свойством вьедливости. И не умею считать "какие-нибудь расстояния" в "каких-нибудь регионах"
Больше похоже, на другое, но я промолчу :)
Насколько все понял, требуется найкратчайшее правдоподобное расстояние для пользователя. Не важно, Пифагор, max(dx, dy), min(dx+dy) или ещё что.
Нет тут никакого пользователя, вобщем-то. А расстояние нужно найти правдоподобное, это да.
Только затык был не в том, что квадраты медленно считаются(никакого заметного выигрыша избавление от корней или квадратов не даёт), а в том, что нужно было перемножать два множества. На данный момент "бордюрный" алгоритм хреначит с адской скоростью, но это всё равно, практически, перемножение двух множеств.
Бордюрный поиск можно значительно ускорить засчет интерполяции. Фактически, расстояния каждого бордюра к каждому - это функция от двух переменных - на выходе плоскость. В этой плоскости надо найти минимум. Особенность в том, что точки плоскости не могут мгновенно изменять свое значение, а только на 1 или sqrt(2) максимум (смотря как бордюр построен, без диагоналей или с).
Не вкурил... Пошагово можешь алгоритм описать?
Быстро кодится оптимизация, когда например считается в этой плоскости каждая например 5-я точка с каждой 5-й (точки выстроены вдоль бордюра). Находится минимум X. Все ребра, которые не получили X+10 (или X+10*sqrt(2)), выкидываются из выборки. Остальное - градиентный спуск. В итоге - профит в 5*5 раз.
Хм... Не уверен, что понял именно то, что ты хотел сказать, но идейка одна родилась, спасибо.
Это, наверное, замечательно, но... ну и что? :) Какая разница, какая между ними разница?
Разница в 8% (;
Т.е. если мы ищем найкратчайшее, то можем его не найти. Но зато найдем расстояние, которое не будет отличаться от найкратчайшего более чем на 8%. Например для генерации уровня игры это скорее всего будет более чем достаточно. А в жизни могут оказаться задачи, для которых этого будет недостаточно.
Свищи на полуровня даже не рассматриваю, и любые алгоритмы, к ним приводящие - тоже.
Возможно для игры нужны только горизонтальные/вертикальные(/диагональные) коридоры
?
г/в/д коридоры необязательно пилить на полуровня, чтобы соединить все.
или я опять чего-то не понимаю в диалоге
Нет, в этих как раз немогут. При соединении ближайших регионов по ближайшим точкам - никак не могут.
Только что провел мат. док-во для точек, а не регионов с тем же свойством. В результате ранее придуманные контрпримеры рассыпались.
Скорее всего да, никак не могут.
Да, надо найти наикратчайшее расстояние. Когда спросили как это считаю я, я ответил что суммой квадратов. Почему ты решил, что это условие?
Не понимаю, как это можно понять по другому.
Не вкурил... Пошагово можешь алгоритм описать?
Есть два множества точек бордюров: A и B.
1. Представим их в виде двух упорядоченных массивов (C И D). В массивах присутствуют все точки множества, но при этом расстояние между двумя любыми C(i) и C(i+1) не превышает 1 (или sqrt(2)), тжс для D.
Другими словами, точки в массивах идут так, как они идут "вдоль" бордюра на плоскости.
2. Находим все расстояния между каждой пятой точкой C и D. С(0), С(5), С(10), ... и D(0), .., D(5), .. D(10), ... Всего N(C)*N(D)/25 расстояний R(i, j).
3. Выбираем из них минимальное MIN. Из множества найденных расстояний выкидываем все, которые больше (MIN + 10)
или (MIN + 10*sqrt(2)), если бордюр построен с использованием диагоналей минуя в некоторых точках горизонтали и вертикали.
4. Остается малое количество пар R(i, j). Искомое расстояние где-то рядом с ними. Где-то тут R(i-5..i+5, j-5..j+5).
5. Это можно перебрать в лоб (100 расстояний), а можно применить градиентный спуск:
а. +-1 по i и j, это расчет 8 расстояний, итерация с перемещением.
б. повторять (а) пока не будет найдено (тут не более 4 раз).
---
5-ку взял интуитивно исходя из картинок уровней. возможно подойдет и 3, и 10. Это от форм уровня зависит и оптимум по скорости ищется экспериментально.
bsivko написал:
1. Представим их в виде двух упорядоченных массивов (C И D).
2. Находим все расстояния между каждой пятой точкой C и D.
Мн кажется, или ты пытаешься реализовать велосипед деления на 2. :)
То есть делим список (вектор/массив) точек бордюра на 4 зоны (равные), берем середины зон и сравниваем с 4 другими точками другого бордюра.
Выбираем наименьшее расстояние, знаем "зону" в которой были эти точки. Делим зоны снова на 4 и т.д.
Не кажется, что это будет еще на порядок быстрее? Для уровня 256 х 256 это всего 4-5 итераций по 16 сравнений.
bsivko написал:
1. Представим их в виде двух упорядоченных массивов (C И D).
2. Находим все расстояния между каждой пятой точкой C и D.
Мн кажется, или ты пытаешься реализовать велосипед деления на 2. :)
То есть делим список (вектор/массив) точек бордюра на 4 зоны (равные), берем середины зон и сравниваем с 4 другими точками другого бордюра.
Выбираем наименьшее расстояние, знаем "зону" в которой были эти точки. Делим зоны снова на 4 и т.д.
Не кажется, что это будет еще на порядок быстрее? Для уровня 256 х 256 это всего 4-5 итераций по 16 сравнений.
Это не гарантирует требуемого результата.
Выбрав зоны любым образом и приняв решение, ты отсекаешь 3/4 решений, и нет гарантии, что среди них есть правильное.
Например ты взял 4 зоны-точки и получил 4 приблизительно равных числа. Выбрав любое из них, ты отбрасываешь 3/4 решений, а среди них может оказаться оптимальное. Например какая-нибудь выпуклость, не попавшая в 4 точки зон.
Это реоптимизированный бордюрный алгоритм, без пост-обработки (нет специальных шагов по приданию просверлов "естественного" вида. Время генерации конкретно этого уровня на слабом компе порядка 47 мс (время колеблется от 16 до 47 мс). Примерно в 18-20 раз быстрее изначального варианта, при котором я стартовал топик.
И вообще, можно все что надо загружать/вычислять в фоне, пока игрок в главном меню ковыряется, генерируется десяток карт.
Если главное это быстрота, то могу предложить вычислять среднюю точку каждого региона и выбирать в каждом бордюре ближайшую точку к средней соседнего региона, их и соединять. Должно корректно работать на выпуклых регионах, на невыпуклых скорее всего будет не совсем корректно работать, но зато разнообразие))
CoderInTank написал:
И вообще, можно все что надо загружать/вычислять в фоне, пока игрок в главном меню ковыряется, генерируется десяток карт.
Это может решить текущую, сиюсекундную, ситуацию, но в будущем такой номер не прокатит. Потом будет понятно почему.
Если главное это быстрота, то могу предложить вычислять среднюю точку каждого региона и выбирать в каждом бордюре ближайшую точку к средней соседнего региона, их и соединять.
Этот вариант я обдумывал, как один из возможных. Результаты будут не очень хорошие, потому, что, повторюсь, регионы могут быть любой формы. И центральная точка может оказаться за три П от региона, с которым должен соединяться текущий. И на пути такого соединений, может оказаться другой регион.
Должно корректно работать на выпуклых регионах, на невыпуклых скорее всего будет не совсем корректно работать, но зато разнообразие))