Я создаю Minecraft-подобный движок в XNA. Я хочу создать плавающие острова, похожие на те, что показаны в этом видео:
http://www.youtube.com/watch?v=gqHVOEPQK5g&feature=related
Как бы я повторил это с помощью генератора мира? Должен ли я использовать какой-нибудь алгоритм шума Перлина? Я не знаю, как это помогло бы мне создать такие массы земли.
Вот код для генератора шума Perlin, который я использую:
private double[,] noiseValues;
private float amplitude = 1; // Max amplitude of the function
private int frequency = 1; // Frequency of the function
/// <summary>
/// Constructor
/// </summary>
///
public PerlinNoise(int freq, float _amp)
{
Random rand = new Random(System.Environment.TickCount);
noiseValues = new double[freq, freq];
amplitude = _amp;
frequency = freq;
// Generate our noise values
for (int i = 0; i < freq; i++)
{
for (int k = 0; k < freq; k++)
{
noiseValues[i, k] = rand.NextDouble();
}
}
}
/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
public double getInterpolatedPoint(int _xa, int _xb, int _ya, int _yb, double x, double y)
{
double i1 = interpolate(
noiseValues[_xa % Frequency, _ya % frequency],
noiseValues[_xb % Frequency, _ya % frequency]
, x);
double i2 = interpolate(
noiseValues[_xa % Frequency, _yb % frequency],
noiseValues[_xb % Frequency, _yb % frequency]
, x);
return interpolate(i1, i2, y);
}
public static double[,] SumNoiseFunctions(int width, int height, List<PerlinNoise> noiseFunctions)
{
double[,] summedValues = new double[width, height];
// Sum each of the noise functions
for (int i = 0; i < noiseFunctions.Count; i++)
{
double x_step = (float)width / (float)noiseFunctions[i].Frequency;
double y_step = (float)height / (float)noiseFunctions[i].Frequency;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int a = (int)(x / x_step);
int b = a + 1;
int c = (int)(y / y_step);
int d = c + 1;
double intpl_val = noiseFunctions[i].getInterpolatedPoint(a, b, c, d, (x / x_step) - a, (y / y_step) - c);
summedValues[x, y] += intpl_val * noiseFunctions[i].Amplitude;
}
}
}
return summedValues;
}
/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
private double interpolate(double a, double b, double x)
{
double ft = x * Math.PI;
double f = (1 - Math.Cos(ft)) * .5;
// Returns a Y value between 0 and 1
return a * (1 - f) + b * f;
}
public float Amplitude { get { return amplitude; } }
public int Frequency { get { return frequency; } }
Но дело в том, что автор кода использует следующее для генерации шума, и я совсем не понимаю его.
private Block[, ,] GenerateLandmass()
{
Block[, ,] blocks = new Block[300, 400, 300];
List<PerlinNoise> perlins = new List<PerlinNoise>();
perlins.Add(new PerlinNoise(36, 29));
perlins.Add(new PerlinNoise(4, 33));
double[,] noisemap = PerlinNoise.SumNoiseFunctions(300, 300, perlins);
int centrey = 400 / 2;
for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short y = 0; y < blocks.GetLength(1); y++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, y, z] = new Block(BlockType.none);
}
}
}
for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, centrey - (int)noisemap[x, z], z].BlockType = BlockType.stone;
}
}
//blocks = GrowLandmass(blocks);
return blocks;
}
И вот сайт, который я использую: http://lotsacode.wordpress.com/2010/02/24/perlin-noise-in-c/ .
И я пытаюсь реализовать перлин-шум способом, указанным Мартином Сойкой.
Итак, вот что я получил:
Будет ли что-то подобное достаточно?
Если это так, проверьте эту статью . Цитируем наиболее актуальные части:
источник
Псевдокод для шага 2:
Как только ваши острова закончили генерировать, вы можете по желанию сдвинуть их вверх и вниз в пространстве, чтобы они были на разной высоте.
источник