If you want to place 100 trees per square-kilometer, then the easiest solution would look something like this (pseudocode):
for (int i = 0; i < 100; i++) {
position.x = randomValueBetween(0.0f, 1000.0f);
position.y = randomValueBetween(0.0f, 1000.0f);
placeTreeAt(position);
}
This will usually give you results which look sort-of-OK at first glance. However, there are a few problems here:
- There will be exactly 100 trees per square-kilometer. This might or might not matter for your game.
- Clustering illusion. While the distribution of your trees will be perfectly randomly distributed (assuming you use a good RNG), it might not look random. This might not be so bad with purely cosmetic trees, but it might be worrisome with objects where tight clusters are bad for gameplay (like player start locations in a battleroyal game).
- It will place trees where there shouldn't be trees. You might see trees sticking out of rocks, growing on steep slopes, in the middle of a lake or even two trees so close together that their trunks intersect each other.
The first point is rather easy to fix if necessary: Just add a random number to the number of trees you want to generate:
int numberOfTrees = 100 + randomValueBetween(-10, 10);
for (var i = 0; i < numberOfTrees; i++) {
position.x = randomValueBetween(0.0f, 1000.0f);
position.y = randomValueBetween(0.0f, 1000.0f);
placeTreeAt(position);
}
The last two points can be fixed by checking if the randomly generated position is actually a valid position to place a tree:
- are there already enough trees in an
x
meter radius around it?
- is it physically possible for a tree to exist at this position?
When the position is not valid, one option is to just skip it. This means you can no longer rely on the number of trees per chunk to be constant. Biomes which have a less "tree-friendly" geography will have less trees than the number of trees says it should have.
Alternatively you can run the loop until you found 100 valid positions, but keep in mind that this might take a while in very tree-unfriendly terrain (or even forever if there aren't 100 valid tree-positions at all in the chunk). So you might also want to set a maximum number of retries.
const int numberOfRetries = 10;
int numberOfTrees = 100 + randomValueBetween(-10, 10);
for (var i = 0; i < numberOfTrees; i++) {
for (var j = 0; j < numberOfRetries; j++) {
position.x = randomValueBetween(0.0f, 1000.0f);
position.y = randomValueBetween(0.0f, 1000.0f);
if (treeCanBePlacedAt(position)) {
placeTreeAt(position);
break;
}
}
}