Как создать определенный процент сущностей с помощью шума Перлина С#?
У меня есть карта местности в виде двумерного массива. Я на ней генерирую деревья (1
) с помощью шума Перлина.
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 штук
. Но тут уже проблема с тем, что они буду слишком рандомно расположены, а не в "кучках" как от шума Перлина. Примерно так:
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
цикле. Но насколько такой подход оптимален?