Unity_Dungeonize 随机生成迷宫

   本文对随机生成迷宫的实现思路进行记录,其作用在于为游戏过程提供随机性以及节省开发周期,下面是Dungeonize的结构

  随机迷宫的生成主要包括几个阶段

  

 

1.生成房间体结构,为墙体,自定义房间,自定义物体生成平台

 

 1     for (var i = 0; i < room_count; i++) {
 2                 Room room = new Room (); 
 3                 if (rooms.Count == 0) {
 4                     //初始房间生成玩家和任务事件监听
 5                     room.x = (int)Mathf.Floor (map_size / 2f);
 6                     room.y = (int)Mathf.Floor (map_size / 2f); //Random.Range(10,20);
 7                     room.w = Random.Range (min_size, max_size);
 8                     if (room.w % 2 == 0) room.w += 1;
 9                     room.h = Random.Range (min_size, max_size);
10                     if (room.h % 2 == 0) room.h += 1;
11                     room.branch = 0;
12                     lastRoom = room;
13                 } else {
14                     int branch = 0;
15                     if (collision_count == 0) {
16                         branch = Random.Range (5, 20); //complexity
17                     }
18                     room.branch = branch;
19 
20                     lastRoom = rooms [rooms.Count - 1];
21                     int lri = 1;
22 
23                     while (lastRoom.dead_end) {
24                         lastRoom = rooms [rooms.Count - lri++];
25                     }
26 
27 
28                     if (direction == "set") {
29                         string newRandomDirection = directions[Random.Range(0, directions.Count)];
30                         direction = newRandomDirection;
31                         while (direction == oldDirection)
32                         {
33                             newRandomDirection = directions[Random.Range(0, directions.Count)];
34                             direction = newRandomDirection;
35                         }
36 
37                     }
38                     this.roomMarginTemp = Random.RandomRange(0, this.roomMargin - 1);
39                     //邻接方位生成房间
40                     if (direction == "y") {
41                         room.x = lastRoom.x + lastRoom.w + Random.Range (3, 5) + this.roomMarginTemp;
42                         room.y = lastRoom.y;
43                     } else if (direction == "-y") {
44                         room.x = lastRoom.x - lastRoom.w - Random.Range (3, 5) - this.roomMarginTemp;
45                         room.y = lastRoom.y;
46                     } else if (direction == "x") {
47                         room.y = lastRoom.y + lastRoom.h + Random.Range (3, 5) + this.roomMarginTemp;
48                         room.x = lastRoom.x;
49                     } else if (direction == "-x") {
50                         room.y = lastRoom.y - lastRoom.h - Random.Range (3, 5) - this.roomMarginTemp;
51                         room.x = lastRoom.x;
52                     }
53 
54                     room.w = Random.Range (min_size, max_size);
55                     if (room.w % 2 == 0) room.w += 1;
56 
57                     room.h = Random.Range (min_size, max_size);
58                     if (room.h % 2 == 0) room.h += 1;
59 
60                     room.connectedTo = lastRoom;
61                 }

  在随机产生生成房间体后,生成墙体形成一个完整的房间结构,为之后prefab提供空间

//wall 
for
(int x = 0; x < map_size_x -1; x++) { for (int y = 0; y < map_size_y -1; y++) { if (map [x, y].type == 0) { if (map [x + 1, y].type == 1 || map [x + 1, y].type == 3) { //west map [x, y].type = 11; map [x, y].room = map [x + 1, y].room; } if (x > 0) { if (map [x - 1, y].type == 1 || map [x - 1, y].type == 3) { //east map [x, y].type = 9; map [x, y].room = map [x - 1, y].room; } } if (map [x, y + 1].type == 1 || map [x, y + 1].type == 3) { //south map [x, y].type = 10; map [x, y].room = map [x, y + 1].room; } if (y > 0) { if (map [x, y - 1].type == 1 || map [x, y - 1].type == 3) { //north map [x, y].type = 8; map [x, y].room = map [x, y - 1].room; } } } } }

通过list存储方位参数

//tile types for ease
        public static List<int> roomsandfloors = new List<int> { 1, 3 };
        public static List<int> corners = new List<int> {4,5,6,7};
        public static List<int> walls = new List<int> {8,9,10,11};  //wall direction 
        private static List<string> directions = new List<string> {"x","y","-y","-x"}; //,"-y"};
        

根据lis存储过道结构

 1     //corners
 2             for (int x = 0; x < map_size_x -1; x++) {
 3                 for (int y = 0; y < map_size_y -1; y++) {
 4                     if (walls.Contains (map [x, y + 1].type) && walls.Contains (map [x + 1, y].type) && roomsandfloors.Contains (map [x + 1, y + 1].type)) { //north
 5                         map [x, y].type = 4;
 6                         map [x, y].room = map [x + 1, y + 1].room;
 7                     }
 8                     if (y > 0) {
 9                         if (walls.Contains (map [x + 1, y].type) && walls.Contains (map [x, y - 1].type) && roomsandfloors.Contains (map [x + 1, y - 1].type)) { //north
10                             map [x, y].type = 5;
11                             map [x, y].room = map [x + 1, y - 1].room;
12 
13                         }
14                     }
15                     if (x > 0) {
16                         if (walls.Contains (map [x - 1, y].type) && walls.Contains (map [x, y + 1].type) && roomsandfloors.Contains (map [x - 1, y + 1].type)) { //north
17                             map [x, y].type = 7;
18                             map [x, y].room = map [x - 1, y + 1].room;
19 
20                         }
21                     }
22                     if (x > 0 && y > 0) {
23                         if (walls.Contains (map [x - 1, y].type) && walls.Contains (map [x, y - 1].type) && roomsandfloors.Contains (map [x - 1, y - 1].type)) { //north
24                             map [x, y].type = 6;
25                             map [x, y].room = map [x - 1, y - 1].room;
26 
27                         }
28                     }
29                     /* door corners --- a bit problematic in this version */
30                     if (map [x, y].type == 3) { 
31                         if (map [x + 1, y].type == 1) {
32                             map [x, y + 1].type = 11;
33                             map [x, y - 1].type = 11;
34                         } else if (Dungeon.map [x - 1, y].type == 1) {
35                             map [x, y + 1].type = 9;
36                             map [x, y - 1].type = 9;
37                         }
38                     }
39 
40                 }
41             }

 这样一个房间体的完整结构已经创建完毕,之后对迷宫结构生成地下城结构

        for (var y = 0; y < Dungeon.map_size_y; y++) {
            for (var x = 0; x < Dungeon.map_size_x; x++) {
                int tile = Dungeon.map [x, y].type;
                int orientation = Dungeon.map[x, y].orientation;
                GameObject created_tile;
                Vector3 tile_location;
                if (!makeIt3d) {
                    tile_location = new Vector3 (x * tileScaling, y * tileScaling, 0);
                } else {
                    tile_location = new Vector3 (x * tileScaling, 0, y * tileScaling);
                }

                created_tile = null;
                if (tile == 1) {
                    GameObject floorPrefabToUse = floorPrefab;
                    Room room = Dungeon.map[x,y].room;
                    if(room != null){
                        foreach(CustomRoom customroom in customRooms){
                            if(customroom.roomId == room.room_id){
                                floorPrefabToUse = customroom.floorPrefab;
                                break;
                            }
                        }
                    }

                    created_tile = GameObject.Instantiate (floorPrefabToUse, tile_location, Quaternion.identity) as GameObject;
                }
                
                if ( Dungeon.walls.Contains(tile)) {
                    GameObject wallPrefabToUse = wallPrefab;
                    Room room = Dungeon.map[x,y].room;
                    if(room != null){
                        foreach(CustomRoom customroom in customRooms){
                            if(customroom.roomId == room.room_id){
                                wallPrefabToUse = customroom.wallPrefab;
                                break;
                            }
                        }
                    }

                    created_tile = GameObject.Instantiate (wallPrefabToUse, tile_location, Quaternion.identity) as GameObject;
                    if(!makeIt3d){
                        created_tile.transform.Rotate(Vector3.forward  * (-90 * (tile -4)));
                    }
                    else{
                        created_tile.transform.Rotate(Vector3.up  * (-90 * (tile -4)));
                    }
                }
                
                if (tile == 3) {
                    if (corridorFloorPrefab)
                    {
                        created_tile = GameObject.Instantiate(corridorFloorPrefab, tile_location, Quaternion.identity) as GameObject;
                    }
                    else
                    {
                        created_tile = GameObject.Instantiate(floorPrefab, tile_location, Quaternion.identity) as GameObject;
                    }

                    if (orientation == 1 && makeIt3d)
                    {
                        created_tile.transform.Rotate(Vector3.up * (-90));
                    }

                }

                if (Dungeon.corners.Contains(tile)) {
                    GameObject cornerPrefabToUse = cornerPrefab;
                    Room room = Dungeon.map[x,y].room;
                    if(room != null){
                        foreach(CustomRoom customroom in customRooms){
                            if(customroom.roomId == room.room_id){
                                cornerPrefabToUse = customroom.cornerPrefab;
                                break;
                            }
                        }
                    }


                    if(cornerPrefabToUse){ //there was a bug in this line. A good man helped for fix.
                        created_tile = GameObject.Instantiate (cornerPrefabToUse, tile_location, Quaternion.identity) as GameObject;
                        if(cornerRotation){
                            if(!makeIt3d){
                                created_tile.transform.Rotate(Vector3.forward  * (-90 * (tile -4)));
                            }
                            else{
                                created_tile.transform.Rotate(Vector3.up  * (-90 * (tile -4)));
                            }
                        }
                    }
                    else{
                        created_tile = GameObject.Instantiate (wallPrefab, tile_location, Quaternion.identity) as GameObject;
                    }
                }
                
                if (created_tile) {
                    created_tile.transform.parent = transform;
                }
            }
        }

  迷宫生成后,需要对房间内容进行添加,随机的物品以及房间为玩家提供游玩条件,特定的内容包含战斗条件或者任务条件

//Spawn Objects;
        List<SpawnList> spawnedObjectLocations = new List<SpawnList> ();

        //OTHERS
        for (int x = 0; x < Dungeon.map_size_x; x++) {
            for (int y = 0; y < Dungeon.map_size_y; y++) {
                if (Dungeon.map [x, y].type == 1 &&
                        ((Dungeon.startRoom != Dungeon.map [x, y].room && Dungeon.goalRoom != Dungeon.map [x, y].room) || maximumRoomCount <= 3)) {
                    var location = new SpawnList ();

                    location.x = x;
                    location.y = y;
                    if (Dungeon.walls.Contains(Dungeon.map[x + 1, y].type)) {
                        location.byWall = true;
                        location.wallLocation = "S";
                    }
                    else if (Dungeon.walls.Contains(Dungeon.map[x - 1, y].type))
                    {
                        location.byWall = true;
                        location.wallLocation = "N";
                    }
                    else if (Dungeon.walls.Contains(Dungeon.map[x, y + 1].type)) {
                        location.byWall = true;
                        location.wallLocation = "W";
                    }
                    else if (Dungeon.walls.Contains(Dungeon.map [x, y - 1].type)) {
                        location.byWall = true;
                        location.wallLocation = "E";
                    }

                    if (Dungeon.map [x + 1, y].type == 3 || Dungeon.map [x - 1, y].type == 3 || Dungeon.map [x, y + 1].type == 3 || Dungeon.map [x, y - 1].type == 3) {
                        location.byCorridor = true;
                    }
                    if (Dungeon.map [x + 1, y + 1].type == 3 || Dungeon.map [x - 1, y - 1].type == 3 || Dungeon.map [x - 1, y + 1].type == 3 || Dungeon.map [x + 1, y - 1].type == 3) {
                        location.byCorridor = true;
                    }
                    location.room = Dungeon.map[x,y].room;

                    int roomCenterX = (int)Mathf.Floor(location.room.w / 2) + location.room.x;
                    int roomCenterY = (int)Mathf.Floor(location.room.h / 2) + location.room.y;

                    if(x == roomCenterX + 1 && y == roomCenterY + 1 )
                    {
                        location.inTheMiddle = true;
                    } 
                    spawnedObjectLocations.Add (location);
                }
                else if (Dungeon.map [x, y].type == 3) {
                    var location = new SpawnList ();
                    location.x = x;
                    location.y = y;    

                    if (Dungeon.map [x + 1, y].type == 1 ) {
                        location.byCorridor = true;
                        location.asDoor = 4;
                        location.room = Dungeon.map[x + 1,y].room;

                        spawnedObjectLocations.Add (location);
                    }
                    else if(Dungeon.map [x - 1, y].type == 1){
                        location.byCorridor = true;
                        location.asDoor = 2;
                        location.room = Dungeon.map[x - 1,y].room;

                        spawnedObjectLocations.Add (location);    
                    }
                    else if (Dungeon.map [x, y + 1].type == 1 ){
                        location.byCorridor = true;
                        location.asDoor = 1;
                        location.room = Dungeon.map[x,y + 1].room;

                        spawnedObjectLocations.Add (location);
                    }
                    else if (Dungeon.map [x, y - 1].type == 1){
                        location.byCorridor = true;
                        location.asDoor = 3;
                        location.room = Dungeon.map[x,y - 1].room;

                        spawnedObjectLocations.Add (location);                    
                    }
                }
            }
        }
        
这样就能生成基本的随机模型

2d ver

3d ver
也可以根据需求进行修改
posted @ 2020-01-18 12:48  OKSSJ  阅读(873)  评论(0编辑  收藏  举报