/// <summary> Creates all of the rooms on the map. </summary> /// <param name="splits"> The amount of times a room should be split. </param> public void CreateRooms(int splits) { Root = new Room(0, 0, Width, Height, null); _tileMap = new int[Width, Height]; SetupTileMap(_tileMap); RecursiveSplit(splits, Root); GenerateTileMap(Root); }
/// <summary> /// Initializes a new instance of the <see cref="Room"/> class. /// </summary> /// <param name="x">The top-left x coordinate.</param> /// <param name="y">The top-left y coordinate.</param> /// <param name="width">The width of the room.</param> /// <param name="height">The height of the room.</param> /// <param name="parent">The parent of this room.</param> public Room(int x, int y, int width, int height, Room parent) { _doors = new bool[width + 1, height + 1]; _occupied = new bool[width, height]; RoomRect = new Rect(x, y, width, height); Parent = parent; Enemies = new List<Enemy>(); Items = new List<Item>(); Transparent = false; }
public static Directions DirectionEnum(Room room, Vector door) { if ((int)door.X == (int)room.RoomRect.X) { return Directions.Left; } if ((int)door.X == (int)(room.RoomRect.X + room.RoomRect.Width - 1)) { return Directions.Right; } if ((int)door.Y == (int)room.RoomRect.Y) { return Directions.Down; } return Directions.Up; }
/// <summary> Recursively creates the BSPs. </summary> /// <param name="splits"> The current number of remaining splits a room can have. </param> /// <param name="node"> The room to be split. </param> private void RecursiveSplit(int splits, Room node, int enumeration = 0) { // Avoid an infinite loop if (enumeration >= 1000) { return; } // Get the x and y-ranges. var xrange1 = (int)node.RoomRect.Left + _minRoomSize; var xrange2 = (int)node.RoomRect.Right - _minRoomSize; var yrange1 = (int)node.RoomRect.Top + _minRoomSize; var yrange2 = (int)node.RoomRect.Bottom - _minRoomSize; // Check if the room is already too small to cut. if (splits <= 0 || (xrange1 > xrange2 && yrange1 > yrange2)) { node.Deleted = StaticRandom.Random.NextDouble() <= _removeProbability; return; } // Initialize variables. int pos, door; Room.CutDirections dir; // Cut horizontally if the room is too small horizontally. if (xrange1 > xrange2) { dir = Room.CutDirections.Horizontal; } // Cut vertically if the room is too small vertically. else if (yrange1 > yrange2) { dir = Room.CutDirections.Vertical; } // Cut randomly if the room is large enough. else { var length = Enum.GetValues(typeof(Room.CutDirections)).Length; dir = (Room.CutDirections)StaticRandom.Random.Next(0, length); } // Depending on the cut direction, set up where the cut will be and where the door will be. if (dir == Room.CutDirections.Horizontal) { var tries = 0; // If you can't find a split after 1000 tries, guessing is probably OK do { pos = StaticRandom.Random.Next(yrange1, yrange2); tries++; } while (node.Parent != null && (IsOnDoor(node.Parent, dir, pos)) && tries < MaxTries); door = StaticRandom.Random.Next((int) node.RoomRect.Left + 1, (int) node.RoomRect.Right - 1); } else { var tries = 0; do { pos = StaticRandom.Random.Next(xrange1, xrange2); tries++; } while (node.Parent != null && (IsOnDoor(node.Parent, dir, pos)) && tries < MaxTries); door = StaticRandom.Random.Next((int)node.RoomRect.Top + 1, (int)node.RoomRect.Bottom - 1); } // Split the room. node.SplitRoom(dir, new Vector(pos, pos), door); // Recursively cut the room's children. RecursiveSplit(splits - 1, node.ChildA, enumeration + 1); RecursiveSplit(splits - 1, node.ChildB, enumeration + 1); }
private bool IsOnDoor(Room current, Room.CutDirections dir, int pos) { if (current == null) return false; if (dir != current.Split.Direction && current.Split.Door == pos) { return true; } return IsOnDoor(current.Parent, dir, pos); }
private void GenerateTileMap(Room node) { if (node == null) return; if (node.Transparent) { GenerateTileMap(node.ChildA); GenerateTileMap(node.ChildB); } else { node.PlaceRoom(ref _tileMap); } }
/// <summary> Split the room with a direction and position. </summary> /// <param name="direction"> The direction of the split. </param> /// <param name="position"> Where the split is located. </param> /// <param name="door"> Where the door is located on the split. </param> public void SplitRoom(CutDirections direction, Vector position, int door) { Split = new Cut { Direction = direction, Position = position, Door = door }; Transparent = true; if (direction == CutDirections.Horizontal) { var x = (int)RoomRect.Left; var y1 = (int)RoomRect.Top; var y2 = (int)Split.Position.Y; var width = (int)RoomRect.Width; var height1 = (int)(Split.Position.Y - RoomRect.Top + 1); var height2 = (int)(RoomRect.Bottom - Split.Position.Y); ChildA = new Room(x, y1, width, height1, this); ChildB = new Room(x, y2, width, height2, this); ChildA.AddDoor(door, (int)position.Y); ChildB.AddDoor(door, (int)position.Y); } else { var x1 = (int)RoomRect.Left; var x2 = (int)Split.Position.X; var y = (int)RoomRect.Top; var width1 = (int)(Split.Position.Y - RoomRect.Left + 1); var width2 = (int)(RoomRect.Right - Split.Position.X); var height = (int)RoomRect.Height; ChildA = new Room(x1, y, width1, height, this); ChildB = new Room(x2, y, width2, height, this); ChildA.AddDoor((int)position.X, door); ChildB.AddDoor((int)position.X, door); } // Add parent doors to room var parent = this; while (parent != null) { for (var y = (int)parent.RoomRect.Y; y < parent.RoomRect.Y + parent.RoomRect.Height; y++) { for (var x = (int)parent.RoomRect.X; x < parent.RoomRect.X + parent.RoomRect.Width; x++) { if (!parent.GetDoor(x, y)) continue; ChildA.AddDoor(x, y); ChildB.AddDoor(x, y); } } parent = parent.Parent; } }