4
\$\begingroup\$

I need to generate tile data for an island based rpg, my goal is have something that looks like this (mountains not required):

enter image description here

For the past few days I have been trying to figure out a satisfactory way to generate tile data that will give me varied and natural islands, such as in the example above.

I've tried using Unity's Mathf.PerlinNoise but the results are far too random, and I can't see a way to get it to generate a single island.

Using LibNoise I was able to get slightly better results, although the generation seems to be significantly slower and perhaps better suited to 3d terrain. Similarly however, I can't see a way to set the Octaves/Frequency/etc, so that I get a nice single island each time.

While there are a fair amount of resources online for perlin/noise in general, it mostly seems to be aimed at 3d terrain and height, where I simply have a 2d array of int for my tile data, that maps to either water, sand or grass and needs to be generated in such a way that sand/grass are grouped together logically to form an island.

Any help would be greatly appreciated!

\$\endgroup\$
  • \$\begingroup\$ Try simplex noise \$\endgroup\$ – Savlon Jul 20 '14 at 14:03
  • 1
    \$\begingroup\$ Your 2d map is in fact a 3d map: The z-coordinate maps to the terrain type. \$\endgroup\$ – Philipp Jul 20 '14 at 14:53
  • \$\begingroup\$ Could you explain that a bit more? Surely the result of PerlinNoise for a given x/y maps to my tile type? Ie: 0.4+ is sand, 0.6+ is grass, etc. \$\endgroup\$ – Neophyte Jul 20 '14 at 14:55
  • \$\begingroup\$ @Neophyte Where you set the thresholds for each terrain type is something you need to experiment with yourself. \$\endgroup\$ – Philipp Jul 20 '14 at 14:57
  • \$\begingroup\$ What does that have to do with z-coordinate? \$\endgroup\$ – Neophyte Jul 20 '14 at 17:02
12
\$\begingroup\$

One thing I've done in the past for island shapes is to use perlin noise minus a circular shape. It usually produces one big island and some little things off on the side. You can use flood fill or smoothing to remove any small noise.

Here's a demo (flash) that I wrote for this question.

For each location (x, y) in the noise bitmap, compute the distance from the center, normalized so that the bitmap is 2x2:

function distance_squared(x, y):
    dx = 2 * x / width - 1
    dy = 2 * y / height - 1
    # at this point 0 <= dx <= 1 and 0 <= dy <= 1
    return dx*dx + dy*dy

Location (x, y) is part of the island if perlin_noise(x, y) > 0.3 + 0.4 * distance_squared(x,y). In the demo you can vary the two constants to see the effects you can get.

I don't think these islands look quite the way you want but this technique might be useful for you in combination with other techniques you're using.

\$\endgroup\$
  • \$\begingroup\$ This is exactly the kinda thing I needed, thank you so much! Using your distance_squared method with my existing perlin code has yielded nice big islands with the occasional smaller one to the side, as you said. Is there anything I can do further, such as turbulence or any specific perlin settings, to deform the shape more towards my example? \$\endgroup\$ – Neophyte Jul 20 '14 at 21:48
  • \$\begingroup\$ You might be able to use fewer octaves. The lower octaves are smoother than the higher ones. Or you might post-process in some way, to smooth out the corners with some sort of blur algorithm. For example, set a block to water if its eight neighbors include at least 3 water (you might need to try different numbers). This might remove some of the rough borders. \$\endgroup\$ – amitp Jul 21 '14 at 1:42
  • \$\begingroup\$ I added a better demo that lets you adjust more parameters. You can either subtract a circular shape or multiply by a cone. \$\endgroup\$ – amitp Jan 30 '16 at 18:57
  • \$\begingroup\$ btw if you want an island longer than it is tall to fit a wide screen, try an ellipse instead of a circle skillsyouneed.com/num/curved-shapes.html \$\endgroup\$ – jhocking Feb 19 '17 at 23:49
-1
\$\begingroup\$

I don't do a lot of 2d in Unity, but I can still make this pretty easily. So, first you start with a minimum and maximum (x,y) then generate a random. From here you need a basic island tileset (full islands) then you will find a random island in code and instantiate it. Henceforth, you now have a island. TRUELY random generation is much harder.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.