I have been new to game programming but I knew little bit about Perlin noise. So I have created a infinite world using Perlin noise but I don't be able to understand how I put trees in my world like it is put in game Factorio. My game is a 2d top down.
-
\$\begingroup\$ There are many many ways to do this, with many considerations which may or may not relate to your particular problem. What have you tried so far, and where specifically have you run into trouble with it? The more you can narrow down the problem, the faster you'll tend to get answers, and the more helpful/actionable they'll be since they're focused on solving the specific issue you're facing. \$\endgroup\$– DMGregory ♦Commented May 20, 2020 at 12:57
2 Answers
I assume you already created a Perlin noise which is supposed to represent the tree density and now you wonder how to feed this noise map into your tree spawning system.
The simplest approach is to place a tree on every position where the amplitude of the Perlin noise exceeds a specific level. That will give you islands of dense grids of trees separated by oceans completely devoid of trees. Or a dense forest grid with occasional clearings, depending on the chosen cutoff level.
Sometimes that's exactly what you want, like in RTS games like Warcraft or Age of Empires where forests are both resources and obstacles. But in other cases you usually want a more organic look with trees placed a lot more randomly and with varying density.
If you are looking for a more natual look, then it's a good way to treat the amplitude of the noise as a tree probability. A simple way to do that is to roll a random number for every possible tree position and place a tree if that number is smaller than the amplitude of the tree-noise at that position. So areas with a high amplitude will statistically generate more trees than areas with a low amplitude.
As usual with procedural generation, you might have to experiment a lot to get the results you find both aesthetically pleasing and good for gameplay. Possible tweaks are a cutoff value under which no trees are generated at all, make tree probability a logarithmic or quadratic function of density, play around with placing trees not exactly on the coordinates but with a slight offset to avoid visible grids in high-density areas and many more.
-
\$\begingroup\$ If you want your trees to spawn based on a world seed; so you don't have to save locations to disk or hold them in memory, there are extra steps. Calculate a tile seed like so.
tile_seed = WORLD_SEED + int(x * 2) + int(y / 2)
. Set an RNG instance's seed to thetile_seed
before doing your probability checks with that RNG object and the tree will always spawn in the same location for the same world seed. Here is an example of this method in action: gfycat.com/obesewanhummingbird \$\endgroup\$ Commented Dec 17, 2020 at 17:40
Philipp's answer is great, but if you want your trees to spawn based on a world seed; so you don't have to save locations to disk or hold them in memory, there are extra steps.
Calculate a tile seed using the x
and y
coordinates of the tile like so.
tile_seed = WORLD_SEED + int(x * 2) + int(y / 2)
Set an RNG instance's seed to the tile_seed
for the given tile's x/y
before doing your probability checks on a tile with that RNG object and the tree will always spawn in the same location for the same world seed. you can do additional rolls with the same tile seed to get randomized properties for the objects as well.
This can be used to spawn anything into the game with randomized properties, in a repeatable way based on tile location and world seed.
Here is an example of this method in action: https://gfycat.com/obesewanhummingbird
I use godot engine, and godot engine wraps around on 64 bit integers if they exceed the bounds, so in theory it should be perfectly safe for pretty much any coordinate.