#java #algorithm #data-structures #3d #minecraft
#java #алгоритм #структуры данных #3D #Minecraft
Вопрос:
Я занимался разработкой некоторых плагинов Minecraft Bukkit и в настоящее время работаю над чем-то, где мне нужно иметь возможность определять «объем» пространства и определять, когда объект (игрок) перемещается снаружи этого объема внутрь (или наоборот).
Если я ограничу «объем» полями, это должно быть просто. Структура данных может просто поддерживать целые числа, ограничивающие X / Y / Z (всего 6 целых чисел), и вычисление входа / выхода с учетом двух точек (перемещение из и перемещение в) должно быть просто вопросом определения, находятся ли А) все три значения To во всех трех диапазонах и Б) хотя бы одинЗначение From находится за пределами соответствующего диапазона.
(Хотя, если есть лучший, более эффективный способ хранения и вычисления этого, я весь внимание.)
Однако, что, если «объем» не является простым блоком? Предположим, у меня есть комната странной формы, и я хочу заключить объем этой комнаты. Я мог бы расположить несколько «томов» по отдельности, чтобы заполнить общее пространство, однако это привело бы к ложным срабатываниям при переходе объекта от одного к другому.
Раньше я не работал в игровых или 3D-движках, поэтому я не понимаю, как я мог бы структурировать что-то подобное. Но мне приходит в голову, что это, вероятно, проблема, которая была решена и имеет известные установленные шаблоны. По сути, я пытаюсь:
- Определите структуру данных, которая может представлять объем пространства странной формы (хотя, по крайней мере, на основе координат блоков).
- Определите алгоритм, который, учитывая источник и пункт назначения движения, может определить, пересекло ли движение границу определенного пространства.
Существуют ли установленные шаблоны и методы для этого?
Ответ №1:
Я не знаю, использовалось ли это раньше в каких-либо видеоиграх, но первое, что пришло на ум, — это классическая реализация сита Эратосфена, единственным изменением было бы сделать boolean
массив 3D и использовать ключи в качестве координат. Очевидно, что, хотя x
y
значения as и могут быть огромными в Minecraft, вы, вероятно, захотите сэкономить место, сохранив смещение между мировой 0,0
позицией и вашим выбором, что-то вроде этого:
class OddArea
{
static final int MAX_SELECTION_SIZE = 64; //Or whatever
public final int xOffset, yOffset;
// 256 = Chunk height
public final boolean[][][] squares = new boolean[MAX_SELECTION_SIZE][MAX_SELECTION_SIZE][256];
OddArea()
{
this(0, 0);
}
OddArea(final int xOffset, final int yOffset)
{
this.xOffset = xOffset;
this.yOffset = yOffset;
}
void addBlock(final int x, final int y, final int z)
{
this.squares[x - this.xOffset][y - this.yOffset][z] = true;
}
boolean isInsideArea(final int x, final int y, final int z)
{
return this.squares[x - this.xOffset][y - this.yOffset][z];
}
}
z
не требует смещения, поскольку мир Minecraft имеет высоту всего 256 блоков.
Единственная проблема, о которой я могу думать при этой настройке, заключается в том, что вам нужно знать наименьшие x
y
координаты, прежде чем начинать заполнять свой объект
Комментарии:
1. Как алгоритм поиска простых чисел (сито Эратосфена) применяется к задачам пересечения границ?
2. @JimGarrison Я имел в виду стиль хранения логического массива с фактическим значением, которое вас интересует в качестве ключей.
3. Мне очень нравится этот подход к хранению всех включенных блоков, а не к вычислению коллизий. В зависимости от того, как я их сохраняю, редактирование сохраненных блоков может быть сложной операцией. Но редактирование томов происходит редко и может занять минуту или две, без проблем. Это переводит обработку на этот шаг, делая часть «обнаружение столкновений» потенциально намного быстрее. Возможно, я даже смогу хранить координаты в двоичном формате с возможностью поиска, чтобы сделать вычисления действительно быстрыми.
4. @MrLore Простое использование массива логических значений не делает что-то связанным с ситом.
Ответ №2:
В общем, вы должны использовать структуру данных, подобную деревьям kd. Вы можете представить свой объем как объединение кубов или сфер, и должно быть легко оценить, входит ли объект в объем.
Кстати, чтобы вычислить, пересекаются ли две сферы, проверьте, меньше ли расстояние между центрами суммы радиусов.