Ich erstelle eine Minecraft-ähnliche Engine in XNA. Ich möchte schwimmende Inseln erstellen, die der in diesem Video gezeigten ähneln:
http://www.youtube.com/watch?v=gqHVOEPQK5g&feature=related
Wie würde ich dies mit einem Weltgenerator replizieren? Muss ich einen Perlin-Rauschalgorithmus verwenden? Ich weiß nicht, wie das mir helfen würde, solche Landmassen zu schaffen.
Hier ist der Code für den Perlin-Rauschgenerator, den ich verwende:
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; } }
Aber die Sache ist, dass der Autor des Codes das Folgende verwendet, um Rauschen zu erzeugen, und ich verstehe es nicht im geringsten.
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;
}
Und hier ist die Seite, die ich benutze: http://lotsacode.wordpress.com/2010/02/24/perlin-noise-in-c/ .
Und ich versuche, Perlin-Rauschen wie von Martin Sojka beschrieben umzusetzen.
Ok, so weit bin ich gekommen: