public bool ContainsAdjacentCells(Room other) { foreach (Vector2 cell in other) { if ( this.ContainsCell(new Vector2(cell.x - 1, cell.y)) || this.ContainsCell(new Vector2(cell.x + 1, cell.y)) || this.ContainsCell(new Vector2(cell.x, cell.y - 1)) || this.ContainsCell(new Vector2(cell.x, cell.y + 1)) ) { return true; } } return false; }
/// <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; }
internal bool IsTouching(Room roomB) { if (this.Overlaps(roomB)) return true; if ( Position.x <= roomB.bounds.xMax && bounds.xMax >= roomB.Position.x && Position.y <= roomB.bounds.yMax && bounds.yMax >= roomB.Position.y) return ContainsAdjacentCells(roomB); return false; }
private void SpawnEnemy(Transform parent, Room room, KillEnemyGoal goal, int amount) { do { Vector2 cell = room.GetRandomCell() + Vector2.one / 2; //center enemy on cell GameObject enemy = ((GameObject)Instantiate(goal.enemy, drawer.GetWorldPosition(cell), Quaternion.Euler(0, Random.Range(0, 360), 0))); enemy.transform.SetParent(parent); enemy.GetComponent<EnemyChar>().onDeath.AddListener(goal.EnemyKilled); } while (--amount > 0); }
public bool Overlaps(Room other) { if (this.bounds.Overlaps(other.bounds)) { foreach (Vector2 cell in other) { if (this.Contains(cell)) return true; } } return false; }
private static int AddCells(Vector2 pos, Vector2 size, Dungeon dungeon, Room room) { int cellsAdded = 0; for (int y = (int)pos.y; y < pos.y + size.y; y++) { for (int x = (int)pos.x; x < pos.x + size.x; x++) { if (x < dungeon.Width && y < dungeon.Height) { int roomCells = room.CellCount; room.AddCell(x, y); if (roomCells < room.CellCount) cellsAdded++; } } } return cellsAdded; }
private static int AddCells(Rect brush, Dungeon dungeon, Room room) { return AddCells(brush.position, brush.size, dungeon, room); }
static void MoveBrush( Dungeon dungeon, Vector2 startingPosition, Vector2 corridorDirection, Room room, Vector2 minBrushSize, Vector2 maxBrushSize, ref Rect brush) { int modifier = (Dungeon.Random.value() <= 0.75 ? -1 : 1); brush.x += Dungeon.Random.Range(1f, brush.width * 0.75f) * modifier; //add some horizontal offset based off of the last calculated width brush.y += Dungeon.Random.Range(1f, brush.height * 0.75f) * modifier; //add some vertical offset based off of the last calculated height brush.x = Mathf.RoundToInt(brush.x); brush.y = Mathf.RoundToInt(brush.y); //and that they are not too further left or above what they could if (corridorDirection.y == 0 && brush.x < startingPosition.x) brush.x = (int)startingPosition.x; if (corridorDirection.x == 0 && brush.y < startingPosition.y) brush.y = (int)startingPosition.y; //ensure the new coordinates are within the dungeon brush.x = Mathf.Clamp(brush.x, 0, dungeon.Width - minBrushSize.x); brush.y = Mathf.Clamp(brush.y, 0, dungeon.Height - minBrushSize.y); brush.x = Mathf.Clamp(brush.x, room.Bounds.x - maxBrushSize.x, room.Bounds.xMax - 1); brush.y = Mathf.Clamp(brush.y, room.Bounds.y - maxBrushSize.y, room.Bounds.yMax - 1); }
private static bool CreateBrush( Vector2 minBrushSize, Vector2 maxBrushSize, Vector2 startingPosition, Vector2 corridorDirection, Dungeon dungeon, Room room, ref Rect brush) { //make sure a segment with the given dimensions won't go over the room bounds brush.width = Mathf.RoundToInt(Dungeon.Random.Range(minBrushSize.x, maxBrushSize.x - Mathf.Min(0, brush.x - startingPosition.x))); brush.height = Mathf.RoundToInt(Dungeon.Random.Range(minBrushSize.y, maxBrushSize.y - Mathf.Min(0, brush.y - startingPosition.y))); Rect brushPerimeter = new Rect(brush); Vector2 offset = corridorDirection.YX(); brushPerimeter.min -= offset; brushPerimeter.max += offset; bool hadToExpandBrush = !room.Size.IsZero() && !room.Bounds.Overlaps(brushPerimeter); //make sure this new part will be connected to the room! while (!corridorDirection.IsZero() && hadToExpandBrush && !dungeon.OverlapsCorridor(brush.position, brush.size)) { brush.width += corridorDirection.y; brush.height += corridorDirection.x; hadToExpandBrush = !room.Bounds.Overlaps(brush); } //make sure this new part won't go over a corridor! while (!corridorDirection.IsZero() && brush.width > minBrushSize.x && brush.height > minBrushSize.y && dungeon.OverlapsCorridor(brush.position, brush.size)) { if (hadToExpandBrush) //there's no point in reducing the brush if it had to be expanded to begin with! return false; brush.width -= corridorDirection.y; brush.height -= corridorDirection.x; } brush.width = Mathf.Min(brush.width, maxBrushSize.x); brush.height = Mathf.Min(brush.height, maxBrushSize.y); return true; }
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; }