在Java中平滑随机生成的地形以获得逼真的效果

时间:2014-10-27 22:32:10

标签: java random terrain

我想帮助平滑我的随机地形,使其看起来更逼真。目前我只是将随机值分配给数组并将tile设置为存储在数组中的值。

这会产生这种效果:

too random terrain

protected void generateLevel() {
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int rand = random.nextInt(1000); //height
            if(rand <= 300){ //water level
                tiles[x + y * width] = 6;//set water
            }else{
                tiles[x + y * width] = 1; //set grass
            }
        }   
   }   
}

请帮助我让我的地形看起来更逼真,我想看看他们如何将这个实现到他们的游戏或我的游戏中。如何平滑地形以获得逼真的效果?

2 个答案:

答案 0 :(得分:3)

您可以考虑使用perlin or simplex noise,而不是使用随机的每个点的地形。无论您以何种顺序阅读地图,这都具有流畅,可复制的优点,并且可以使用给定的起始“混洗数组”进行复制。 this post提供了非常好的描述和实现。

答案 1 :(得分:0)

使用OpenSimplex噪音:https://gist.github.com/KdotJPG/b1270127455a94ac5d19

做类似的事情:

protected void generateLevel() {
    OpenSimplexNoise noise = new OpenSimplexNoise(); //optionally pass in a seed.
    for (int y = 0 y < height; y++) {
        for (int x = 0; x < width; x++) {
            double value = noise.eval(x / 24.0, y / 24.0, 0.5);
            if (value < 0) {
                tiles[x + y * width] = 6; //set water
            } else {
                tiles[x + y * width] = 1; //set grass
            }
        }
    }
}

还有Perlin噪音和单纯噪音等替代品。我完全跳过Perlin噪声,因为它往往会出现视觉上重要的网格伪影(它的所有特征都与其底层方形网格对齐)。 2D中的单纯形噪声是可以的,尽管互联网上大多数2D单纯形噪声的实现使用了一个奇怪的梯度集,导致负对角线下的伪影。而3D单面噪音是专利背负的。

Perlin噪声与OpenSimplex噪声,2D切片3D: enter image description here

  • 左边是噪声(x,y,0)灰度
  • 接下来是噪声(x,y,0)&gt; 0?白色:黑色
  • 接下来是| noise(x,y,0)| &GT; 0.1?白色:黑色
  • 接下来是噪声(x,y,0.5)灰度

编辑:这是评论中的代码

分形噪音:

OpenSimplexNoise n1 = new OpenSimplexNoise(seed1);
OpenSimplexNoise n2 = new OpenSimplexNoise(seed2);
OpenSimplexNoise n3 = new OpenSimplexNoise(seed3);

for each x,y {
    double value = (n1.eval(x / 48.0, y / 48.0, 0.5) + n2.eval(x / 24.0, y / 24.0, 0.5) * .5 + n3.eval(x / 12.0, y / 12.0, 0.5) * .25) / (1 + .5 + .25);
    //Do whatever you need to with that value
}

河流:

if (value > -0.1 || value < 0.1)
    water
else
    land

生物群

OpenSimplexNoise n1 = new OpenSimplexNoise(seed1);
OpenSimplexNoise n2 = new OpenSimplexNoise(seed2);
OpenSimplexNoise n3 = new OpenSimplexNoise(seed3);

for each x,y {
    double elevation = n1.eval(x / 24.0, y / 24.0, 0.5);
    double temperature = n2.eval(x / 24.0, y / 24.0, 0.5);
    double precipitation = n3.eval(x / 24.0, y / 24.0, 0.5);

    if (elevation < 0)
        water
    else {
        //decide biome based on temperature, precipitation, and elevation
    }
}