using System.Collections.Generic; using Godot; /// <summary> /// 地牢生成器 /// </summary> public class GenerateDungeon { public readonly TileMap TileMap; private Grid<bool> _roomGrid = new Grid<bool>(); private List<RoomInfo> _roomInfos = new List<RoomInfo>(); private int _count = 0; private int _maxCount = 30; public GenerateDungeon(TileMap tileMap) { TileMap = tileMap; } public void Generate() { GenerateRoom(null, 0); foreach (var info in _roomInfos) { //临时铺上地砖 var id = (int)TileMap.TileSet.GetTilesIds()[0]; for (int i = 0; i < info.Size.x; i++) { for (int j = 0; j < info.Size.y; j++) { TileMap.SetCell(i + (int)info.Position.x, j + (int)info.Position.y, id); } } } } private RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction) { if (_count > _maxCount) { return null; } _count++; var info = new RoomInfo(); info.Size = new Vector2(Utils.RandRangeInt(10, 30), Utils.RandRangeInt(10, 30)); info.Position = Vector2.Zero; info.Direction = direction; if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡 { //房间间隔 var space = Utils.RandRangeInt(3, 4); //中心偏移 int offset; if (direction == 0 || direction == 2) { offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.y, (int)prevRoomInfo.Size.y); } else { offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.x, (int)prevRoomInfo.Size.x); } //计算房间位置 if (direction == 0) //上 { info.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y - info.Size.y - space); } else if (direction == 1) //右 { info.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset); } else if (direction == 2) //下 { info.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + prevRoomInfo.Size.y + space); } else if (direction == 3) //左 { info.Position = new Vector2(prevRoomInfo.Position.x - info.Size.x - space, prevRoomInfo.Position.y + offset); } //是否碰到其他房间 if (_roomGrid.RectCollision(info.Position - new Vector2(1, 1), info.Size + new Vector2(2, 2))) { return null; } } _roomInfos.Add(info); _roomGrid.AddRect(info.Position, info.Size, true); //下一个房间 //0上, 1右, 2下, 3左 var dirList = new List<int>(new []{ 0, 1, 2, 3 }); if (prevRoomInfo != null) { dirList.Remove(GetReverseDirection(direction)); } while (dirList.Count > 0) { var randDir = Utils.RandChoose(dirList); var generateRoom = GenerateRoom(info, randDir); if (generateRoom == null) { break; } dirList.Remove(randDir); } return info; } private int GetReverseDirection(int direction) { switch (direction) { case 0: return 2; case 1: return 3; case 2: return 0; case 3: return 1; } return 2; } }