12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- package pathgame.tilemap;
- import java.util.Random;
- public class HighMap {
- private static final float LOW_FREQUENCY = 8.0f;
- private static final float HIGH_FREQUENCY = 7.0f;
- public static HighMap generate(long seed, int width, int height) {
- HighMap map = new HighMap(seed, width, height);
- map.zoom();
- return map;
- }
- private final int width;
- private final int height;
- private final float data[][];
- private final Random r;
- private HighMap(long seed, int width, int height) {
- r = new Random(seed);
- this.width = width;
- this.height = height;
- this.data = new float[width][height];
- }
- public float get(int x, int y) {
- return data[x][y];
- }
- private float[][] randomizeBase() {
- int w = (int) Math.ceil(width / HIGH_FREQUENCY) + 1;
- int h = (int) Math.ceil(height / HIGH_FREQUENCY) + 1;
- float[][] base = new float[w][h];
- for(int x = 0; x < w; x++) {
- for(int y = 0; y < h; y++) {
- base[x][y] = r.nextFloat();
- }
- }
- return base;
- }
- private float smooth(float[][] base, float x1, float y1) {
- // distance to next exact pixel
- float fractX = x1 - (int) x1;
- float fractY = y1 - (int) y1;
- // neighbour pixel coords
- int x2 = ((int) x1 + 1) % width;
- int y2 = ((int) y1 + 1) % height;
- // interpolate over all 4 pixels, strength varies with distance
- float value = 0.0f;
- value += (1 - fractX) * (1 - fractY) * base[(int) x1][(int) y1];
- value += (1 - fractX) * fractY * base[(int) x1][(int) y2];
- value += fractX * (1 - fractY) * base[(int) x2][(int) y1];
- value += fractX * fractY * base[(int) x2][(int) y2];
- return value;
- }
- private float turbulence(float[][] base, float x1, float y1) {
- float sum = 0.0f;
- sum += smooth(base, x1 / LOW_FREQUENCY, y1 / LOW_FREQUENCY) * LOW_FREQUENCY;
- sum += smooth(base, x1 / HIGH_FREQUENCY, y1 / HIGH_FREQUENCY) * HIGH_FREQUENCY;
- return sum;
- }
- private void zoom() {
- float[][] base = randomizeBase();
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- for(int x = 0; x < width; x++) {
- for(int y = 0; y < height; y++) {
- float f = turbulence(base, x, y);
- data[x][y] = f;
- if(f < min) {
- min = f;
- }
- if(f > max) {
- max = f;
- }
- }
- }
- float f = 1.0f / (max - min);
- for(int x = 0; x < width; x++) {
- for(int y = 0; y < height; y++) {
- data[x][y] = (data[x][y] - min) * f;
- }
- }
- }
- }
|