Hello there đ I am currently working on a small project and needed to experiment with different map sizes and shapes. I took this opportunity to learn more about how maps can be procedurally generated in 3D.
** In this blog post I will show you how to procedurally create maps in Godot using Grid Maps. **
I also felt like I struggled a bit with creating and optimizing the code and I took this as a perfect opportunity to give back to the community :)
đGet the latest version of the code here
Prerequisites
For this tutorial we will be using a 3D model of a hexagon that Iâve borrowed from Jmbivâs tutorial.
Alternatively, you can also scour the web for other 3D models and resize them to 1mm height and ~1.74mm width.
As long as you donât want to sell your game and donât want to build the 3D models yourself, I suggest also looking over MagHex Tiles for Gloomhaven which you can download and resize for your game.
Setting up your scene
In this part you can follow my steps from the gifs in order to setup you scene with everything you need and then we can go over the nitty-gritty of the code.
If for some God forbidden reason the website doesnât load the gifs for you, ping me with your browser type in the comments and follow the gifs posted on the repo.
Note - You will see in the gifs that the first key I press is F7, which I use for starting the recordings. You will not need to press F7 when tracing my steps.
Step 1 - The Main Node
We will need to create a main node to which we will attach the other components and which will be displayed when running the game.
Step 2 - The Main Camera
You see that nice blue horizon line in the background?
If we run the game as it is, we wonât be able to see it without a camera.
Step 3 - The Mesh Library
In this approach of procedurally generating maps, we will be using GridMaps.
In order to take full advantage of them, we will transform our 3D object into a Mesh Library, such that we can later import it inside the GridMap.
Step 4 - The GridMap
We now create the main piece of our puzzle, the GridMap.
You will see me typing in some numbers for the cell_size. I will go more into details about those numbers when explaining the code. All you have to know now is this specific 3D object (now Hex Mesh) that we are using, we have to put in those values for it to perfectly fit between its brothers and sisters.
Step 5 - Adding The Script
Now you just copy-paste the script, and thatâs it⌠project done. Now you can add Godot game developer in your CV.
Or⌠if you really want you can also follow the next chapters in order to understand how the code works.
Understanding the code
The first draft For the first iteration of the code, all we want to be able to do is to create a rectangle given the number of rows and columns.
So letâs define the variables that we needâŚ
We will now use Godotâs _ready() function to update the values of cell_size dynamically.
Iâll try not to deviate too much and go into the math and why we use the cosine function here. But if youâre curios (which is something admirable) you can look at this explanatory YouTube video.
Now letâs actually generate the square mapâŚ
In the end, you should have a result similar to the one in the image below.
Centering map - Experimentation
So a first approach to centering may be to move all cells to the right by half the width of the rectangle.
So letâs implement it and see if it worksâŚ
Well that doesnât look quite right. Letâs try printing out the x position of each cells in a row to see whatâs wrong.
# This logic is for a rectangle with 5 columns
X_shift is: 4.35
X is: 0 X-X_shift is: -4.35
X is: 1 X-X_shift is: -2.35
X is: 2 X-X_shift is: -0.35
X is: 3 X-X_shift is: 1.65
X is: 4 X-X_shift is: 3.65
It seems like the pattern may be something like even numbers from -4 to 4 with a 0.35 shift. But something breaks when we subtract the shift from 3.
âď¸ What do you say about a small competition?
Try thinking of a way to solve the problem and after you come up with a solution, you can compare your solution with mine.
Iâll add some empty space for you not to get any spoilers.
Centering map - My solution So ideally what we want is to replace our range from [0 to hex_cols] to something like [-hex_cols/2 to hex_cols/2].
Unfortunately at the time of me writing this blogpost Godot does not support negative ranges, so the only solution is to create our own range.
We then just have to integrate the zero centered range in our previous code.
Now what the map will look like would be something like this.
Yup⌠that looks a bit better but it seems like something is still out of place.
Removing extra cells
It seems that on even rows the rectangle is a little bit longer. Nothing a few if statements canât solve.
That looks mutch better, but how did we get those new colors?
Must have been a bug, who knowsâŚ
Future investigations
Generating hexagonal maps should also be something to look into.
The starter code should be enough for you to wrap your head around how to generate the hex map, but if you struggle with it you can ping me in the comments and Iâll create a tutorial for it.
đGet the latest version of the code here
Conclusions
In todayâs post we looked over:
how to create a scene and mesh library how to use grid map together with the mesh library how to procedurally populate the map with hexagon meshes If there are any questions leave them in the comments and Iâll try to answer them as soon as I can.
Hope you enjoyed the blogpost :)
Peace đ
References
Jmbiv - 3D Hexcell Square Map -Â YouTube link
Gingerageous Games - 2D Squarecell Hex Map -Â YouTube link
Brian McLogan - Find missing length using cosine function -Â YouTube link