50
\$\begingroup\$

I'm working on a Worms-styled game and want to generate some terrain procedurally. I've previously done a lot of terrain generation using perlin noise, and this is what I started out using for this game. The only problem with it is that it's too simple and boring, giving me some hills but not the complexity I want. I'd like to have features like caves and hanging mountains and I don't mind floating islands and such. Something like this, but even crazier would be ok:

enter image description here

I thought of first generating the terrain using classic perlin noise, then just removing parts to create caves and what not, but I'm having trouble guiding the removal of those parts. Are there any alternatives to generating such a terrain?

\$\endgroup\$
5
  • \$\begingroup\$ Does the red represent caves or is that just part of the terrain? \$\endgroup\$ Dec 5, 2011 at 15:04
  • \$\begingroup\$ It's part of the terrain. I just Google that image, was the closest to what I want to accomplish. The "cave" part might be that little hole to the right, if it was continued more inside the terrain to it's left. \$\endgroup\$
    – Xeon06
    Dec 5, 2011 at 15:12
  • \$\begingroup\$ @Drackir, edited the image. \$\endgroup\$
    – Xeon06
    Dec 5, 2011 at 15:16
  • \$\begingroup\$ Related: gamedev.stackexchange.com/questions/6721/… (but not a duplicate as it seems to focus on implementation versus the generation algorithms). \$\endgroup\$
    – user1430
    Dec 5, 2011 at 16:50
  • \$\begingroup\$ @JoshPetrie indeed. I'm good with the destruction. It's the generation I'm having trouble with. \$\endgroup\$
    – Xeon06
    Dec 5, 2011 at 16:59

3 Answers 3

52
\$\begingroup\$

I'd suggest you start with 2D Perlin-noise. Something like this:

perlin-noise

Then apply a threshold on the image, so that you get several isolated islands, as shown here:

perlin noise with threshold

I chose a threshold of 0.04, everything above the threshold would be colored blue. The rest remaining black. Then after that, it's time to determine which "islands" to keep and which to throw away.

A possible approach would be to run through the image from left to right at various heights and select intersecting "islands" given a certain probability. In the example picture, the lowest line has a probability of 100%, so every island it crosses will be selected (filled white). The second line has a probability of 50% and the topmost line has a probability of 10%.

Once you have your islands marked like that, you can close the gaps in between by applying a morphological operation (dilate)

dilated islands

And there's a possible landscape.

The "granularity" of the noise is going to determine how small the details in your world are going to be. So it's probably best to experiment with these values.

Also where and with what probabilities your "selecting-lines" are positioned, the result is going to be vastly different. If you have a line near the top of the image with high probability to "select" an island, then you can build some sort of cave-landscape, etc.

\$\endgroup\$
5
  • \$\begingroup\$ Thanks a lot for the great detailed and illustrated answer! This is exactly what I'm gonna do. \$\endgroup\$
    – Xeon06
    Dec 5, 2011 at 20:13
  • \$\begingroup\$ Would you have any tips on the generation of such perlin noise, with this level of detail and such? I've been trying the whole evening and am not getting anywhere. \$\endgroup\$
    – Xeon06
    Dec 6, 2011 at 2:32
  • \$\begingroup\$ @Xeon06 I was just using the Perlin noise function provided by flash. The parameters were 24 for baseX and baseY, 1 octave and I chose to output grayscale noise and disabled "fractal". What language are you implementing this in? \$\endgroup\$
    – bummzack
    Dec 6, 2011 at 7:52
  • \$\begingroup\$ I'm implementing it JavaScript. I've been scourging the web for a good implementation that would give similar results for a week but can't find anything. \$\endgroup\$
    – Xeon06
    Dec 11, 2011 at 1:23
  • \$\begingroup\$ I've made another question pertaining to the perlin noise part gamedev.stackexchange.com/questions/20880/fast-noise-generation \$\endgroup\$
    – Xeon06
    Dec 11, 2011 at 1:37
6
\$\begingroup\$

I'd start with a perlin noise, filtered carefully. You'd end with something like in the picture attached to the question, with floating islands. Juste remove the floating islands afterwards using a counting algorithm like the ones discussed here

\$\endgroup\$
5
  • \$\begingroup\$ Oh I think I get it now. I need to use 2D perlin noise, not 1D. Could you elaborate on said filtering? \$\endgroup\$
    – Xeon06
    Dec 5, 2011 at 16:45
  • 2
    \$\begingroup\$ I can't post pictures right now, but I'm just talking about a simple threshold filter à-la if(0.3>pixelValue>0.5) KeepIt();. The 'carefully' bit is about getting 0.3 and 0.5 right. You could also have a linear (or not) gradient, starting with high alpha at the top, gradually getting to 0 at the bottom, so you have room for a sky, and the ground is mostly filled up. Hope that helps. \$\endgroup\$
    – Ravachol
    Dec 5, 2011 at 17:05
  • \$\begingroup\$ @Ravachol If you post a link to a picture, someone with more rep can add it to your post for you. \$\endgroup\$ Dec 5, 2011 at 18:50
  • \$\begingroup\$ "if(0.3>pixelValue>0.5)", I guess this is just a typo, but it can be confusing to have contradictory things in you post... Can you please edit that? \$\endgroup\$
    – jcora
    Dec 11, 2011 at 16:19
  • \$\begingroup\$ I can't seem to edit a comment. Read "if(0.3<pixelValue<0.5)", obviously. \$\endgroup\$
    – Ravachol
    Dec 12, 2011 at 9:33
4
\$\begingroup\$

I actually implemented this starting from bummzack excellent answer.

Here are the steps I ended up with:

  1. Generate an image with Perlin noise
  2. Floodfill where you want some terrain
  3. Dilation + erosion to remove the hollows that are too small
  4. Remove the remaining background regions inside the terrain
  5. Antialiasing

And this is an example of the result: example of generated terrain

I wrote a detailed article about the whole process here and the code(JavaScript) is open source, check it out if you want something ready to use ;)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .