我正在尝试编写多人平局基础java游戏。(只是为了好玩)
使用Perlin Noise创建的世界地图。所以我很感兴趣,我怎样才能创建真正大的地图?
例如要生成带有Perlin噪声的8000x8000地图需要大约 4096Mb的RAM 。
地图表示为[8000] [8000] 数组,但生成后我将其存储在数据库中,但我想在其中创建大约25000x25000个图块的地图。 我可以将地图生成过程划分为更小的部分吗? 问题是我应该在整个地图上使用Perlin噪声,否则地图看起来就像几块,或者如果你对动态地图生成有所了解,请告诉我。 我很惊讶它在Minecraft中是如何工作的(我的意思是新生成的块以某种方式与流行相关)。
这是我的代码:
public static float[][] generateWhiteNoise(int width, int height)
{
Random random = new Random(); //Seed to 0 for testing
float[][] noise = new float[width][height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
noise[i][j] = (float)random.nextDouble() % 1;
}
}
return noise;
}
static float Interpolate(float x0, float x1, float alpha)
{
return x0 * (1 - alpha) + alpha * x1;
}
static float[][] generateSmoothNoise(float[][] baseNoise, int octave)
{
int width = baseNoise.length;
int height = baseNoise[0].length;
float[][] smoothNoise = new float[width][height];
int samplePeriod = 1 << octave; // calculates 2 ^ k
float sampleFrequency = 1.0f / samplePeriod;
for (int i = 0; i < width; i++)
{
//calculate the horizontal sampling indices
int sample_i0 = (i / samplePeriod) * samplePeriod;
int sample_i1 = (sample_i0 + samplePeriod) % width; //wrap around
float horizontal_blend = (i - sample_i0) * sampleFrequency;
for (int j = 0; j < height; j++)
{
//calculate the vertical sampling indices
int sample_j0 = (j / samplePeriod) * samplePeriod;
int sample_j1 = (sample_j0 + samplePeriod) % height; //wrap around
float vertical_blend = (j - sample_j0) * sampleFrequency;
//blend the top two corners
float top = Interpolate(baseNoise[sample_i0][sample_j0],
baseNoise[sample_i1][sample_j0], horizontal_blend);
//blend the bottom two corners
float bottom = Interpolate(baseNoise[sample_i0][sample_j1],
baseNoise[sample_i1][sample_j1], horizontal_blend);
//final blend
smoothNoise[i][j] = Interpolate(top, bottom, vertical_blend);
}
}
return smoothNoise;
}
static float[][] generatePerlinNoise(float[][] baseNoise, int octaveCount)
{
int width = baseNoise.length;
int height = baseNoise[0].length;
float[][][] smoothNoise = new float[octaveCount][][]; //an array of 2D arrays containing
float persistance = 0.5f;
//generate smooth noise
for (int i = 0; i < octaveCount; i++)
{
smoothNoise[i] = generateSmoothNoise(baseNoise, i);
}
float[][] perlinNoise = new float[width][height];
float amplitude = 1.0f;
float totalAmplitude = 0.0f;
//blend noise together
for (int octave = octaveCount - 1; octave >= 0; octave--)
{
amplitude *= persistance;
totalAmplitude += amplitude;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] += smoothNoise[octave][i][j] * amplitude;
}
}
}
//normalisation
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] /= totalAmplitude;
}
}
return perlinNoise;
}
答案 0 :(得分:1)
现在,您可能正在使用java.util.Random生成噪音。您需要将其替换为mixing function。你的perlin噪音发生器应该是无状态功能。像这样:
int noise(int x, int y) {
return (x*31)^(y*41); // mix x and y pseudorandomly
}
double smoothNoise(double x, double y) {
return noise(floor(x),floor(y)) * fract(x) + ... // interpolate
}
double perlinNoise(double x, double y) {
return smoothNoise(x,y)*0.5 +
smoothNoise(x/2,y/2)*0.25 + ... // add octaves
}
这样,您可以随时拨打perlinNoise
,并始终返回相同的结果。这样您就可以在没有可见接缝的情况下以块的形式生成地图。
答案 1 :(得分:0)
我看到两个选项:
我的投票转到了数据库。