package com.galvarez.ttw.model.map;
import com.badlogic.gdx.math.MathUtils;
import com.galvarez.ttw.utils.MyMath;
public class MidpointDisplacement {
public float smoothness;
public MidpointDisplacement() {
// Smoothness controls how smooth the resultant terrain is.
// Higher = smoother
smoothness = 2f;
}
public float[][] getMap2(int n, int wmult, int hmult) {
// get the dimensions of the map
int power = MyMath.pow(2, n);
int width = wmult * power + 1;
int height = hmult * power + 1;
// initialize arrays to hold values
float[][] map = new float[width][height];
int step = power / 2;
float sum;
int count;
// h determines the fineness of the scale it is working on. After every
// step, h is decreased by a factor of "smoothness"
float h = 1;
// Initialize the grid points
for (int i = 0; i < width; i += 2 * step) {
for (int j = 0; j < height; j += 2 * step) {
map[i][j] = MathUtils.random(2 * h);
}
}
// Do the rest of the magic
while (step > 0) {
// Diamond step
for (int x = step; x < width; x += 2 * step) {
for (int y = step; y < height; y += 2 * step) {
sum = map[x - step][y - step] + // down-left
map[x - step][y + step] + // up-left
map[x + step][y - step] + // down-right
map[x + step][y + step]; // up-right
map[x][y] = sum / 4 + MathUtils.random(-h, h);
}
}
// Square step
for (int x = 0; x < width; x += step) {
for (int y = step * (1 - (x / step) % 2); y < height; y += 2 * step) {
sum = 0;
count = 0;
if (x - step >= 0) {
sum += map[x - step][y];
count++;
}
if (x + step < width) {
sum += map[x + step][y];
count++;
}
if (y - step >= 0) {
sum += map[x][y - step];
count++;
}
if (y + step < height) {
sum += map[x][y + step];
count++;
}
if (count > 0)
map[x][y] = sum / count + MathUtils.random(-h, h);
else
map[x][y] = 0;
}
}
h /= smoothness;
step /= 2;
}
// Normalize the map
normalize(map);
return map;
}
/**
* Modify the map values to have only values between 0.0 and 1.0 while keeping
* the proportion between the different values.
*/
public static void normalize(float[][] map) {
float max = Float.MIN_VALUE;
float min = Float.MAX_VALUE;
for (float[] row : map) {
for (float d : row) {
if (d > max)
max = d;
if (d < min)
min = d;
}
}
for (int x = 0; x < map.length; x++) {
for (int y = 0; y < map[0].length; y++) {
map[x][y] = (map[x][y] - min) / (max - min);
}
}
}
}