# Tile-basierte, zufällige Levelgenerierung



## JavaKiwi (2. Nov 2013)

Nabend! 

Ich programmiere einen Terraria-Klon und stecke beim Erstellen des Levels fest.
Mit meinen eigenen Methoden wird soweit eine ganz ordentliche, zufällige Grasfläche mit Erde darunter erstellt. Jetzt wären die Höhlen dran, aber genau da komme ich mit meinen eigenen Methoden nicht weiter. Um diese "Noise"-Methode oder um Interpolation werde ich wohl nicht rumkommen - die Frage ist aber: Wie implementiere ich das?
Ich möchte das jetzt professionell lösen. 

Wie wird so ein Level-Image erstellt (ein Bild, auf welchem jedem Pixel mit seiner Farbe ein Tile zugeordnet wird)?

Am meisten würde mir eine generelle Beschreibung des Vorgehens helfen. 

Vielen Dank, und hoffentlich schaffe ich das!


----------



## BuddaKaeks (4. Nov 2013)

Du hast einen Zufallszahkengenerator, der wie folgt aufgebaut ist:

public int getRandom(int x, int y);

Dieser zufallsgenerator liefert für 2 ganze Zahlen x, y immer den selben wert

nun nimmst du für jedes 10. Tile folgenden wert

tiles[i*10][j*10] = getRandom(i, j);

dann interpolierst du.


----------



## BuddaKaeks (4. Nov 2013)

Spoiler: Noise





```
public class NoiseGenPerlin{
	
	private NoiseGenPerlin() {
	}
	
	public static long seed = 0;
	
	public static void setSeed(final long nSeed) {
		seed = nSeed;
	}
	
	public static double getNoise(final double x, final double y,
	        final int numOfOctaves, final double persistence) {
		double total = 0;
		int frequency;
		double amplitude;
		for (int i = 0; i < numOfOctaves; i++) {
			frequency = (int) Math.pow(2, i);
			amplitude = Math.pow(persistence, i);
			total += (interpolate2D(x * frequency, y * frequence) * amplitude);
		}
		return total;
	}
	
	private static double rand2D(final int x, final int y) {
		long n = x + (y * 57) + seed;
		n = (n << 13) ^ n;
		double tmp = 1.0f - ((((n * ((n * n * 15731) + 789221)) + 1376312589) & 0x7fffffff) / 1073741824.0f);
		return tmp > 0 ? tmp : -tmp;
	}
	
	private static double interpolate1D(final double a, final double b,
	        final double x) {
		final double ft = x * Math.PI;
		final double f = (1 - Math.cos(ft)) * .5f;
		return (a * (1 - f)) + (b * f);
	}
	
	private static double smooth(final int x, final int y) {
		final double corners = (rand2D(x - 1, y - 1)
		        + rand2D(x + 1, y - 1) + rand2D(x - 1, y + 1) + rand2D(
		        x + 1, y + 1)) / 16f;
		final double sides = (rand2D(x - 1, y) + rand2D(x + 1, y)
		        + rand2D(x, y - 1) + rand2D(x, y + 1)) / 8f;
		final double center = rand2D(x, y) / 4f;
		return corners + sides + center;
	}
	
	private static double interpolate2D(final double x, final double y) {
		int integerX = (int) x;
		if (integerX > x) {
			integerX--;
		}
		final double fractionalX = x - integerX;
		
		int integerY = (int) y;
		if (integerY > y) {
			integerY--;
		}
		final double fractionalY = (y - integerY);
		
		final double v1 = smooth(integerX, integerY);
		final double v2 = smooth(integerX + 1, integerY);
		final double v3 = smooth(integerX, integerY + 1);
		final double v4 = smooth(integerX + 1, integerY + 1);
		
		final double i1 = interpolate1D(v1, v2, fractionalX);
		final double i2 = interpolate1D(v3, v4, fractionalX);
		
		return interpolate1D(i1, i2, fractionalY);
	}
	
}
```


----------

