Island gradient

In this topic I will be creating a noise gradient that we can subtract from our heightmap,
to create an island like heightmap. The island gradient will look something like this:

Island gradient
Island gradient applied to heightmap

Island heightmap with tiles

To create an Island gradient, we will create another helper method in our Noise class “GenerateIslandGradientMap”

public static float[] GenerateIslandGradientMap(int mapWidth, int mapHeight)
{
	float[] map = new float[mapWidth * mapHeight];
	for (int x = 0; x < mapWidth; x++)
	{
		for (int y = 0; y < mapHeight; y++)
		{
			// Value between 0 and 1 where * 2 - 1 makes it between -1 and 0
			float i = x / (float)mapWidth * 2 - 1;
			float j = y / (float)mapHeight * 2 - 1;

			// Find closest x or y to the edge of the map
			float value = Mathf.Max(Mathf.Abs(i), Mathf.Abs(j));

			// Apply a curve graph to have more values around 0 on the edge, and more values >= 3 in the middle
			float a = 3;
			float b = 2.2f;
			float islandGradientValue = Mathf.Pow(value, a) / (Mathf.Pow(value, a) + Mathf.Pow(b - b * value, a));

			// Apply gradient in the map
			map[y * mapWidth + x] = islandGradientValue;
		}
	}
	return map;
}

The curve graph formula is the one made on desmos.com right here:

Without applying the curve you’d get something like this, which is going to give us too much water, and not enough land. Basically a very tiny island.

Island gradient without curve applied
Island gradient with curve applied

Now to subtract this gradient from our heightmap, we can add a boolean option to our NoiseGenerator to do this.
So in our NoiseGenerator class lets add a boolean “ApplyIslandGradient”.

public bool ApplyIslandGradient;

And in our Apply method, just right under where we Generate our noiseMap, we can add our subtraction.

if (ApplyIslandGradient)
{
	var islandGradient = Noise.GenerateIslandGradientMap(tilemap.Width, tilemap.Height);
	for (int x = 0, y; x < tilemap.Width; x++)
	{
		for (y = 0; y < tilemap.Height; y++)
		{
			// Subtract the islandGradient value from the noiseMap value
			float subtractedValue = noiseMap[y * tilemap.Width + x] - islandGradient[y * tilemap.Width + x];

			// Apply it into the map, but make sure we clamp it between 0f and 1f
			noiseMap[y * tilemap.Width + x] = Mathf.Clamp01(subtractedValue);
		}
	}
}

The final method should look like this:

public override void Apply(TilemapStructure tilemap)
{
	// Make sure that TileTypes are ordered from small to high height
	TileTypes = TileTypes.OrderBy(a => a.Height).ToArray();

	// Pass along our parameters to generate our noise
	var noiseMap = Noise.GenerateNoiseMap(tilemap.Width, tilemap.Height, tilemap.Seed, NoiseScale, Octaves, Persistance, Lacunarity, Offset);

	if (ApplyIslandGradient)
	{
		var islandGradient = Noise.GenerateIslandGradientMap(tilemap.Width, tilemap.Height);
		for (int x = 0, y; x < tilemap.Width; x++)
		{
			for (y = 0; y < tilemap.Height; y++)
			{
				// Subtract the islandGradient value from the noiseMap value
				float subtractedValue = noiseMap[y * tilemap.Width + x] - islandGradient[y * tilemap.Width + x];

				// Apply it into the map, but make sure we clamp it between 0f and 1f
				noiseMap[y * tilemap.Width + x] = Mathf.Clamp01(subtractedValue);
			}
		}
	}

	for (int x=0; x < tilemap.Width; x++)
	{
		for (int y = 0; y < tilemap.Height; y++)
		{
			// Get height at this position
			var height = noiseMap[y * tilemap.Width + x];

			// Loop over our configured tile types
			for (int i = 0; i < TileTypes.Length; i++)
			{
				// If the height is smaller or equal then use this tiletype
				if (height <= TileTypes[i].Height)
				{
					tilemap.SetTile(x, y, (int)TileTypes[i].GroundTile);
					break;
				}
			}
		}
	}
}

Now you can tick the checkbox on the NoiseGenerator algorithm to create an island like shape.

Island gradient applied on our previous perlin noise tutorial result

Thanks for checking out this tutorial.
For this topic, I also wanted to credit Sebastian Lague for his great job and inspiration
for creation of the gradient and curve graph used in this tutorial.

Next up I will be covering layered tilemaps.
Seperating ground tilemap from object tilemap, and drawing some trees on the grass tiles.

The github repository commit for this tutorial can be found here:
https://github.com/Venom0us/Code2DTutorials/commit/774fb52c034153298532e756e07b0faf6cceb7a9

The source files can be found here:
https://github.com/Venom0us/Code2DTutorials/releases/tag/v4

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website at WordPress.com
Get started