I myself am a procedural loving person and I have done a lot of PCG. From experience, I can say that procedural generation is too broad to define on "how to do it". There are lots of ways on how you can approach reaching some goal. That is a part of fun in procedural generation that every algorithm has something of its own and unique in some degree.
Of course we can generalise some things and look at some common approaches. But first let's ask a question: "what is procedural?".
A lot of stuff I write here is opinion based. I am trying to share what I understood from a few projects with procedural generation. So I don't think it's ideal or something that defines PCG.
What I mean by this is that procedural isn't random. It utilises randomness in order for it to be procedural? More or less - yes. But I like to think about the result being procedural, what you get in the end is procedural. Placing a few objects at random places, I wouldn't call it procedural, but generating a map of objects placed randomly, following some rules to make sense - that is what I think is procedural.
I will try to define general approaches and try to guess the specific approach that was taken to generated this map from an example that you have shared.
Noise generation based.
Developers frequently take this approach because there is wide variety of different forms and shapes of textures that are being generated and they serve for different purposes allowing for generation of all kinds of shapes. Very common is to use textures for generating height maps for terrain
0 being at lowest point and
1 being at the highest point on the terrain.
Textures are just random numbers from
0f-1f at each pixel. How those random numbers are generated for textures depends on the rules set for generating such a texture. So basically you can do the same thing just with random number generation without using a texture, but sometimes you want to save that data, to speed up some processes, to have a visual representation and so on... This is when textures are handy.
The most common one and a base for everything else. Just using random numbers for indices and values to randomly place some object, extend it in some direction, create random positions for mesh vertices...
Nothing is truly random in most
Random modules. They are just mathematical functions that will give the same result provided the seed for them was the same.
Beautiful forms that generate itself from the same rules.
There are two major methods of two dimensional fractal generation. One is to apply an iterative process to simple equations by generative recursion. The other main method is with Iterated Function Systems consisting of a number of affine transformations.
There are lots of algorithms not to only generate maps, objects, and 3D. But text, dialogues, behaviours, story chain...
Example from question.
The approach I would take to generate this kind of a map.
Random module to take an
int/long seed. Based on this
seed we will get random values from our module that would change the world to some extent every time we change the seed and regenerate everything.
First thing that we would need is a tile map. Just a map that represents a grid of tiles
Tiles[10,10]. It could be a 3D one and more
Tiles[10, 1, 10], we could even store some other information in that array, it doesn't really matter. But for this one I would choose a 2D tile map as this is enough. Tiles are not necessary
GameObjects or even
classes [I usually make them classes or structs]. They are just convenient containers holding data about tile, like its position, indices position in array that holds them and other valuable data for your type of generation.
sand tiles. For each of the tile type you could define it's own rules of generation.
Generate river by using some algorithm that would simulate behaviour of river.
Then I would scatter resources like trees, rocks and everything natural. I would generated them on some tiles defined by some rules. Like
pick a random location, place tree, trees grow close one to another, close to water, place some more trees until its enough and still under limited number of trees.
Then I would generate roads by using path-finding algorithm like
A* for simplicity. Or I could first generated buildings - then generate roads. Or first generate the castle, then everything else. It all depends on the result we would like to see in the end.
It's really that simple and there are no things like generate neat texture then generate everything else based on this texture - it's still possible though, if you need this.
They are widely used during process of generation. Usually to simplify rules or provide tools for human interaction with generation.
you could use colliders to check if something overlaps or can fit in during placement [when you don't have strictly defined bounds or you can't utilise those bounds to achieve your generative goal].
you could use colliders to allow designer to meddle in how something is generated. [Blocking tiles, marking them walkable, allowing generation on them, setting some rules for the area...].
It's easy to create something procedural. But it's hard to make it fun and less repetitive, once you master generation, you have to master another field. And that is generating something unique and quite different from previous experience. You can see many patterns of repetitiveness in lots of games.
In the end. Everything that PCG is can be boiled down to randomness, just random numbers. It's the way we use those numbers is what defines the shapes and forms of content we can create with them. And from those we create algorithms, techniques and new ways of morphing those random numbers into sets of other types of randomness.