我有一个二维数组形式的区域地图。1我使用 Perlin 噪声在其上生成树 ( )。
0 0 0 0 0 0 1 1 1 1
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 -> 0 1 0 1 1
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 1 1 0 0
生成时,我指定要创建多少百分比的树。
for (var x = sector.top; x < sector.topOffset; x++)
for (var y = sector.left; y < sector.leftOffset; y++)
{
var rawNoise = Mathf.PerlinNoise((x - noiseOffsetX) / noiseScale, (y - noisnoiseScale);
var clampedNoise = Mathf.Clamp(rawNoise, 0, 1);
if (clampedNoise < percent)
{
_map[x, y] = 1;
}
}
但现在我想创建石头 ( 2),以便它们仅出现在空字段 ( 0) 上,同时保持我选择的百分比。我无法理解如何做到这一点(如果可能的话)。
如果我只是检查是否下注0,那么最终石头的百分比将会减少,因为那些试图在树上生成的石头将无法做到这一点。
我还考虑过使用通常的随机选项。在这里可以用循环保存百分比:пока не заспавниться N штук。但已经存在一个问题,即它们的位置过于随机,而不是像 Perlin 的噪音那样“成堆”。像那样:
0 1 1 1 1
1 2 0 2 1
2 0 0 0 1
0 1 0 2 0
2 1 1 0 2
还有一个选项可以将所有生成实体一次传递给生成方法,以便进行多项检查:
for (var x = sector.top; x < sector.topOffset; x++)
for (var y = sector.left; y < sector.leftOffset; y++)
{
var rawNoise = Mathf.PerlinNoise((x - noiseOffsetX) / noiseScale, (y - noisnoiseScale);
var clampedNoise = Mathf.Clamp(rawNoise, 0, 1);
if (clampedNoise < wood)
{
_map[x, y] = 1;
}
else if (clampedNoise < stone)
{
_map[x, y] = 2;
}
}
但石头永远只会围绕着树木,你需要更多的随机性:
2 1 1 1 1
1 2 2 2 1
2 0 0 2 1
1 0 2 0 2
2 1 1 2 0
这就是地图本身现在的填充方式:
var terrainMaskBuilder = new TerrainMaskBuilder(mapSize);
terrainMaskBuilder.AddPerlinTerrain(Size.FullMap, entity: 1, percent: 0.6, noiseScale: 5);
terrainMaskBuilder.AddPerlinTerrain(Size.FullMap, entity: 2, percent: 0.2, noiseScale: 5);
var result = terrainMaskBuilder.Get();
UPD1:有一个选项可以使用噪声创建带有实体的蒙版,将它们覆盖在地图上并检查它们是否有 N%。如果没有,则创建一个新掩码。如此while循环。但这种方法的最优程度如何?
对于所有空闲单元,计算柏林噪声值。将单元格收集到数组中(噪声值、x、y),按噪声降序排序。从数组的开头选择所需数量的单元格。将石头排列在这些单元格中。