如何随着无限地图的增长而不断产生柏林噪声?



编辑:我最终使用了在这里找到的FastNoise库: https://github.com/Auburns/FastNoise 它拥有阳光下的一切,有人可能需要产生许多不同类型的噪音。正如标题可能暗示的那样,它也很快!

我正在创建一个无限的2D,程序生成的世界。当播放器移动时,我从光盘中加载和卸载块。我正在使用元胞自动机函数来定义每个块中的局部图块是如何设计的,但我需要噪声(在本例中为柏林(来定义每个块在创建新块时将是什么生物群落类型。我了解如何将 0 和 1 之间的小数转换为表示这一点,我唯一的问题是我在创建 Perlin 噪声时遵循的教程要求您向其传递预定义的 2d 数组并返回相同大小的噪声数组。因为我的世界是动态增长的,所以我对如何使用固定大小的数组来指定新的块类型有点困惑。

我看到的其他答案并没有确切地涵盖如何处理噪声产生的无限部分。我最好的猜测是,我需要以某种方式为每个新创建的块生成或扩展噪音,尽管我如何做到这一点让我感到困惑。

以下是我从这里翻译成 C# 的一些代码:http://devmag.org.za/2009/04/25/perlin-noise/

诚然,这里的一些数学我还不完全理解,尤其是按位函数!

public class PerlinNoiseGenerator
{
public int OctaveCount { get; set; }
public float Persistence { get; set; }

public PerlinNoiseGenerator(int octaveCount, float persistence)
{
this.OctaveCount = octaveCount;
this.Persistence = persistence;
}
public float[,] GenerateWhiteNoise(int width, int height)
{
float[,] noiseFieldToReturn = new float[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
noiseFieldToReturn[i, j] = (float)Game1.Utility.RGenerator.NextDouble() % 1;
}
}
return noiseFieldToReturn;
}
public float[,] SmoothNoiseField(float[,] whiteNoise, int octave)
{
int width = whiteNoise.GetLength(0);
int height = whiteNoise.GetLength(1);
float[,] smoothField = new float[width, height];
int samplePeriod = 1 << octave;
float sampleFrequency = 1.0f / samplePeriod;
for(int i =0; i < width; i++)
{
int samplei0 = (i / samplePeriod) * samplePeriod;
int samplei1 = (samplei0 + samplePeriod) % width;
float horizontalBlend = (i - samplei0) * sampleFrequency;
for(int j =0; j < height; j++)
{
int samplej0 = (j/samplePeriod) * samplePeriod;
int samplej1 = (samplej0 + samplePeriod) % height;
float verticalBlend = (j - samplej0) * sampleFrequency;
float top = LinearInterpolate(whiteNoise[samplei0, samplej0],
whiteNoise[samplei1, samplej0], horizontalBlend);
float bottom = LinearInterpolate(whiteNoise[samplei0, samplej1],
whiteNoise[samplei1, samplej1], horizontalBlend);
smoothField[i, j] = LinearInterpolate(top, bottom, verticalBlend);
}
}
return smoothField;
}
public float[,] GeneratePerlinNoise(float[,] baseNoise, int octaveCount)
{
int width = baseNoise.GetLength(0);
int height = baseNoise.GetLength(1);
float[][,] smoothNoise = new float[octaveCount][,];
float persistance = .5f;
for(int i =0; i < octaveCount;i++)
{
smoothNoise[i] = SmoothNoiseField(baseNoise, i);
}
float[,] perlinNoise = new float[width, height];
float amplitude = 1f;
float totalAmplitude = 0.0f;
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;
}
}
}
for(int i =0; i < width; i++)
{
for(int j =0; j < height; j++)
{
perlinNoise[i, j] /= totalAmplitude;
}
}
return perlinNoise;
}
public float LinearInterpolate(float a, float b, float alpha)
{
return a * (1 - alpha) + alpha * b;
}
} 

此代码应编译并生成固定大小的噪声数组

您要确保的主要事情是起始随机噪声是伪随机的,因此坐标始终具有"固定随机值"。

您可能必须使用坐标作为输入来重写随机噪声发生器。我想你的地图有一个随机的种子数,所以你可以用这篇文章作为起点,加上 1 个因素: 基于2个输入的伪随机数生成器

为了给您制作地图提供一些灵感,我不久前写了这篇文章:https://steemit.com/map/@beeheap/create-a-fantasy-grid-map-in-excel

在您的评论后添加:您唯一需要更改的功能是GenerateWhiteNoise。我不会说 C#,但这是一般的想法:

GenerateWhiteNoise(int x_start_coord, int y_start_coord, int random_seed) {
int default_x_width = 100;
int default_y_heigth = 50;
float[,] noiseFieldToReturn = new float[width, height];
for (in x = x_start_coord; i < default_x_width + x_start_coord; x++)
{
for (in y = y_start_coord; i < default_y_width + y_start_coord; y++)
{
noiseFieldToReturn[i, j] = (float)pseudo_rnd_value(x, y, random_seed);
}
}
return noiseFieldToReturn;
}

这应该为您提供构建地图图块所需的伪随机值,您唯一需要的是玩家的坐标(x 和 y(。

最新更新