Estou criando um mecanismo semelhante ao Minecraft no XNA. O que eu quero fazer é criar ilhas flutuantes semelhantes à mostrada neste vídeo:
http://www.youtube.com/watch?v=gqHVOEPQK5g&feature=related
Como eu replicaria isso usando um gerador mundial? Eu precisaria usar algum algoritmo de ruído Perlin? Não sei como isso me ajudaria a formar massas de terra assim.
Aqui está o código para o gerador de ruído perlin que estou usando:
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; } }
Mas o problema é que o autor do código usa o seguinte para gerar ruído, e eu não o entendo nem um pouco.
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;
}
E aqui está o site que estou usando: http://lotsacode.wordpress.com/2010/02/24/perlin-noise-in-c/ .
E estou tentando implementar o ruído perlin da maneira especificada por Martin Sojka.
Ok, então é isso que eu tenho até agora:
Algo assim seria suficiente?
Nesse caso, consulte este artigo . Citando as partes mais relevantes:
fonte
Pseudocódigo para a etapa 2:
Depois que suas ilhas terminarem de gerar, você poderá alterná-las para cima e para baixo no espaço para tê-las em diferentes alturas.
fonte