Mini LD 69 Postmortem: Generating a continent

For Mini Ludum Dare 69 I wanted to create a simple strategy game about colonizing an unknown continent (inspired by Africa). But in the end I was only able to create a simple continent generator, which would’ve been the first step towards an actual game. At the next Ludum Dare I definitely need to pay attention that I start with actual gameplay and build upon that – but that just as a side-note.

Screenshot 1

In this post I just want to roughly outline how I went about generating the continent – and maybe it’s helpful for you and/or we can discuss about possible improvements or alternative methods :).

Try out the Continent Generator if you like: Try it out.

The article is below the “Read the rest of this entry”.

Overview

  1. Basic Data Structures
  2. Continent Shape
  3. Generating Areas
  4. Filling Areas
  5. Conclusion

Basic Data Structures

I use a Hex Grid data structure based on the amazing article Hexagonal Grid article by Redblobgames. Basically the Hex Grid is represented by a 3-dimensional coordinate system describing all three directions of a hexagon (q, r and s, with s being redundant and calculated by s = -(q + r). But it is useful for calculating symmetric shapes).

Continent Shape

Areas

For generating the continent shape I merged two symmetric shapes like those shown in the picture above: A big hexagon of radius 8-10 with one big diamond shape with (q,r,s)-radius of either (6,10,6), (7,11,7) or (8,12,8).

Continent2

Then I chose the offset to attach the diamond shape to the hexagon shape as following: Start with an offset of (q,r)-coordinates (4,5) or (4,6) and then rotate it randomly by 60°, 120°, 180°, 240°, 300°, 360° around the origin. Rotation by 60° is done by shifting the (q,r,s)-coordinates (s being implicitly defined by -(q + r)) to the right or left and flipping the signs. So for (4,6) all rotations would be (10, -4), (6, -10), (-4, -6), (-10, 4) and (-6, 10).

All possible offsets generated by this method are shown by the grey hexes in the image above.

Generating Areas

After generating the landmasses I thought about adding areas to my map – in my case three areas: A desert, a green savannah and a mountain range. They are all generated using the same method with different parameters.

The 5 parameters of my method are:

  • length of the basic shape
  • radius of the area around the basic shape
  • random curve chance which decides how straight or curved the basic shape will be
  • curve timeout which specifies how many straight steps must be between curves
  • outer layer noise chance which specifies how many of the outer layer hexes will be randomly removed to create a more ragged appeareance.

The basic algorithm is like this

  1. Basic shape generation
    1. Start with Hex (0, 0) and choose a random direction (one of the sides of the hex) as current direction.
    2. For 1 to length:
      1. Add the neighboring hex in the current direction to the shape
      2. If there is at least a number of curve timeout steps since the last direction change:
        1. With a random chance of random curve chance change the current direction to one of the neighboring directions (turning left or right)
  2. Area generation
    1. Add the basic shape to the area.
    2. For 1 to radius (the current layer):
      1. For all directly neighboring hexes of the area:
        1. If it is not yet the outermost layer:
          1. Add that hex to the area
        2. Else:
          1. Don’t add the hex with a random chance of outer layer noise chance

So in order to generate the three areas in my example I used following parameters:

  • Desert:
    • length: randomly chosen between continent width /2 and continent width
    • radius: Randomly chosen between 3 and 4
    • curve chance: 50%
    • curve timeout: 1
    • outer layer noise: 50%
  • Green Savannah:
    • length: randomly chosen between continent width /2 and continent width
    • radius: Randomly chosen between 5 and 6
    • curve chance: 30%
    • curve timeout: 2
    • outer layer noise: 50%
  • Mountain Range:
    • length: randomly chosen between continent width /2 and continent width
    • radius: 0 (only the basic shape)
    • curve chance: 80%
    • curve timeout: 0
    • outer layer noise: 0%

After generating the areas, they are placed on the continent: The desert in the upper third, the jungle and mountain range in the lower third. Hexes that fall outside the continent or are already occupied by another area (except when placing the mountain range, which is placed on top) are ignored when placing.

Since the directions were not limited in any way and the areas were placed in relation to their center, some of the areas reach sometimes quite a bit outside of their designed area.

Filling Areas

Tileset
Finally a few words about filling the areas. Basically I use a weighted random choice between all of the tiles of the particular area. Everything not filled by an non-mountain area was filled with the grassland tiles (second row). In my case those were (always in order from left to right on the tileset above):

  • Desert: 4 : 1 (only few cacti)
  • Green Savannah: 2 : 2 : 2 : 1 (rather more than less trees)
  • Grassland: 3 : 3 : 3 : 1  (Not wanting too many Zebras)

Conclusion

That’s all about my simple continent generator. It’s still very simplistic and there are many things that could be improved – first and foremost giving the continent shape a more realistic ragged appearance.
And while writing this article I felt it would be nice to have something like a node based editor to just plug together several components to easily create different kinds of complex generators from simple parts – well maybe on another day 😉

Thank you for your interest and reading this far and I hope it was helpful to you in any way.

Feel free to leave a comment and if you are interested in my game developing endeavours (and 8 bit pixelart which I retweet quite a lot :D) then follow me on Twitter:

Tags: hex grid, procedural content generation