上周我正在开发一个世界生成器(用于 Minecraft 模组)。但是,我不只是在寻找 Perlin 噪声,而是基于单元噪声的东西。我想生成一种地下实验室,存在几个不同大小的房间。
为了解释这个问题,我使用了 2D 示例。
噪声生成器采用网格单元位置 ( int x, int y
),并返回具有以下结构的对象:
boolean top;
boolean right;
boolean down;
boolean left;
int roomType;
4 个布尔值代表启用或禁用的墙壁:roomType
分别代表房间的类型。
最终的结果应该是这样的:
这里,背景棋盘格图案代表基础网格,黑色线条代表墙壁。这只是一个可以生成的简单示例,但在实际情况下,网格在 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 x 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 );
编辑:
笔记:
我无法手动加载和删除块(网格单元),基本 API(我的世界)正在为我做这件事。它只给了我坐标(这取决于玩家的互动),我应该归还一个适合该坐标处的块的(一部分)房间。我也知道,一旦生成了一个块,就不会再次生成它。