|
@@ -1,186 +1,107 @@
|
|
|
-package speedtester;
|
|
|
+package pathgame.tilemap;
|
|
|
|
|
|
-import java.awt.image.BufferedImage;
|
|
|
-import java.io.File;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.Arrays;
|
|
|
import java.util.Random;
|
|
|
-import javax.imageio.ImageIO;
|
|
|
|
|
|
public class HighMap
|
|
|
{
|
|
|
+ public static HighMap generate(int width, int height, float zoom)
|
|
|
+ {
|
|
|
+ HighMap map = new HighMap(width, height);
|
|
|
+ map.zoom(zoom);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
private final int width;
|
|
|
private final int height;
|
|
|
- private float data[][];
|
|
|
- private Random r = new Random(0);
|
|
|
+ private final float data[][];
|
|
|
+ private final Random r = new Random(0);
|
|
|
|
|
|
- public HighMap(int width, int height)
|
|
|
+ private HighMap(int width, int height)
|
|
|
{
|
|
|
this.width = width;
|
|
|
this.height = height;
|
|
|
this.data = new float[width][height];
|
|
|
}
|
|
|
|
|
|
- public void smooth(int radius)
|
|
|
+ public float get(int x, int y)
|
|
|
{
|
|
|
- float[][] newData = new float[width][height];
|
|
|
-
|
|
|
- for(int x = 0; x < width; x++)
|
|
|
- {
|
|
|
- for(int y = 0; y < height; y++)
|
|
|
- {
|
|
|
- int div = 0;
|
|
|
- float sum = 0;
|
|
|
- for(int mx = -radius; mx <= radius; mx++)
|
|
|
- {
|
|
|
- for(int my = -radius; my <= radius; my++)
|
|
|
- {
|
|
|
- if(x + mx >= 0 && x + mx < width && y + my >= 0 && y + my < height)
|
|
|
- {
|
|
|
- sum += data[x + mx][y + my];
|
|
|
- div++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- sum /= div;
|
|
|
- newData[x][y] = sum;
|
|
|
- }
|
|
|
- }
|
|
|
- data = newData;
|
|
|
+ return data[x][y];
|
|
|
}
|
|
|
|
|
|
- public void randomize(int bound)
|
|
|
+ private float[][] randomizeBase()
|
|
|
{
|
|
|
+ float[][] base = new float[width][height];
|
|
|
for(int x = 0; x < width; x++)
|
|
|
{
|
|
|
for(int y = 0; y < height; y++)
|
|
|
{
|
|
|
- data[x][y] = r.nextInt(bound);
|
|
|
+ base[x][y] = r.nextFloat();
|
|
|
}
|
|
|
}
|
|
|
+ return base;
|
|
|
}
|
|
|
|
|
|
- public BufferedImage export()
|
|
|
+ private float smooth(float[][] base, float x1, float y1)
|
|
|
{
|
|
|
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
|
|
|
-
|
|
|
- float min = Float.MAX_VALUE;
|
|
|
- float max = Float.MIN_VALUE;
|
|
|
-
|
|
|
- for(int x = 0; x < width; x++)
|
|
|
- {
|
|
|
- for(int y = 0; y < height; y++)
|
|
|
- {
|
|
|
- if(data[x][y] < min)
|
|
|
- {
|
|
|
- min = data[x][y];
|
|
|
- }
|
|
|
- if(data[x][y] > max)
|
|
|
- {
|
|
|
- max = data[x][y];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- float div = 255.0f / (max - min);
|
|
|
-
|
|
|
- for(int x = 0; x < width; x++)
|
|
|
- {
|
|
|
- for(int y = 0; y < height; y++)
|
|
|
- {
|
|
|
- int base = (int) ((data[x][y] - min) * div);
|
|
|
- image.setRGB(x, y, 0xFF000000 | (base << 16) | (base << 8) | base);
|
|
|
- }
|
|
|
- }
|
|
|
+ // 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;
|
|
|
|
|
|
- return image;
|
|
|
+ // 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;
|
|
|
}
|
|
|
|
|
|
- public void threshold(int levels)
|
|
|
+ private float turbulence(float[][] base, float x1, float y1, float factor)
|
|
|
{
|
|
|
- float[] values = new float[width * height];
|
|
|
- int counter = 0;
|
|
|
- for(int x = 0; x < width; x++)
|
|
|
+ float sum = 0.0f;
|
|
|
+ while(factor >= 1)
|
|
|
{
|
|
|
- for(int y = 0; y < height; y++)
|
|
|
- {
|
|
|
- values[counter++] = data[x][y];
|
|
|
- }
|
|
|
- }
|
|
|
- Arrays.sort(values);
|
|
|
-
|
|
|
- float[] borders = new float[levels];
|
|
|
- for(int i = 0; i < levels - 1; i++)
|
|
|
- {
|
|
|
- borders[i] = values[(int) (((i + 1.0f) / levels) * values.length)];
|
|
|
- }
|
|
|
- borders[borders.length - 1] = Float.MAX_VALUE;
|
|
|
-
|
|
|
- for(int x = 0; x < width; x++)
|
|
|
- {
|
|
|
- for(int y = 0; y < height; y++)
|
|
|
- {
|
|
|
- for(int i = 0; i < borders.length; i++)
|
|
|
- {
|
|
|
- if(data[x][y] < borders[i])
|
|
|
- {
|
|
|
- data[x][y] = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ sum += smooth(base, x1 / factor, y1 / factor) * factor;
|
|
|
+ factor *= 0.5f;
|
|
|
}
|
|
|
+ return sum;
|
|
|
}
|
|
|
|
|
|
- public BufferedImage colorExport(int scale, int... colors)
|
|
|
+ private void zoom(float factor)
|
|
|
{
|
|
|
- BufferedImage image = new BufferedImage(width * scale, height * scale, BufferedImage.TYPE_4BYTE_ABGR);
|
|
|
+ float[][] base = randomizeBase();
|
|
|
|
|
|
- float[] values = new float[width * height];
|
|
|
- int counter = 0;
|
|
|
+ float min = Float.MAX_VALUE;
|
|
|
+ float max = Float.MIN_VALUE;
|
|
|
+
|
|
|
for(int x = 0; x < width; x++)
|
|
|
{
|
|
|
for(int y = 0; y < height; y++)
|
|
|
{
|
|
|
- values[counter++] = data[x][y];
|
|
|
+ float f = turbulence(base, x, y, factor);
|
|
|
+ data[x][y] = f;
|
|
|
+ if(f < min)
|
|
|
+ {
|
|
|
+ min = f;
|
|
|
+ }
|
|
|
+ if(f > max)
|
|
|
+ {
|
|
|
+ max = f;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- Arrays.sort(values);
|
|
|
|
|
|
- float[] borders = new float[colors.length];
|
|
|
- for(int i = 0; i < colors.length - 1; i++)
|
|
|
- {
|
|
|
- borders[i] = values[(int) (((i + 1.0f) / colors.length) * values.length)];
|
|
|
- }
|
|
|
- borders[borders.length - 1] = Float.MAX_VALUE;
|
|
|
-
|
|
|
+ float f = 1.0f / (max - min);
|
|
|
for(int x = 0; x < width; x++)
|
|
|
{
|
|
|
for(int y = 0; y < height; y++)
|
|
|
{
|
|
|
- for(int i = 0; i < borders.length; i++)
|
|
|
- {
|
|
|
- if(data[x][y] < borders[i])
|
|
|
- {
|
|
|
- for(int mx = 0; mx < scale; mx++)
|
|
|
- {
|
|
|
- for(int my = 0; my < scale; my++)
|
|
|
- {
|
|
|
- image.setRGB(x * scale + mx, y * scale + my, colors[i]);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ data[x][y] = (data[x][y] - min) * f;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return image;
|
|
|
- }
|
|
|
-
|
|
|
- public void save(int scale, String name) throws IOException
|
|
|
- {
|
|
|
- BufferedImage image = colorExport(scale, 0xFF131ec1, 0xFF131ee0, 0xFF39aa38, 0xFFa57c4d, 0xFF50463a);
|
|
|
- ImageIO.write(image, "png", new File(name + ".png"));
|
|
|
}
|
|
|
}
|