Search Unity

2D array dungeon generation

Discussion in 'Scripting' started by darryldonohoe, Jan 26, 2015.

  1. darryldonohoe

    darryldonohoe

    Joined:
    Jan 10, 2012
    Posts:
    55
    Hey there i don't know if this is the right section. But it would be helpful if i could get some suggestions comments or whatever.
    Anyway, i am trying to create is a top down 2d array dungeon generator like Zelda, Binding of Isaac. The method i was thinking of is like:

    - create a grid of classes, each class has its own variables including a "type-cell" int, at the start fill the entire grid with type 0(meaning empty)
    - Set a random x and y position as the starting cell with a "pre-direction" this direction will determine the next cell position. The direction variable will be randomized before each cell being instantiated, not only are there 4 direction. But! Also multiple directions possible. So in some cases it branch of like: north, south, west
    - Step 2 will be repeated until the amount of cells is equal to iterations(maximum amount of rooms)

    I have the following script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DungeonGenerator : MonoBehaviour
    5. {
    6.     public int width;
    7.     public int length;
    8.  
    9.     public int iterations;
    10.  
    11.     private int newDirection;
    12.     private int rooms;
    13.  
    14.     private Vector2[] positions;
    15.  
    16.     private int prevX;
    17.     private int prevY;
    18.  
    19.     private int nextX;
    20.     private int nextY;
    21.  
    22.     private int nextDir;
    23.  
    24.     public RoomID[,] mapArray;
    25.  
    26.     public Texture2D room;
    27.     public Texture2D start;
    28.     public Texture2D empty;
    29.  
    30.     private float miniMap;
    31.     private float icon;
    32.  
    33.     void Start()
    34.     {
    35.         mapArray = new RoomID[width,length];
    36.         positions = new Vector2[iterations+1];
    37.  
    38.         miniMap = Screen.height;
    39.         icon = (miniMap/length);
    40.  
    41.         for(int x = 0; x < width; x++)
    42.         {
    43.             for(int y = 0; y < length; y++)
    44.             {
    45.                 mapArray[x,y] = new RoomID();
    46.  
    47.                 mapArray[x,y].xPos = x;
    48.                 mapArray[x,y].yPos = y;
    49.                 mapArray[x,y].type = 0;
    50.             }
    51.         }
    52.  
    53.         Generate();
    54.     }
    55.  
    56.     void Generate()
    57.     {
    58.         while(rooms <= iterations)
    59.         {
    60.             if(rooms == 0)
    61.             {
    62.                 positions[rooms] = new Vector2(Random.Range(1,width-1),Random.Range(1,length-1));
    63.  
    64.                 mapArray[(int)positions[rooms].x,(int)positions[rooms].y].type = 2;
    65.                 mapArray[(int)positions[rooms].x,(int)positions[rooms].y].id = rooms;
    66.  
    67.                 nextDir = Random.Range(0,3);
    68.                 mapArray[(int)positions[rooms].x,(int)positions[rooms].y].nextDirection = nextDir;
    69.  
    70.                 prevX = (int)positions[rooms].x;
    71.                 prevY = (int)positions[rooms].y;
    72.  
    73.                 rooms ++;
    74.             }
    75.             else
    76.             {
    77.                 nextDir = Random.Range (0,3);
    78.                 nextX = 0;
    79.                 nextY = 0;
    80.  
    81.                 if(nextDir == 0)
    82.                 {
    83.                     nextX = prevX;
    84.                     nextY = ((int)positions[rooms-1].y - 1);
    85.  
    86.                     if(nextX >= 0 && nextX < width && nextY >= 0 && nextY < length)
    87.                     {
    88.                         if(mapArray[nextX,nextY].type == 0)
    89.                         {
    90.                             positions[rooms] = new Vector2(nextX,nextY);
    91.  
    92.                             prevX = (int)positions[rooms].x;
    93.                             prevY = (int)positions[rooms].y;
    94.  
    95.                             mapArray[nextX,nextY].type = 1;
    96.                         }
    97.                     }
    98.                 }
    99.                 if(nextDir == 1)
    100.                 {
    101.                     nextX = prevX;
    102.                     nextY = ((int)positions[rooms-1].y + 1);
    103.  
    104.                     if(nextX >= 0 && nextX < width && nextY >= 0 && nextY < length)
    105.                     {
    106.                         if(mapArray[nextX,nextY].type == 0)
    107.                         {
    108.                             positions[rooms] = new Vector2(nextX,nextY);
    109.  
    110.                             prevX = (int)positions[rooms].x;
    111.                             prevY = (int)positions[rooms].y;
    112.  
    113.                             mapArray[nextX,nextY].type = 1;
    114.                         }
    115.                     }
    116.                 }
    117.                 if(nextDir == 2)
    118.                 {
    119.                     nextX = ((int)positions[rooms-1].x - 1);
    120.                     nextY = prevY;
    121.  
    122.                     if(nextX >= 0 && nextX < width && nextY >= 0 && nextY < length)
    123.                     {
    124.                         if(mapArray[nextX,nextY].type == 0)
    125.                         {
    126.                             positions[rooms] = new Vector2(nextX,nextY);
    127.                            
    128.                             prevX = (int)positions[rooms].x;
    129.                             prevY = (int)positions[rooms].y;
    130.  
    131.                             mapArray[nextX,nextY].type = 1;
    132.                         }
    133.                     }
    134.                 }
    135.                 if(nextDir == 3)
    136.                 {
    137.                     nextX = ((int)positions[rooms-1].x + 1);
    138.                     nextY = prevY;
    139.  
    140.                     if(nextX >= 0 && nextX < width && nextY >= 0 && nextY < length)
    141.                     {
    142.                         if(mapArray[nextX,nextY].type == 0)
    143.                         {
    144.                             positions[rooms] = new Vector2(nextX,nextY);
    145.                            
    146.                             prevX = (int)positions[rooms].x;
    147.                             prevY = (int)positions[rooms].y;
    148.  
    149.                             mapArray[nextX,nextY].type = 1;
    150.                         }
    151.                     }
    152.                 }
    153.  
    154.                 rooms++;
    155.             }
    156.         }
    157.     }
    158.  
    159.  
    160.     void OnGUI()
    161.     {
    162.         GUI.BeginGroup(new Rect(miniMap/2,0,miniMap,miniMap));
    163.  
    164.         for(int x = 0; x < width; x++)
    165.         {
    166.             for(int y = 0; y < length; y++)
    167.             {
    168.                 if(mapArray[x,y].type == 0)
    169.                 {
    170.                     GUI.DrawTexture(new Rect(x*icon,y*icon,icon,icon), empty);
    171.                 }
    172.                 else if(mapArray[x,y].type == 1)
    173.                 {
    174.                     GUI.DrawTexture(new Rect(x*icon,y*icon,icon,icon), room);
    175.                 }
    176.                 else if(mapArray[x,y].type == 2)
    177.                 {
    178.                     GUI.DrawTexture(new Rect(x*icon,y*icon,icon,icon), start);
    179.                 }
    180.             }
    181.         }
    182.  
    183.         GUI.EndGroup();
    184.     }
    185. }
    186.  
    And the "RoomID" class:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RoomID
    5. {
    6.     public int type;
    7.  
    8.     public int id;
    9.  
    10.     public int distance;
    11.  
    12.     public int intensity;
    13.  
    14.     public int xPos;
    15.     public int yPos;
    16.    
    17.     public int nextDirection;    //0 = north
    18.                                 //1 = south
    19.                                 //2 = west
    20.                                 //3 = east
    21.                                 //4 = north/south
    22.                                 //5 = west/east
    23.                                 //6 = north/west
    24.                                 //7 = north/east
    25.                                 //8 = south/west
    26.                                 //9 = south/east
    27.                                 //10 = north/east/south
    28.                                 //11 = north/west/south
    29.                                 //12 = north/east/west
    30.                                 //13 = south/east/west
    31.                                 //14 = north/east/south/west
    32. }
    33.  
    As you can see, in the RoomID class i have a int called nextDirection with examples which value is what.
    This set up creates a very basic dungeon lay-out. (since i have just 4 directions set up at the moment)
    However, sometimes rooms get separated from the path, or i end up with just 3 rooms. Probably because its trying to instantiate a room on a already taken cell or outside of the grid. Which i thought i already had taken care of. The 2 if statements in the actual script.

    I also had an idea once i have the basics working, for the generator to instantiate bigger "cells". So in the nextDirection int in the RoomID class to have more values like:
    - 15 = square (1 cell upper left 1 cell upper right 1 cell down left and 1 down right)
    - 16 = line ( 1 cell up 1 cell down)
    etc..

    This would probably be set up in the actual instantiating cells process. With an if statement which contains instantiating 2, 4 or maybe more cells at their given location.

    What do you guys think? Is there a better way around this? Or do you have any suggestions improving my script? I would be very happy to hear your responses!

    Cheers,
    Darryl