In this series, you will learn to create an infinite procedural world.
We prepared a project in space, but the techniques you will learn apply to any project.
You will learn to:
By the end of the series, you will have three procedural content generator prototypes for worlds taking place in space. The player can navigate to infinity in any direction; the world never ends.
The third generator will include planets and virtual routes that connect them. There won’t be any particular gameplay: we’ll focus on the visuals to illustrate and test the algorithms we’ll explore in the lessons.
In the demos, the player controls a ship with the WASD keys. They can move forward and turn.
In the last lesson, we’ll allow the player to make persistent changes to the infinite world. By left-clicking in a grid cell, the player will be able to create a new planet that’ll automatically connect to nearby ones. Right-clicking on a planet will remove it from the world.
As the player moves to new quadrants of the world grid, now distant areas unload, and the world generation algorithm populates nearby quadrants, taking saved changes into account.
Here is a class diagram of the demos towards which we will work on in this series.
We have a world generator that stores reference to all the resources it needs to instantiate. The generator produces random numbers, creates entities, places them in the world, and saves some data regarding each of the world’s sectors.
You can find a start project that goes along with the tutorials. It contains the player ship, the asteroid, and a utility object to overlay a grid on the game world.
Using those start assets saves you setup time and allows us to focus on the exciting part: the world generation algorithms.
To generate infinite worlds, like with other procedural generation algorithms, we split space into a grid and work on one cell at a time.
In this case, we’ll look at the grid cell the player is in and only populate the grid cells around them. One cell would be slightly larger than one screen, which is big enough for the player not to see any loading or unloading, and small enough to run fast, even with GDScript code.
In this series, we will use a dictionary to keep track of the world’s data. Dictionaries are both flexible and efficient data structures in this context.
You may need a different data structure in a much more complex game. Still, the principle of storing the world’s state and persistent changes from the player should stay the same. The main difference would be in the implementation details.
We will use noise generators to place objects in the world. We’ll start with white noise, which produces unpredictable numbers and can work well if you need entities to clump up in some places.
Then, we’ll look at blue noise, which produces random yet orderly distributions and works well for object placement.
We’ll talk more about what noise is and how it’s used in procedural generation in the next lesson.