Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am currently working on a small game that will generate a world with caves and entrances to the caves, something like Terraria if you will. Today I reached some trouble on the world/cave generation code. I want to use Perlin Noise but I am not so sure how to implement it into my code. Could someone point me in the right direction for a reference or even code samples?

share|improve this question
    
possible duplicate of Terrain Generation for Tile-Based 2D Platformer –  Byte56 Jul 16 '12 at 22:49
2  
And maybe: gamedev.stackexchange.com/questions/20588/… depending on the style you want. And gamedev.stackexchange.com/questions/18735/… and gamedev.stackexchange.com/questions/14238/… Just search this site for Terraria. –  Byte56 Jul 16 '12 at 22:51
    
Yes I've seen most of these and get the basic idea. The thing I'm clueless on is how to implement this in XNA to where I can later use it as a terrain for a player. –  Noah Simpson Jul 18 '12 at 1:02
1  
The implementation is going to be specific to the rest of your game. The developers job is to take concepts and turn them into code. –  Byte56 Jul 18 '12 at 3:24
add comment

1 Answer

Here's something to get you started; for organic structures such as caves I've found that random walk works fine, and it's great because it's dead simple.

This sample code does the following:

  • Create a basic 2d terrain (any method will do)
  • Choose a cave entrance
  • Starting from that cave entrance, do a 2D random walk and "carve" out the interior of the cave, making sure that we don't break through the surface

http://ideone.com/CJhzhm

using System;
using System.Collections.Generic;

public class Test
{
    static Random rand = new Random();
    static int width = 79;
    static int height = 24;
    static char[] cells = new char[width * height];
    // Cells are ordered left-to-right, top-to-bottom

    public static void Main()
    {
        GenerateRandomTerrain();

        // pick a point on the surface as the cave entrance
        int caveX = 35;
        int caveY = 0;
        while (cells[caveY * width + caveX] == ' ')
        {
            caveY++;
        }
        // drill down until we are deep underground
        while (cells[caveY * width + caveX - 1] == ' ' ||
            cells[caveY * width + caveX + 1] == ' ')
        {
            cells[caveY * width + caveX] = '.';
            caveY++;
        }

        // starting from the entrance, walk randomly within the terrain,
        // "carving out" the cave
        // make sure we do not create new entrances; the carving must not go
        // adjacent to an "open air" cell
        for (int i = 0; i < 1000; i++)
        {
            // "carve out" the current cell
            cells[caveY * width + caveX] = '.';

            // Get random direction:
            // 0: up
            // 1: right
            // 2: down
            // 3: left
            int dir = rand.Next(4);
            switch (dir)
            {
                case 0: // up
                    if (IsValidCaveCell(caveX, caveY + 1))
                    {
                        caveY++;
                    }
                    break;
                case 1: // right
                    if (IsValidCaveCell(caveX + 1, caveY))
                    {
                        caveX++;
                    }
                    break;
                case 2: // down
                    if (IsValidCaveCell(caveX, caveY - 1))
                    {
                        caveY--;
                    }
                    break;
                case 3: // left
                    if (IsValidCaveCell(caveX - 1, caveY))
                    {
                        caveX--;
                    }
                    break;
            }
        }

        // Show our results
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                System.Console.Write(cells[y * width + x]);
            }
            System.Console.WriteLine();
        }
    }

    static void GenerateRandomTerrain()
    {
        for (int x = 0; x < width; x++)
        {
            int elevation = rand.Next(height * 4 / 5, height);
            for (int y = 0; y < height; y++)
            {
                if (y < height - elevation)
                {
                    // Open air
                    cells[y * width + x] = ' ';
                }
                else
                {
                    // Ground
                    cells[y * width + x] = 'X';
                }
            }
        }
    }

    static bool IsValidCaveCell(int x, int y)
    {
        // a cave cell is valid if:
        // - it doesn't exceed the world boundaries
        // - it isn't adjacent to an "open air" cell
        if (x < 0 || x >= width || y < 0 || y >= height)
        {
            // out of world bounds
            return false;
        }
        for (int dx = -1; dx <= 1; dx++)
        {
            if (x + dx < 0 || x + dx >= width)
            {
                continue;
            }
            for (int dy = -1; dy <= 1; dy++)
            {
                if (y + dy < 0 || y + dy >= height)
                {
                    continue;
                }
                if (cells[(y + dy) * width + (x + dx)] == ' ')
                {
                    // adjacent to "open air" cell
                    return false;
                }
            }
        }
        return true;
    }
}

Sample output:

          X   XX  XXX     X                    X       X   XX   X  XX X  X     
        X XX  XX XXXX     X             X      X  X  X X X XX   X  XXXXX X X X 
   X XXXXXXXX XXXXXXX  XXXXX X X    X   XX XX  X  X  X X X XX  XXXXXXXXXXX X X 
XX X XXXXXXXXXXXXXXXXXXXXXXXXX X XX.XXXXXXXXXX X  X XX X X XX XXXXXXXXXXXX X XX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..XX........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.......X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXX...............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXX.X.XXXXXXXXXXXXX..X.........X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXX.....XXXXXXXXXXX...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX......XXXXXXXXXXXXX....X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXX.X......XX...X....XXX.X.XX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
.XXXXXXX.........X........XXX...XX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
......X..X.XX..X.X.............XXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
...........XXXXX...................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
..........XXXXXX........X.....X....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

You can play around with the number of iterations (it's set to 1000) to see what results you prefer.

Note that for platformers (you mentioned terraria) you would want to make sure players can't get stuck, that is there are no platforms for the player to jump out of. Platformers also prefer caves that are flatter than they are deep; you can modify the random walk to bias horizontal movements more than vertical for instance.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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