Hex Strategy

GitHub

Overview

This is an unfinished project which I began work on in October 2022.

At the time I had been playing a lot of Civilisation 6 and Humankind and I was inspired to make my own Hexagon-based 4X game. I began by working on creating the hexagonal world mesh that the game would be played on. I used Cat Like Coding's Hex Map Tutorial series as a guide for this project. 

I created the hexagonal mesh, allowing for height variation, terrain colour variation and the addition of rivers. I was in the process of implementing roads when I last worked on this project.

The grid is created by starting with a rectangular grid of cells where odd-numbered cells are displaced by half a cell height along the z-axis. The grid co-ordinates are then converted to hex co-ordinates as using a 3-dimensional co-ordinate system is much easier for navigating through hexagons than using a 2-dimensional co-ordinate system. This is helpful as when a cell gets changed it is much easier to identify its neighbours as you can just increment and decrement each of its co-ordinates by 1 to find its 6 neighbours. There is a small gap between each cell and its neighbour which is filled with a quad (or a triangle when three hexagons meet) and these regions are used to blend colours and heights between cells.

The user then has the option to modify several elements of the cell. First is the colour. At the moment this is a simple change of the vertex colour attribute at the corners of the cell, with a special blend used in the regions between cells. 

Then there is the height. The height displaces all of the vertices in the cell along the y-axis. The blend regions are then modified depending on the relative heights of the neighbouring cells. If two neighbouring cells have an absolute difference of 1 in elevation then the blend region forms a terrace otherwise it is a simple slope. In the regions where three cells meet, the terraces also have to be taken into account when generating the triangle shape. In addition to this, a noise texture is sampled to add a small amount of height variation. This adds greater visual variation to the flatter regions of the map.

Rivers and roads can be also added to the cells. Both features are added by dragging from one cell to the next. In the case of rivers the cell is redrawn with a channel and a water mesh is added with the UVs moving with respect to time to give the water an animated effect.  The channel creation takes into account if a river is present or not in neighbouring cells. Rivers also follow certain rules such as water can travel downhill but not uphill and water can enter a cell from multiple directions but may only leave from one direction. Roads on the other hand are a new mesh which gets placed on top of the ground mesh using z-displacement in the shader so that it is always rendered on top. Roads follow the rules that they cannot go up or down a hill where the absolute difference in elevation is greater than 1 and they cannot enter or leave a cell in the same direction as a river.

Finally, noise is applied to the corner vertices of each cell as well as the vertices along the edge of the river banks to give further visual variance to the map.

So far there are not many differences between my project and the tutorial as this project is still a work in progress. 

The biggest difference between what I have produced so far and the tutorial series I have been following is my implementation of the rivers. In the original tutorial, there are strict rules that rivers can only enter a tile from one direction and leave a tile from one direction. I took this a step further and made it so that rivers could enter the same tile from multiple directions, allowing the formation of confluences. Adding additional channels to tiles with multiple rivers entering and exiting the tile was not much of a challenge as the infrastructure was already in place for this. What did, however, provide a challenge in this process was calculating the UVs for the water in the channels so that the river always appeared to flow downstream, regardless of how many river channels entered a given tile. 

I have also started to implement bridges for roads going over rivers. I have set a rule for the roads that get drawn over rivers which only allows the placement of the road if it passes over the river in a straight line and the road does not enter or leave the tile through the same side as a river.