public void Generate() { int minRoomSize = 50; rooms = new HashSet <GenRoom>(); for (int i = 0; i < 7 + ( int )(UnityEngine.Random.value * 4); i++) { GenRoom room = new GenRoom(); room.bounds.width = ((15 + ( int )(UnityEngine.Random.value * 20)) / 2) * 2; room.bounds.height = ((15 + ( int )(UnityEngine.Random.value * 20)) / 2) * 2; rooms.Add(room); } while (true) { bool changed = false; foreach (GenRoom r1 in rooms) { foreach (GenRoom r2 in rooms) { if (r1 == r2) { continue; } Vector2Int p1 = new Vector2Int(r1.bounds.x + r1.bounds.width / 2, r1.bounds.y + r1.bounds.height / 2); Vector2Int p2 = new Vector2Int(r2.bounds.x + r2.bounds.width / 2, r2.bounds.y + r2.bounds.height / 2); if (Math.Pow(Vector2Int.Distance(p1, p2), 2) < 2 * minRoomSize * minRoomSize + 2) { r2.bounds.x += ( int )((UnityEngine.Random.value - 0.5) * 5); r2.bounds.y += ( int )((UnityEngine.Random.value - 0.5) * 2.5); changed = true; break; } } if (changed) { break; } } if (!changed) { break; } } HashSet <GenVertex> Q = new HashSet <GenVertex>(); foreach (GenRoom r in rooms) { Q.Add(new GenVertex(r)); } GenVertex root = null; foreach (GenVertex v in Q) { if (root == null || v.r.bounds.x < root.r.bounds.x) { root = v; } } root.value = 0; HashSet <GenEdge> E = new HashSet <GenEdge>(); HashSet <GenEdge> G = new HashSet <GenEdge>(); HashSet <GenVertex> F = new HashSet <GenVertex>(); foreach (GenVertex r1 in Q) { foreach (GenVertex r2 in Q) { if (r1 == r2) { goto outer; } foreach (GenEdge e in E) { if (e.r2 == r1 && e.r1 == r2) { goto outer; } } E.Add(new GenEdge(r1, r2)); } outer :; } F.Add(root); Q.Remove(root); while (Q.Count > 0) { GenEdge start2 = null; foreach (GenEdge e in E) { if (F.Contains(e.r1) ^ F.Contains(e.r2)) { if (start2 == null || e.dist < start2.dist) { start2 = e; } } } Q.Remove(start2.r2); Q.Remove(start2.r1); F.Add(start2.r2); F.Add(start2.r1); E.Remove(start2); G.Add(start2); if (start2.r1.value < start2.r2.value) { start2.r2.value = ( float )(start2.r1.value + start2.dist); } else { start2.r1.value = ( float )(start2.r2.value + start2.dist); } } // G list of edges // rooms list of rooms HashSet <GenRoom> rooms2 = new HashSet <GenRoom>(); foreach (GenEdge ed in G) { // horizontal float diff1 = ed.r1.r.bounds.y - ed.r2.r.bounds.y - ed.r2.r.bounds.height + TUNNEL_THICKNESS; float diff2 = ed.r2.r.bounds.y - ed.r1.r.bounds.y - ed.r1.r.bounds.height + TUNNEL_THICKNESS; // vertical float diff3 = ed.r1.r.bounds.x - ed.r2.r.bounds.x - ed.r2.r.bounds.width + TUNNEL_THICKNESS; float diff4 = ed.r2.r.bounds.x - ed.r1.r.bounds.x - ed.r1.r.bounds.width + TUNNEL_THICKNESS; if (diff1 < 0 && diff2 < 0) { AddStraightHorizontal(rooms2, ed); } else if (diff3 < 0 && diff4 < 0) { AddStraightVertical(rooms2, ed); } else { AddCurve(rooms2, ed); } } HashSet <Vector2Int> allDoors = new HashSet <Vector2Int>(); foreach (GenRoom r in rooms) { for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { int xMode = (x1 == r.bounds.x) ? -1 : (x1 == r.bounds.x + r.bounds.width - 1) ? 1 : 0; int yMode = (y1 == r.bounds.y) ? -1 : (y1 == r.bounds.y + r.bounds.height - 1) ? 1 : 0; r.tiles.Add(new Vector2Int(x1, y1), new GenTile(Room.TileType.WALL, GenTile.GetPosition(xMode, yMode))); } } for (int x1 = r.bounds.x + 1; x1 < r.bounds.x + r.bounds.width - 1; x1++) { for (int y1 = r.bounds.y + 1; y1 < r.bounds.y + r.bounds.height - 1; y1++) { r.tiles[new Vector2Int(x1, y1)].type = Room.TileType.GROUND; } } allDoors.UnionWith(r.AllDoors()); foreach (Vector2Int v in r.doorsDown) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.BOTTOM; } foreach (Vector2Int v in r.doorsUp) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.TOP; } foreach (Vector2Int v in r.doorsLeft) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.LEFT; } foreach (Vector2Int v in r.doorsRight) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.RIGHT; } } path = new GenRoom(); foreach (GenRoom r in rooms2) { for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { Vector2Int pos1 = new Vector2Int(x1, y1); if (path.tiles.ContainsKey(pos1)) { path.tiles[pos1].type = Room.TileType.GROUND; } else { path.tiles.Add(pos1, new GenTile(Room.TileType.GROUND)); } Vector2Int pos2 = new Vector2Int(x1 + 1, y1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.LEFT)); } pos2 = new Vector2Int(x1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP)); } pos2 = new Vector2Int(x1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM)); } } } for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { Vector2Int pos2 = new Vector2Int(x1 + 1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP_RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP_LEFT)); } pos2 = new Vector2Int(x1 + 1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM_RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM_LEFT)); } } } if (r.AllDoors().Count > 0) { throw new NotSupportedException("Paths should not have any doors"); } } start = root.r; end = null; foreach (GenRoom r in rooms) { if (end == null || r.bounds.x > end.bounds.x) { end = r; } } rooms.Remove(start); rooms.Remove(end); foreach (GenRoom r in rooms) { GenerateInterior(r); } start.spawnpoints.Add(start.GetCenter()); end.spawnpoints.Add(end.GetCenter()); foreach (Vector2Int v in allDoors) { foreach (GenRoom r in rooms) { for (int x = -TUNNEL_THICKNESS; x < TUNNEL_THICKNESS; x++) { for (int y = -TUNNEL_THICKNESS; y < TUNNEL_THICKNESS; y++) { if (r.tiles.ContainsKey(v + new Vector2Int(x, y)) && r.tiles[v + new Vector2Int(x, y)].type == Room.TileType.ROCK) { r.tiles[v + new Vector2Int(x, y)].type = Room.TileType.GROUND; } } } } { GenRoom r = path; if (r.tiles.ContainsKey(v + new Vector2Int(0, 1)) && r.tiles[v + new Vector2Int(0, 1)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(0, 1)); } if (r.tiles.ContainsKey(v + new Vector2Int(0, -1)) && r.tiles[v + new Vector2Int(0, -1)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(0, -1)); } if (r.tiles.ContainsKey(v + new Vector2Int(1, 0)) && r.tiles[v + new Vector2Int(1, 0)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(1, 0)); } if (r.tiles.ContainsKey(v + new Vector2Int(-1, 0)) && r.tiles[v + new Vector2Int(-1, 0)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(-1, 0)); } } } foreach (GenRoom r in rooms) { MakeRoomRelative(r); } MakeRoomRelative(start); MakeRoomRelative(end); MakeRoomRelative(path); }
public GenEdge(GenVertex r1, GenVertex r2) { this.r1 = r1; this.r2 = r2; dist = r1.r.Distance(r2.r); }