public GenRect(GenRect rect) { MinX = rect.MinX; MaxX = rect.MaxX; MinY = rect.MinY; MaxY = rect.MaxY; }
public static bool IsInDirection4(GenRect rect, int gx, int gy, params Direction4[] dir) { Direction8[] other = new Direction8[dir.Length]; for (int i = 0; i < dir.Length; i++) { Direction8 target = Direction8.Bottom; switch (dir[i]) { case Direction4.Right: target = Direction8.Right; break; case Direction4.Bottom: target = Direction8.Bottom; break; case Direction4.Left: target = Direction8.Left; break; case Direction4.Top: target = Direction8.Top; break; default: break; } other[i] = target; } return(IsInOctant(rect, gx, gy, other)); }
public GenRect Union(GenRect other) { GenRect rect = new GenRect( Mathf.Max(other.MinX, MinX), Mathf.Min(other.MaxX, MaxX), Mathf.Max(other.MinY, MinY), Mathf.Min(other.MaxY, MaxY)); return(rect); }
public GenTile[,] GetTiles(GenRect rect) { GenTile[,] tiles = new GenTile[rect.WidthT, rect.HeightT]; for (int x = 0; x < tiles.GetLength(0); x++) { for (int y = 0; y < tiles.GetLength(1); y++) { tiles[x, y] = GetTile(rect.MinX + x, rect.MinY + y); } } return(tiles); }
/// <summary> /// returns a symetric version of a feature based on a room /// </summary> /// <param name="feature">the features described by tiles to be placed</param> /// <param name="gx">Global position X if position changes this will change</param> /// <param name="gy">Global position Y if position changes this will change</param> /// <param name="room">The room the symetry should be in</param> /// <param name="axis">The axis symetry should be created in</param> /// <returns>The complete feature</returns> public static GenTile[,] GetSymetry(GenTile[,] feature, ref int gx, ref int gy, GenRoom room, Axis axis) { GenRect size = new GenRect(gx, gx + feature.GetLength(0) - 1, gy, gy + feature.GetLength(1) - 1); GenRect checkRect = new GenRect(size); if (axis.HasFlag(Axis.Vertical)) { do { checkRect.Transform(0, 1, 0, 0); } while (!TouchesWall(checkRect, room)); checkRect.Transform(0, -1, 0, 0); do { checkRect.Transform(0, 0, 0, 1); } while (!TouchesWall(checkRect, room)); checkRect.Transform(0, 0, 0, -1); GenTile[,] resize = checkRect.ResizeTiles(feature, ref gx, ref gy); GenTile[,] flip = resize.GetCopy().GetFlip(Axis.Vertical); resize = resize.Place(0, 0, flip); feature = resize; } if (axis.HasFlag(Axis.Horizontal)) { do { checkRect.Transform(1, 0, 0, 0); } while (!TouchesWall(checkRect, room)); checkRect.Transform(-1, 0, 0, 0); do { checkRect.Transform(0, 0, 1, 0); } while (!TouchesWall(checkRect, room)); checkRect.Transform(0, 0, -1, 0); GenTile[,] resize = checkRect.ResizeTiles(feature, ref gx, ref gy); GenTile[,] flip = resize.GetCopy().GetFlip(Axis.Horizontal); resize = resize.Place(0, 0, flip); feature = resize; } return(feature); }
public void FixOverlap() { for (int i = 0; i < Rooms.Count - 1; i++) { for (int j = i + 1; j < Rooms.Count; j++) { GenRoom a = Rooms[i]; GenRoom b = Rooms[j]; if (a.Outer.Overlaps(b.Outer)) { GenRect rA = a.Outer; GenRect rB = b.Outer; // find the union of both int uLeft = Mathf.Max(rA.MinX, rB.MinX); int uTop = Mathf.Max(rA.MinY, rB.MinY); int uRight = Mathf.Min(rA.MaxX, rB.MaxX); int uBot = Mathf.Min(rA.MaxY, rB.MaxY); GenRect union = new GenRect(uLeft, uRight, uTop, uBot); GenRoom dominant = a.SpacePriority > b.SpacePriority ? a : b; GenRoom weaker = a.SpacePriority > b.SpacePriority ? b : a; HashSet <GenPositionTile> dominantEdge = dominant.GetEdge(); for (int x = union.MinX; x <= union.MaxX; x++) { for (int y = union.MinY; y <= union.MaxY; y++) { // check if on the edge if (dominantEdge.Any(e => e.Tile == dominant.GetAtWorldspaceG(x, y))) { // this Tile is on the Edge and should be shared weaker.SetTileAtG(x, y, dominant.GetAtWorldspaceG(x, y)); } else { // remove the tile from weaker one weaker.RemoveTileAtG(x, y); } } } } } } }
public static bool TouchesWall(GenRect rect, GenRoom room) { for (int x = rect.MinX; x <= rect.MaxX; x++) { for (int y = rect.MinY; y <= rect.MaxY; y++) { GenTile check = room.GetAtWorldspaceG(x, y); if (check != null) { if (check.AnyTypes(GenDetail.DetailType.Wall)) { return(true); } } } } return(false); }
/// <summary> /// grows a room to wanted size /// </summary> /// <param name="gx">global starting positon</param> /// <param name="gy">global starting position</param> /// <param name="tWidth">target Width</param> /// <param name="tHeight">target Height</param> /// <param name="rect">the resulting Rect/best match</param> /// <param name="connectToWall">When hitting a wall should it be used?</param> /// <param name="startDir">the direction the rect should start growing in</param> /// <returns>if the procedure was successful</returns> public bool TryGrowRect( int gx, int gy, int tWidth, int tHeight, out GenRect rect, bool connectToWall = false, GenUtil.Direction4 startDir = GenUtil.Direction4.Right, GrowSettings extra = new GrowSettings()) // merge to wall { // create base rect rect = new GenRect(gx, gx, gy, gy); GenRect helper = new GenRect(rect); // this is used to confirm what is inside the rect and already allowed List <GenTile> Confirmed = new List <GenTile>(); // add the current tile to it var s = GetTiles(rect).ToList(); Confirmed.AddRange(s); // used to get easier access to // if we reached max growth in this direction // -1 is not reached // 0 is reached // 1 reached but grow 1 in the end int top = extra.Top - 1; int right = extra.Right - 1; int bot = extra.Bot - 1; int left = extra.Left - 1; GenUtil.Direction4 direction = startDir; int width = rect.WidthT; int height = rect.HeightT; int ohNo = 100; while (width < tWidth || height < tHeight) { Confirmed.Clear(); s = GetTiles(rect).ToList(); Confirmed.AddRange(s); ohNo--; helper = rect; switch (direction) { case GenUtil.Direction4.Right: if (width == tWidth || right >= 0) { break; } helper = helper.Transform(0, 0, 1, 0); List <GenTile> addR = GetTiles(helper).ToList(); addR = addR.Except(Confirmed).ToList(); if (addR.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { // we hit a wall next to us // they are automatically allowed Confirmed.AddRange(addR); rect = helper.Transform(0, 0, -1, 0); right = 1; } else { // we check the next one for safety helper = helper.Transform(0, 0, 1, 0); List <GenTile> query = GetTiles(helper).ToList(); query = query.Except(Confirmed).ToList(); if (query.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { if (connectToWall) { // try and pull the other way if (left < 1) { helper = helper.Transform(-1, 0, 0, 0); left = -1; } // we connect without problem Confirmed.AddRange(query); rect = helper.Transform(0, 0, -1, 0); right = 1; } else { // we prevent connection and transform 2 back helper = helper.Transform(0, 0, -2, 0); right = 0; rect = helper; } } else { helper.Transform(0, 0, -1, 0); rect = helper; } } break; case GenUtil.Direction4.Bottom: if (height == tHeight || bot >= 0) { break; } helper = helper.Transform(0, 0, 0, 1); List <GenTile> addB = GetTiles(helper).ToList(); addB = addB.Except(Confirmed).ToList(); if (addB.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { // we hit a wall next to us // they are automatically allowed Confirmed.AddRange(addB); rect = helper.Transform(0, 0, 0, -1); bot = 1; } else { // we check the next one for safety helper = helper.Transform(0, 0, 0, 1); List <GenTile> query = GetTiles(helper).ToList(); query = query.Except(Confirmed).ToList(); if (query.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { if (connectToWall) { if (top < 1) { helper = helper.Transform(0, -1, 0, 0); top = -1; } // we connect without problem Confirmed.AddRange(query); rect = helper.Transform(0, 0, 0, -1); bot = 1; } else { // we prevent connection and transform 2 back helper = helper.Transform(0, 0, -0, -2); bot = 0; rect = helper; } } else { helper.Transform(0, 0, 0, -1); rect = helper; } } break; case GenUtil.Direction4.Left: if (width == tWidth || left >= 0) { break; } helper = helper.Transform(1, 0, 0, 0); List <GenTile> addL = GetTiles(helper).ToList(); addL = addL.Except(Confirmed).ToList(); if (addL.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { // we hit a wall next to us // they are automatically allowed Confirmed.AddRange(addL); rect = helper.Transform(-1, 0, 0, 0); left = 1; } else { // we check the next one for safety helper = helper.Transform(1, 0, 0, 0); List <GenTile> query = GetTiles(helper).ToList(); query = query.Except(Confirmed).ToList(); if (query.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { if (connectToWall) { // try and pull the other way if (right < 1) { helper = helper.Transform(0, 0, -1, 0); right = -1; } // we connect without problem Confirmed.AddRange(query); rect = helper.Transform(-1, 0, 0, 0); left = 1; } else { // we prevent connection and transform 2 back helper = helper.Transform(-2, 0, 0, 0); left = 0; rect = helper; } } else { helper.Transform(-1, 0, 0, 0); rect = helper; } } break; case GenUtil.Direction4.Top: if (height == tHeight || top >= 0) { break; } helper = helper.Transform(0, 1, 0, 0); List <GenTile> addT = GetTiles(helper).ToList(); addT = addT.Except(Confirmed).ToList(); if (addT.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { // we hit a wall next to us // they are automatically allowed Confirmed.AddRange(addT); rect = helper.Transform(0, -1, 0, 0); top = 1; } else { // we check the next one for safety helper = helper.Transform(0, 1, 0, 0); List <GenTile> query = GetTiles(helper).ToList(); query = query.Except(Confirmed).ToList(); if (query.Any(t => t.AnyTypes(GenDetail.DetailType.Wall))) { if (connectToWall) { // try and pull the other way if (bot < 1) { helper = helper.Transform(0, 0, 0, -1); bot = -1; } // we connect without problem Confirmed.AddRange(query); rect = helper.Transform(0, -1, 0, 0); top = 1; } else { // we prevent connection and transform 2 back helper = helper.Transform(0, -2, 0, 0); top = 0; rect = helper; } } else { helper.Transform(0, -1, 0, 0); rect = helper; } } break; default: break; } width = rect.WidthT; if (left > 0) { width++; } if (right > 0) { width++; } height = rect.HeightT; if (top > 0) { height++; } if (bot > 0) { height++; } if (top >= 0 && right >= 0 && bot >= 0 && left >= 0) { break; } if (ohNo <= 0) { break; } direction = GenUtil.Rotate(direction, 1); } rect = rect.Transform(Mathf.Max(0, left), Mathf.Max(0, top), Mathf.Max(0, right), Mathf.Max(0, bot)); if (rect.WidthT == tWidth && rect.HeightT == tHeight) { return(true); } return(false); }
public static IEnumerator GetSimpleTemple() { GenData temple = new GenData(Random.Range(TempleWidth.start, TempleWidth.end), Random.Range(TempleHeight.start, TempleHeight.end)); List <GenRoom> AutoFillRoom = new List <GenRoom>(); // list of all rooms that are not allowed to be used for door placement List <GenRoom> NoAutoDoor = new List <GenRoom>(); List <GenRoom> SecretRooms = new List <GenRoom>(); GenTile Chest = GenTile.GetEmpty(); Chest.Details.Add(new GenDetail() { Char = '=', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.Chest }); GenTile pillar = GenTile.GetEmpty(); //pillar.Details.Add(new GenDetail() { Char = '\u01C1', Type = GenDetail.DetailType.Decoration }); pillar.Details.Add(new GenDetail() { Char = 'O', Type = GenDetail.DetailType.Decoration }); GenTile[,] pillars = new GenTile[, ] { { GenTile.Copy(pillar), GenTile.Copy(pillar) }, { GenTile.Copy(pillar), GenTile.Copy(pillar) } }; GenTile Door = GenTile.GetEmpty(); Door.Details.Add(new GenDetail() { Char = '+', Type = GenDetail.DetailType.Door, Entity = GenDetail.EntityType.Door }); GenRoom outer = GenRoom.Sized(temple.Width, temple.Height); outer.FillFloor('+'); outer.SpacePriority = -2; temple.PlaceRoom(0, 0, outer); temple.EdgeWalls('#', outer); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- int w = Random.Range(9, 12); int h = Random.Range(10, 16); // EntryHall temple.TryGrowRect(1, outer.Outer.GetCenter().y, w, h, out GenRect EntrySize, false); GenRoom EntryHall = GenRoom.At(EntrySize.MinX, EntrySize.MinY, EntrySize.WidthT, EntrySize.HeightT); EntryHall.FillFloor('.'); temple.PlaceRoom(EntrySize.MinX, EntrySize.MinY, EntryHall); temple.EdgeWalls('#'); EntryHall.GetAtWorldspaceG( EntrySize.MinX + 1, EntrySize.GetCenter().y) .Details .Add(new GenDetail() { Char = '>', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.StairsDown }); int posX = EntrySize.MinX + 2; int posy = EntrySize.MinY + 2; GenTile[,] sym = GenUtil.GetSymetry(pillars.GetCopy(), ref posX, ref posy, EntryHall, GenUtil.Axis.Horizontal | GenUtil.Axis.Vertical); EntryHall.PlaceDetailsAt(posX, posy, sym); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // hall to big thing int whall = Random.Range(10, 25); int hhall = Random.Range(5, 7); int space = Random.Range(2, 4); temple.TryGrowRect(EntrySize.MaxX + 1, EntrySize.GetCenter().y, whall, hhall, out GenRect HallSize); GenRoom PillarHall = GenRoom.Sized(HallSize.WidthT, HallSize.HeightT); PillarHall.FillFloor('.'); PillarHall.SpacePriority = 3; temple.PlaceRoom(HallSize.MinX, HallSize.MinY, PillarHall); temple.EdgeWalls('#', PillarHall); NoAutoDoor.Add(PillarHall); // place doors to the entry if (hhall == 5) { // a single door in the middle PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 2, GenTile.Copy(Door)); } else { // place symetric doors PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 3, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 3, GenTile.Copy(Door)); } int currBar = HallSize.MinX + space; GenTile[,] singlePillar = new GenTile[, ] { { GenTile.Copy(pillar) } }; while (temple.IsInsideRoom(currBar, HallSize.MinY + 1, PillarHall)) { int fx = currBar; int fy = HallSize.MinY + 1; GenTile[,] feature = GenUtil.GetSymetry(singlePillar, ref fx, ref fy, PillarHall, GenUtil.Axis.Vertical); PillarHall.PlaceDetailsAt(fx, fy, feature); currBar += space; } temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // holy water or something int waterHeight = Random.Range(2, 4); int waterWidth = Random.Range(2, 4); int waterPillarWidth = Random.Range(2, 3); int waterRoomHeight = waterHeight + 4 + waterPillarWidth * 2; int waterRoomWidth = waterWidth + 6 + waterPillarWidth * 2; temple.TryGrowRect(HallSize.MaxX + 1, HallSize.GetCenter().y, waterRoomWidth, waterRoomHeight, out GenRect WaterSize, false, GenUtil.Direction4.Top); GenRoom waterRoom = GenRoom.Sized(WaterSize.WidthT, WaterSize.HeightT); waterRoom.FillFloor(); waterRoom.SpacePriority = 2; temple.PlaceRoom(WaterSize.MinX, WaterSize.MinY, waterRoom); temple.EdgeWalls('#', waterRoom); int BackDoorWater = Random.Range(1, waterRoom.Height / 2); waterRoom.AddDetails(WaterSize.MaxX, WaterSize.MinY + BackDoorWater, GenTile.Copy(Door)); waterRoom.AddDetails(WaterSize.MaxX, WaterSize.MaxY - BackDoorWater, GenTile.Copy(Door)); GenTile waterSingle = GenTile.GetEmpty(); waterSingle.Details.Add(new GenDetail() { Char = '~', Type = GenDetail.DetailType.Background }); GenTile[,] water = GenUtil.Fill(waterWidth, waterHeight, waterSingle); waterRoom.PlaceDetailsAt(WaterSize.MinX + 3 + waterPillarWidth, WaterSize.MinY + 2 + waterPillarWidth, water); int waterPX = WaterSize.MinX + 3; int waterPY = WaterSize.MinY + 2; GenTile[,] waterPillarPlace = GenUtil.GetSymetry(pillars.GetCopy(), ref waterPX, ref waterPY, waterRoom, GenUtil.Axis.Horizontal | GenUtil.Axis.Vertical); waterRoom.PlaceDetailsAt(waterPX, waterPY, waterPillarPlace); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // pillar spam int spamWidth = Random.Range(10, 20); int spamHeight = WaterSize.HeightT + Random.Range(8, 15); temple.TryGrowRect(WaterSize.MaxX + 1, WaterSize.GetCenter().y, spamWidth, spamHeight, out GenRect SpamSize, true, GenUtil.Direction4.Top); GenRoom Spam = GenRoom.Sized(SpamSize.WidthT, SpamSize.HeightT); Spam.FillFloor(); Spam.SpacePriority = 1; temple.PlaceRoom(SpamSize.MinX, SpamSize.MinY, Spam); temple.EdgeWalls('#', Spam); int spamPX = SpamSize.MinX + 2; int spamPY = SpamSize.MinY + 2; for (int x = spamPX; temple.IsInsideRoom(x, spamPY, Spam); x += 2) { for (int y = spamPY; temple.IsInsideRoom(x, y, Spam); y += 2) { GenTile p = GenTile.Copy(pillar); Spam.AddDetails(x, y, p); } } Spam.AddDetail( SpamSize.MaxX - 1, SpamSize.GetCenter().y, new GenDetail() { Char = '<', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.StairsUp }); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- //temple.Rooms.Remove(outer); // we dont have boundries for (int x = outer.Inner.MinX; x < outer.Outer.MaxX; x++) { for (int y = outer.Inner.MinY; y < outer.Outer.MaxY; y++) { outer.RemoveTileAtG(x, y); } } //GenRoom Mark = GenRoom.Sized(0, 0); //Mark.FillFloor('X'); //Mark.SpacePriority = 100; // lets go ham with randomly sized rooms int spawnAttemptsRemaining = 1000; while (spawnAttemptsRemaining-- > 0)// lol the arrow { int rWidth = Random.Range(RandomWidth.start, RandomWidth.end); int rHeight = Random.Range(RandomHeight.start, RandomHeight.end); int rX = Random.Range(2, temple.Width - 2); int rY = Random.Range(2, temple.Height - 2); GenRect rHopeSize = new GenRect(rX, rX + rWidth + 1, rY, rY + rWidth - 1); if (temple.IsInsideRoom(rX, rY) || temple.GetTile(rX, rY) != null) { continue; } temple.TryGrowRect(rX, rY, rWidth, rHeight, out GenRect rSize, true); GenRoom add = GenRoom.Sized(rSize.WidthT, rSize.HeightT); add.FillFloor(); add.SpacePriority = 01; temple.PlaceRoom(rSize.MinX, rSize.MinY, add); AutoFillRoom.Add(add); temple.EdgeWalls('#', add); temple.FixOverlap(); /* * if (rWidth * 2 < rHeight || rHeight * 2 < rWidth) * { * if (Random.Range(0,10)>4) * { * // we are making a hallway * * //TODO: hallway * * temple.PlaceRoom(rX, rY, Mark); * Log(temple); * if (Logging!=null) * { * yield return new WaitForSeconds(0.25f); * } * temple.Rooms.Remove(Mark); * continue; * } * } */ /* * int randomChance = Random.Range(0, 4); * switch (randomChance) * { * case 0: * // random pillars in the room * * for (int i = 0; i < 7 + (rSize.WidthT + rSize.HeightT)/5; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * add.AddDetails(px, py, pillar); * } * * break; * case 1: * // random water * for (int i = 0; i < 15 + (rSize.WidthT + rSize.HeightT)/3; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * GenDetail littleWater= new GenDetail() { Char = '~', Type = GenDetail.DetailType.Background}; * add.AddDetail(px, py, littleWater); * } * break; * case 2: * // random room inside if possible else empty * if (rSize.WidthT>=7&& rSize.HeightT >= 7) * { * int insideX = rSize.GetCenter().x; * int insideY = rSize.GetCenter().y; * * temple.TryGrowRect(insideX, insideY, 100, 100, out GenRect insideSize, false); * GenRoom inside = GenRoom.Sized(insideSize.WidthT, insideSize.HeightT); * inside.FillFloor(); * inside.SpacePriority = 2; * temple.PlaceRoom(insideSize.MinX, insideSize.MinY, inside); * temple.EdgeWalls('#',inside); * temple.FixOverlap(); * * } * else * { * for (int i = 0; i < 7; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * add.AddDetails(px, py, pillar); * } * } * break; * default: * break; * } * * Log(temple); * if (Logging!=null) * { * yield return new WaitForSeconds(0.25f); * } */ } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // now fill the rooms with things var adjList = temple.GetAdjacentRoomMap(); // remove any Room that is too small and have no connections List <GenRoom> tooSmall = new List <GenRoom>(); foreach (var room in temple.Rooms) { if (room.Width >= 5 && room.Height == 3) { tooSmall.Add(room); continue; } if (room.Height >= 5 && room.Width == 3) { tooSmall.Add(room); continue; } if (room.Height <= 3 && room.Width <= 3) { tooSmall.Add(room); continue; } if (adjList[room].Count == 0) { tooSmall.Add(room); continue; } } foreach (var room in tooSmall) { temple.Rooms.Remove(room); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- List <GenRoom> PotentialSecret = new List <GenRoom>(); foreach (var room in temple.Rooms) { if (room.Width + room.Height <= 12) { PotentialSecret.Add(room); } } Debug.Log("potential " + PotentialSecret.Count + "Secret rooms"); // 1 room --> 0,1,2,3 // 2 room --> 4,5 int SecretCount = Mathf.Min(Mathf.FloorToInt(Mathf.Sqrt(Random.Range(1, 6))), PotentialSecret.Count); // this goes to 5 Debug.Log(SecretCount + " Secret rooms chosen"); foreach (var secret in PotentialSecret.GetRandom(SecretCount)) { // we get random door // add a chest // remove it from door spawn GenPositionTile entry = temple.GetDoorableTiles(secret.GetAllTiles()).GetRandom(); secret.AddDetail(entry.PositionG.x, entry.PositionG.y, new GenDetail() { Char = '*', Entity = GenDetail.EntityType.Door, Type = GenDetail.DetailType.Door }); GenPositionTile myChest = secret .GetAllTiles() .Where(t => temple.IsInsideRoom(t.PositionG.x, t.PositionG.y, secret) && temple.IsCornerGR(t.PositionG.x, t.PositionG.y, secret)) .ToList() .GetRandom(); secret.AddDetails(myChest.PositionG.x, myChest.PositionG.y, GenTile.Copy(Chest)); AutoFillRoom.Remove(secret); SecretRooms.Add(secret); NoAutoDoor.Add(secret); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // go through all other rooms and determin what they are foreach (GenRoom room in AutoFillRoom) { // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // pillar hallway if (room.Height <= 7 && room.Height >= 5 && room.Width > 6) { // potential horizontal hallway if (Random.value < 0.4f) { // hallway confirmed // left to right GenTile[,] p = new GenTile[, ] { { GenTile.Copy(pillar) } }; int spacing = Random.Range(2, 5); int tmpX = room.Outer.MinX + spacing; int tmpY = room.Outer.MinY + 1; p = GenUtil.GetSymetry(p, ref tmpX, ref tmpY, room, GenUtil.Axis.Vertical); while (temple.IsInsideRoom(tmpX, tmpY, room)) { room.PlaceDetailsAt(tmpX, tmpY, p); tmpX = tmpX + spacing; } int enemyCount = Random.Range(0, 4); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-2, 2); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } continue; } } if (room.Width <= 7 && room.Width >= 5 && room.Height > 6) { // potential horizontal hallway if (Random.value < 0.4f) { // hallway confirmed // left to right GenTile[,] p = new GenTile[, ] { { GenTile.Copy(pillar) } }; int spacing = Random.Range(2, 5); int tmpX = room.Outer.MinX + 1; int tmpY = room.Outer.MinY + spacing; p = GenUtil.GetSymetry(p, ref tmpX, ref tmpY, room, GenUtil.Axis.Horizontal); while (temple.IsInsideRoom(tmpX, tmpY, room)) { room.PlaceDetailsAt(tmpX, tmpY, p); tmpY = tmpY + spacing; } int enemyCount = Random.Range(0, 4); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-2, 2); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } continue; } } if (room.Height >= 8 && room.Width >= 8) { // can either be pillar spam or room in room if (Random.value < 0.6f) { if (Random.value < 0.7f && room.Width % 2 == 1 && room.Height % 2 == 1) { // pillar spam for (int x = 2; x < room.Width - 2; x += 2) { for (int y = 2; y < room.Height - 2; y += 2) { room.AddDetails(room.PosX + x, room.PosY + y, GenTile.Copy(pillar)); } } int enemyCount = Random.Range(0, 5); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-3, 3); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } } else { // room in room // find where to put the inner room temple.TryGrowRect(room.Inner.GetCenter().x, room.Inner.GetCenter().y, 100, 100, out GenRect InnerSize); if (InnerSize.WidthT >= 4 && InnerSize.HeightT >= 4) { if (InnerSize.WidthT >= 10 || InnerSize.HeightT >= 10) { if (Mathf.Abs(InnerSize.WidthT - InnerSize.HeightT) > 3) { // we want to divide if (InnerSize.WidthT > InnerSize.HeightT) { // divide left and right int singleWidth = InnerSize.WidthT / 2 - 2; // left GenRect LeftRoom = new GenRect(InnerSize.MinX, InnerSize.MinX + singleWidth, InnerSize.MinY, InnerSize.MaxY); // right GenRect RightRoom = new GenRect(InnerSize.MaxX - singleWidth, InnerSize.MaxX, InnerSize.MinY, InnerSize.MaxY); GenRoom left = GenRoom.Sized(LeftRoom.WidthT, LeftRoom.HeightT); left.FillFloor(); left.SpacePriority = 4; GenRoom right = GenRoom.Sized(RightRoom.WidthT, RightRoom.HeightT); right.FillFloor(); right.SpacePriority = 4; temple.PlaceRoom(LeftRoom.MinX, LeftRoom.MinY, left); temple.PlaceRoom(RightRoom.MinX, RightRoom.MinY, right); NoAutoDoor.Add(left); NoAutoDoor.Add(right); temple.EdgeWalls('#', left); temple.EdgeWalls('#', right); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- var leftDoor = temple.GetDoorableTiles(left.GetAllTiles()).GetRandom(1); var rightDoor = temple.GetDoorableTiles(right.GetAllTiles()).GetRandom(1); for (int i = 0; i < leftDoor.Count; i++) { left.AddDetails(leftDoor[i].PositionG.x, leftDoor[i].PositionG.y, GenTile.Copy(Door)); } for (int i = 0; i < rightDoor.Count; i++) { right.AddDetails(rightDoor[i].PositionG.x, rightDoor[i].PositionG.y, GenTile.Copy(Door)); } SpawnItem(temple, left); SpawnItem(temple, right); if (Random.value < 0.4f) { SpawnItem(temple, right); } if (Random.value < 0.4f) { SpawnItem(temple, left); } if (Random.value < 0.2f) { SpawnChest(temple, left, true); } if (Random.value < 0.2f) { SpawnChest(temple, left, true); } } else { // divide top bot Debug.Log("currently not implemented, sorry"); } } } else { // one single room if (InnerSize.WidthT > 5) { InnerSize = InnerSize.Transform(-1, 0, -1, 0); } if (InnerSize.HeightT > 5) { InnerSize = InnerSize.Transform(0, -1, 0, -1); } Debug.Log("HERE"); GenRoom single = GenRoom.Sized(InnerSize.WidthT, InnerSize.HeightT); single.SpacePriority = 4; single.FillFloor(); NoAutoDoor.Add(single); temple.PlaceRoom(InnerSize.MinX, InnerSize.MinY, single); temple.EdgeWalls('#', single); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // double doors var doorables = single.GetAllTiles();// single.GetEdge().ToList(); var theDoors = temple.GetDoorableTiles(doorables).GetRandom(2); for (int i = 0; i < theDoors.Count; i++) { single.AddDetails(theDoors[i].PositionG.x, theDoors[i].PositionG.y, GenTile.Copy(Door)); } SpawnItem(temple, single); if (Random.value < 0.2f) { SpawnChest(temple, single, true); } if (Random.value < 0.2f) { SpawnChest(temple, single, true); } } } SpawnEnemy(temple, room); if (Random.value < 0.5f) { SpawnEnemy(temple, room); } if (Random.value < 0.2f) { SpawnEnemy(temple, room); } } continue; } } // something random //room.FillFloor('~'); SpawnEnemy(temple, room); SpawnEnemy(temple, room); if (Random.value < 0.5f) { SpawnEnemy(temple, room); } if (Random.value < 0.2f) { SpawnEnemy(temple, room); } SpawnItem(temple, room); if (Random.value < 0.3f) { SpawnItem(temple, room); } if (Random.value < 0.3f) { SpawnItem(temple, room); } if (Random.value < 0.4f) { SpawnChest(temple, room); } if (Random.value < 0.1f) { SpawnChest(temple, room); } } List <GenRoom> RequireDoor = new List <GenRoom>(temple.Rooms); foreach (var doo in NoAutoDoor) { RequireDoor.Remove(doo); } List <GenRoom> DoorIteration = new List <GenRoom>(RequireDoor); GenRoom start = EntryHall; Dictionary <GenRoom, List <GenRoom> > adj = temple.GetAdjacentRoomMap(); void RandomDoorTo(GenRoom a, GenRoom b) { var tiles = temple.GetDoorableTiles(temple.GetConnectingTiles(a, b)); var location = tiles.GetRandom(); a.AddDetails(location.PositionG.x, location.PositionG.y, GenTile.Copy(Door)); } while (RequireDoor.Count > 0) { DoorIteration.Clear(); DoorIteration.AddRange(RequireDoor); foreach (var room in DoorIteration) { if (temple.IsReachable(start, room)) { // reachable so we dont have to do a thing RequireDoor.Remove(room); } else { // place random door var available = adj[room]; RandomDoorTo(room, available.GetRandom()); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.1f)); } // ----------- } } foreach (var room in adj[Spam].GetRandom(2)) { RandomDoorTo(Spam, room); } Log(temple); Debug.Log("Done"); LastOutput = GenUtil.Print(temple, false); Done?.Invoke(); }
public bool IsEnclosing(GenRect other) { return(MinX < other.MinX && MinY < other.MinY && MaxX > other.MaxX && MaxY > other.MaxY); }
public bool IsInside(GenRect other) { return(other.MinX < MinX && other.MinY < MinY && other.MaxX > MaxX && other.MaxY > MaxY); }
public bool Overlaps(GenRect rect) { return(MinX <= rect.MaxX && MaxX >= rect.MinX && MinY <= rect.MaxY && MaxY >= rect.MinY); }
public static bool IsInOctant(GenRect rect, int gx, int gy, params Direction8[] dir) { //NOTE: does not check if in rect float tx = (rect.MinX + rect.MaxX) / 2f; float ty = (rect.MinY + rect.MaxY) / 2f; // to a range of -1 to 1 // relativ position float cx = gx - tx; float cy = gy - ty; cx = cx / (rect.WidthT / 2); cy = cy / (rect.WidthT / 2); // regular directions if (dir.Contains(Direction8.Top)) { if (cy <= 0 && Mathf.Abs(cx) <= Mathf.Abs(cy)) { return(true); } } if (dir.Contains(Direction8.Right)) { if (cx >= 0 && Mathf.Abs(cy) <= Mathf.Abs(cx)) { return(true); } } if (dir.Contains(Direction8.Bottom)) { if (cy >= 0 && Mathf.Abs(cx) <= Mathf.Abs(cy)) { return(true); } } if (dir.Contains(Direction8.Left)) { if (cx <= 0 && Mathf.Abs(cy) <= Mathf.Abs(cx)) { return(true); } } // quadrants if (dir.Contains(Direction8.TopLeft)) { if (cy <= 0 && cx <= 0) { return(true); } } if (dir.Contains(Direction8.TopRight)) { if (cy <= 0 && cx >= 0) { return(true); } } if (dir.Contains(Direction8.BottomRight)) { if (cy >= 0 && cx >= 0) { return(true); } } if (dir.Contains(Direction8.BottomLeft)) { if (cy >= 0 && cx <= 0) { return(true); } } return(false); }