В последние недели я разрабатывал генератор мира (для мода Minecraft). Тем не менее, я искал не просто шум Перлина, а что-то, основанное на шуме клетки. Я хочу создать своего рода подземную лабораторию, состоящую из нескольких комнат разных размеров.
Чтобы объяснить проблему, я использую 2D-примеры.
Генератор шума занимает положение ячейки сетки (int x, int y
) и возвращает объект с такой структурой:
boolean top;
boolean right;
boolean down;
boolean left;
int roomType;
4 логических значения представляют собой стены, которые включены или отключены:
The roomType
represents the type of the room respectively.
The final result should be something like this:
Здесь фоновый рисунок шахматной доски представляет базовую сетку, а черные линии представляют стены. Это простой пример, который можно сгенерировать, но в реальном случае сетка бесконечна в обоих направлениях x и y .
Проблема, которую я получаю сейчас, состоит в том, что генератор шума принимает только координаты x и y, которые являются координатами ячейки сетки, которую он должен генерировать. Есть семя, из которого я могу генерировать больше случайных семян для хеш-функций:
long seed = 0x75fd239de48;
Random r = new Random(seed);
int seed1 = r.nextInt();
int seed2 = r.nextInt();
// etc.
Я мог бы использовать хеш-функцию: Hash.hash2D(int seed, int x, int y)
, которая возвращает случайное значение double
для координаты в соответствии с начальным числом.
Это даст возможность генерировать информацию для окружающих ячеек.
Чтобы легко создавать комнаты большего размера, вы можете установить максимальный размер комнаты и проверить область для комнат, которые пытаются быть больше, чем 1x1. Если они там и будут охватывать текущую комнату, эта комната будет продолжением другой комнаты. Однако проверка того, будет ли комната расширяться, требует проверки того, не расширяется ли она (в противном случае нежелательные расширения комнаты появляются в базах комнат, которые расширяют другую), что приводит к бесконечному циклу.
В моем случае есть таблица типов комнат, их размеров и веса. Пример:
name: size [weight]
room-1: 1x1 [128]
room-2: 1x1 [128]
room-3: 2x1 [16]
room-4: 1x2 [16]
room-5: 2x2 [8]
room-6: 3x1 [4]
room-7: 1x3 [4]
Есть много других, с размерами до 5x5, но я использую этот список примеров для моего вопроса. Максимальный размер в этом примере - 3x3 (только max-width и max-height).
Здесь у меня есть пример класса некоторых базовых настроек в Java:
public class RoomNoise {
private final long seed;
private final Random rand;
public RoomNoise( long seed ) {
this.seed = seed;
this.rand = new Random( seed );
}
public enum RoomTypes {
ROOM1( 1, 1, 128 ),
ROOM2( 1, 1, 128 ),
ROOM3( 2, 1, 16 ),
ROOM4( 1, 2, 16 ),
ROOM5( 2, 2, 8 ),
ROOM6( 1, 3, 4 ),
ROOM7( 3, 1, 4 );
public final int width;
public final int height;
public final int weight;
private RoomTypes( int w, int h, int weight ) {
width = w;
height = h;
this.weight = weight;
}
}
public static class Output {
public final RoomTypes roomType;
public final boolean upWall;
public final boolean rightWall;
public final boolean downWall;
public final boolean leftWall;
public Output( RoomTypes type, boolean u, boolean r, boolean d, boolean l ) {
roomType = type;
upWall = u;
rightWall = r;
downWall = d;
leftWall = l;
}
}
public Output generate( int x, int y ) {
// What should be here
}
}
Я ищу содержимое метода generate
, для которого я пробовал много вещей, но каждый раз я превращался в бесконечный цикл, или он не работал.
Есть ли способ создать этот шум в O(N)
с N
меньше бесконечности? И если есть способ, то какой это путь и как я могу его реализовать? Я искал в интернете и много раз пробовал (уже 3 недели) и до сих пор не нашел решения.
Я использую Java 1.8, но я предпочитаю любой язык в стиле C.
Опять же, у меня есть эта хеш-функция:
Hash.hash2D( int seed, int x, int y );
Edit:
Ожидаемый результат:
Синие линии - это коридоры, которые генерируются позже. Просто забудь их.
Примечание:
Я не могу загружать и удалять чанки (ячейки сетки) вручную, базовый API (Minecraft) делает это для меня. Это только дает мне координату (которая зависит от взаимодействия с игроком), и я должен вернуть (часть a) комнату, которая соответствует куску по этой координате. Я также знаю, что как только порция генерируется, она не генерируется снова.