2D单纯形光滑洞穴生成

所以我在随机地形下创建了一个洞穴系统,我使用2D Simplex Noise来完成这个任务,而且我对生成随机洞穴有很好的把握。 然而,从地形到洞穴层开始的地方有点突然,我想知道如何防止这种情况发生。

随机等级生成:

public static Level GetRandomLevel(int rows, int cols, float scale = 1f) { Tile[][] tiles = new Tile[rows][]; for (int i = 0; i < rows; i++) { tiles[i] = new Tile[cols]; for (int x = 0; x < cols; x++) { tiles[i][x] = new Tile(0, new Vector2(x, i), scale); } } int left = Main.rand.Next(rows / 4, rows / 2); double seed = Main.rand.NextDouble() * 255; for (int i = 0; i < cols; i++) { float noise = Noise.Generate((float)seed); noise *= 7; int height = left + (int)noise; height = (int)MathHelper.Clamp(height, 0, rows - 1); tiles[height][i] = new Tile(2, new Vector2(i, height), scale); FillLower(tiles, height, i, scale); seed += .05f; } int[] heightmap = new int[cols]; for (int i = 0; i < cols; i ++) { for (int j = 0; j < rows; j++) { if (tiles[j][i].TileID == 2) { heightmap[i] = j; break; } } } //Smoothing out terrain for (int i = 0; i < cols - 1; i++) { if (heightmap[i] > heightmap[i + 1]) { tiles[heightmap[i] - 1][i] = new Tile(6, new Vector2(i, heightmap[i] - 1), scale); tiles[heightmap[i]][i] = new Tile(3, new Vector2(i, heightmap[i]), scale); } } for (int i = cols - 1; i > 0; i--) { if (heightmap[i] > heightmap[i - 1]) { tiles[heightmap[i] - 1][i] = new Tile(5, new Vector2(i, heightmap[i] - 1), scale); tiles[heightmap[i]][i] = new Tile(4, new Vector2(i, heightmap[i]), scale); } } //Caves for (int y = 0; y < rows && left + 10 + y < rows; y++) { for (int x = 0; x < cols; x++) { double noise = Noise.Generate(x / (70 * scale), (y + 1) / (70 * scale)); //Not air if (tiles[left + 10 + y][x].TileID != 0 && noise > 0) { tiles[left + 10 + y][x] = new Tile(0, new Vector2(x, left + 10 + y), scale); } } } return new Level(tiles); } 

这是一幅展示我的意思是“洞穴层切断”是突然的图片。 在这里输入图像描述

Foreach专栏,将地面上的空气砖块跳起来,然后开始施加2d噪音。 在伪代码中:

  //Caves Foreach cols { Bool FoundFirstGround=false; Foreach rows //from top { if (FoundFirstGround){ //APPLY YOUR 2d simplex noise logic ... } else //jump air tiles over surface if (! is air){ FoundFirstGround=true; } } } 

我继续沿着洞穴的起点从左到右循环,并使用recursion方法来填充洞穴层顶部开始的所有洞穴,从而消除任何截断。

 //Looping along cave layer for (int i = 0; i < cols; i++) { if (tiles[left + 10][i].TileID == 0) { FillCaves(tiles, left + 10, i, scale); } } private static void FillCaves(Tile[][] tiles, int i, int j, float scale) { tiles[i][j] = new Tile(1, new Vector2(j, i), scale); if (i - 1 >= 0 && tiles[i - 1][j].TileID == 0) { FillCaves(tiles, i - 1, j, scale); } if (i + 1 < tiles.Length && tiles[i + 1][j].TileID == 0) { FillCaves(tiles, i + 1, j, scale); } if (j - 1 >= 0 && tiles[i][j - 1].TileID == 0) { FillCaves(tiles, i, j - 1, scale); } if (j + 1 < tiles[i].Length && tiles[i][j + 1].TileID == 0) { FillCaves(tiles, i, j + 1, scale); } } 

正如你所看到的,不再有一个奇怪的截止点。