public Corridor[] RemoveAt(int index) { if (index < 0 || index >= Length) throw new System.ArgumentOutOfRangeException("index", "Value should be in the range 0 " + Length); Corridor[] result = new Corridor[2]; if (index > 0) result[0] = CreateInstance(bounds.position, index, _direction); if (index < _length - 1) result[1] = CreateInstance(this[index + 1], _length - index - 1, _direction); foreach (DungeonSection connection in connections) { if (result[0] && connection.ContainsCell(Position - Direction)) result[0].AddConnection(connection); else if (result[1] && connection.ContainsCell(LastCell + Direction)) result[1].AddConnection(connection); connection.RemoveConnection(this); } return result; }
/// <summary> /// Creates a corridor. /// </summary> /// <param name="roomBounds">Position and dimension of the room where the corridor shall start.</param> /// <param name="direction">The direction (right or bottom) of the corridor.</param> /// <param name="corridor">Bounds of the corridor created.</param> /// <returns>True if a corridor was created without any intersections.</returns> public static bool CarveCorridor(Dungeon dungeon, Room room, Vector2 direction, Vector2 minMaxCorridorLength, Vector2 minRoomDimensions, out Corridor corridor) { corridor = Corridor.CreateInstance(new Rect(), direction); if (!CanFitCorridor(dungeon, direction, room.Bounds, minMaxCorridorLength)) { return false; } Vector2 corridorStart = Vector2.zero; int tries = 10; bool maySpawnCorridor = false; Vector2 sideOffset = direction.YX(); for (int count = 0; !maySpawnCorridor && count < tries; count++) { corridorStart = room.GetRandomCell(); //move the corridor starting point outside the room while (corridorStart.x < dungeon.Width && corridorStart.y < dungeon.Height && room.ContainsCell(corridorStart)) corridorStart += direction; Vector2 offsetA = corridorStart + sideOffset; Vector2 offsetB = corridorStart - sideOffset; if (dungeon.IsWithinDungeon(offsetA)) { if (dungeon[offsetA] != null) { maySpawnCorridor = false; continue; } else { maySpawnCorridor = true; } } if (dungeon.IsWithinDungeon(offsetB)) { if (dungeon[offsetB] != null) { maySpawnCorridor = false; continue; } else { maySpawnCorridor = true; } } } corridor.Position = corridorStart; //if there would be no space for the smallest room after making a corridor with the minimum length, no use creating one if ((direction.x != 0 && corridor.X + minRoomDimensions.x >= dungeon.Width) || (direction.y != 0 && corridor.Y + minRoomDimensions.y >= dungeon.Height)) return false; //move the end of the corridor to the very edge of the room bounds (on the direction the corridor should go) while ((direction.x != 0 && corridor.LastCell.x < room.Bounds.xMax) || (direction.y != 0 && corridor.LastCell.y < room.Bounds.yMax)) corridor.Length++; corridor.Length += Mathf.CeilToInt(Dungeon.Random.Range(minMaxCorridorLength.x, minMaxCorridorLength.y)); if (corridor.Length == 0) { Debug.LogWarning("No use creating a corridor with 0 length (" + room.Bounds + ")"); return false; } int predefinedSize = corridor.Length; int actualSize = 0; for (int size = 0; size < predefinedSize; size++) { Vector2 cell = corridor[size]; if (!dungeon.IsWithinDungeon(cell) || dungeon[cell] != null) { break; } actualSize = size + 1; } corridor.Length = actualSize; bool success = corridor.Length > 0 && corridor.Length == predefinedSize; return success; }
public static bool CarveRoom(Dungeon dungeon, Corridor corridor, Vector4 brushSizeVariation, Vector2 maxRoomSize, int maxBrushStrokes, out Room room) { Vector2 startingPosition = corridor ? corridor.Bounds.max : Vector2.zero; Vector2 corridorDirection = corridor ? corridor.Direction : Vector2.zero; Vector2 minBrushSize = brushSizeVariation.XY(); Vector2 maxBrushSize = brushSizeVariation.ZW(); Rect brush = new Rect(startingPosition, Vector2.zero); //move the room one up or to the left so it aligns properly to the corridor brush.x -= corridorDirection.y; brush.y -= corridorDirection.x; room = Room.CreateInstance(brush.position, Dungeon.Random); if (brush.x < 0 || brush.y < 0 || !AdjustCoordinate(corridorDirection, minBrushSize, dungeon.Size, ref brush)) { return false; } bool enoughSpaceForRoom = !dungeon.OverlapsCorridor(brush.position, minBrushSize); while (!corridorDirection.IsZero() && !enoughSpaceForRoom //if the room is currently intersecting a corridor && ((corridorDirection.y != 0 && brush.x >= 0 && brush.x + minBrushSize.x - 1 > room.Bounds.x) //and it can be moved to the left (orUp) || (corridorDirection.x != 0 && brush.y >= 0 && brush.y + minBrushSize.y - 1 > room.Bounds.y))) //while still being attached to the corridor { //move the room and check again brush.x -= corridorDirection.y; brush.y -= corridorDirection.x; enoughSpaceForRoom = !dungeon.OverlapsCorridor(brush.position, minBrushSize);//!dungeon.SearchInArea(pos, minSize, CellType.corridor); } if (!enoughSpaceForRoom) //if a room with the minimum size possible would still intersect a corridor, stop trying to make it return false; brush.x = Mathf.Clamp(brush.x, 0, dungeon.Width); brush.y = Mathf.Clamp(brush.y, 0, dungeon.Height); bool roomCarved = false; //mark cells at random locations within the room, until the maximum tries is reached for (int tries = 0; tries < maxBrushStrokes; tries++) { if (CreateBrush( minBrushSize, maxBrushSize, startingPosition, corridorDirection, dungeon, room, ref brush)) { if (!brush.size.IsZero()) { if (!dungeon.OverlapsCorridor(brush.position, brush.size)) { if (AddCells(brush, dungeon, room) > 0) roomCarved = true; } } } MoveBrush(dungeon, startingPosition, corridorDirection, room, minBrushSize, maxBrushSize, ref brush); } if (room.Position.x < 0 || room.Position.y < 0) throw new ArgumentOutOfRangeException("Room was carved outside of dungeon!\n" + room); return roomCarved; }