private void CreateDummyLocations() { dummyLocations = new Location[2]; string seed = ""; if (GameMain.GameSession != null && GameMain.GameSession.Level != null) { seed = GameMain.GameSession.Level.Seed; } else if (GameMain.NetLobbyScreen != null) { seed = GameMain.NetLobbyScreen.LevelSeed; } MTRandom rand = new MTRandom(ToolBox.StringToInt(seed)); for (int i = 0; i < 2; i++) { dummyLocations[i] = Location.CreateRandom(new Vector2((float)rand.NextDouble() * 10000.0f, (float)rand.NextDouble() * 10000.0f)); } }
private void Generate() { connections.Clear(); Locations.Clear(); GenerateNoiseMap(generationParams.NoiseOctaves, generationParams.NoisePersistence); List <Vector2> sites = new List <Vector2>(); float mapRadius = size / 2; Vector2 mapCenter = new Vector2(mapRadius, mapRadius); float locationRadius = mapRadius * generationParams.LocationRadius; for (float x = mapCenter.X - locationRadius; x < mapCenter.X + locationRadius; x += generationParams.VoronoiSiteInterval) { for (float y = mapCenter.Y - locationRadius; y < mapCenter.Y + locationRadius; y += generationParams.VoronoiSiteInterval) { float noiseVal = Noise[(int)(x / size * generationParams.NoiseResolution), (int)(y / size * generationParams.NoiseResolution)]; if (Rand.Range(generationParams.VoronoiSitePlacementMinVal, 1.0f, Rand.RandSync.Server) < noiseVal * generationParams.VoronoiSitePlacementProbability) { sites.Add(new Vector2(x, y)); } } } Voronoi voronoi = new Voronoi(0.5f); List <GraphEdge> edges = voronoi.MakeVoronoiGraph(sites, size, size); float zoneRadius = size / 2 / generationParams.DifficultyZones; sites.Clear(); foreach (GraphEdge edge in edges) { if (edge.Point1 == edge.Point2) { continue; } if (Vector2.DistanceSquared(edge.Point1, mapCenter) >= locationRadius * locationRadius || Vector2.DistanceSquared(edge.Point2, mapCenter) >= locationRadius * locationRadius) { continue; } Location[] newLocations = new Location[2]; newLocations[0] = Locations.Find(l => l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2); newLocations[1] = Locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2)); for (int i = 0; i < 2; i++) { if (newLocations[i] != null) { continue; } Vector2[] points = new Vector2[] { edge.Point1, edge.Point2 }; int positionIndex = Rand.Int(1, Rand.RandSync.Server); Vector2 position = points[positionIndex]; if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) { position = points[1 - positionIndex]; } int zone = MathHelper.Clamp(generationParams.DifficultyZones - (int)Math.Floor(Vector2.Distance(position, mapCenter) / zoneRadius), 1, generationParams.DifficultyZones); newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.Server)); Locations.Add(newLocations[i]); } var newConnection = new LocationConnection(newLocations[0], newLocations[1]); float centerDist = Vector2.Distance(newConnection.CenterPos, mapCenter); newConnection.Difficulty = MathHelper.Clamp(((1.0f - centerDist / mapRadius) * 100) + Rand.Range(-10.0f, 10.0f, Rand.RandSync.Server), 0, 100); connections.Add(newConnection); } //remove connections that are too short float minConnectionDistanceSqr = generationParams.MinConnectionDistance * generationParams.MinConnectionDistance; for (int i = connections.Count - 1; i >= 0; i--) { LocationConnection connection = connections[i]; if (Vector2.DistanceSquared(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minConnectionDistanceSqr) { continue; } //locations.Remove(connection.Locations[0]); connections.Remove(connection); foreach (LocationConnection connection2 in connections) { if (connection2.Locations[0] == connection.Locations[0]) { connection2.Locations[0] = connection.Locations[1]; } if (connection2.Locations[1] == connection.Locations[0]) { connection2.Locations[1] = connection.Locations[1]; } } } HashSet <Location> connectedLocations = new HashSet <Location>(); foreach (LocationConnection connection in connections) { connection.Locations[0].Connections.Add(connection); connection.Locations[1].Connections.Add(connection); connectedLocations.Add(connection.Locations[0]); connectedLocations.Add(connection.Locations[1]); } //remove orphans Locations.RemoveAll(c => !connectedLocations.Contains(c)); //remove locations that are too close to each other float minLocationDistanceSqr = generationParams.MinLocationDistance * generationParams.MinLocationDistance; for (int i = Locations.Count - 1; i >= 0; i--) { for (int j = Locations.Count - 1; j > i; j--) { float dist = Vector2.DistanceSquared(Locations[i].MapPosition, Locations[j].MapPosition); if (dist > minLocationDistanceSqr) { continue; } //move connections from Locations[j] to Locations[i] foreach (LocationConnection connection in Locations[j].Connections) { if (connection.Locations[0] == Locations[j]) { connection.Locations[0] = Locations[i]; } else { connection.Locations[1] = Locations[i]; } Locations[i].Connections.Add(connection); } Locations.RemoveAt(j); } } for (int i = connections.Count - 1; i >= 0; i--) { i = Math.Min(i, connections.Count - 1); LocationConnection connection = connections[i]; for (int n = Math.Min(i - 1, connections.Count - 1); n >= 0; n--) { if (connection.Locations.Contains(connections[n].Locations[0]) && connection.Locations.Contains(connections[n].Locations[1])) { connections.RemoveAt(n); } } } foreach (LocationConnection connection in connections) { float centerDist = Vector2.Distance(connection.CenterPos, mapCenter); connection.Difficulty = MathHelper.Clamp(((1.0f - centerDist / mapRadius) * 100) + Rand.Range(-10.0f, 10.0f, Rand.RandSync.Server), 0, 100); } AssignBiomes(); GenerateNoiseMapProjSpecific(); }
private void GenerateLocations() { Voronoi voronoi = new Voronoi(0.5f); List <Vector2> sites = new List <Vector2>(); for (int i = 0; i < 100; i++) { sites.Add(new Vector2(Rand.Range(0.0f, size, Rand.RandSync.Server), Rand.Range(0.0f, size, Rand.RandSync.Server))); } List <GraphEdge> edges = voronoi.MakeVoronoiGraph(sites, size, size); sites.Clear(); foreach (GraphEdge edge in edges) { if (edge.point1 == edge.point2) { continue; } //remove points from the edge of the map if (edge.point1.X == 0 || edge.point1.X == size) { continue; } if (edge.point1.Y == 0 || edge.point1.Y == size) { continue; } if (edge.point2.X == 0 || edge.point2.X == size) { continue; } if (edge.point2.Y == 0 || edge.point2.Y == size) { continue; } Location[] newLocations = new Location[2]; newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2); newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2)); for (int i = 0; i < 2; i++) { if (newLocations[i] != null) { continue; } Vector2[] points = new Vector2[] { edge.point1, edge.point2 }; int positionIndex = Rand.Int(1, Rand.RandSync.Server); Vector2 position = points[positionIndex]; if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) { position = points[1 - positionIndex]; } newLocations[i] = Location.CreateRandom(position); locations.Add(newLocations[i]); } //int seed = (newLocations[0].GetHashCode() | newLocations[1].GetHashCode()); connections.Add(new LocationConnection(newLocations[0], newLocations[1])); } //remove connections that are too short float minDistance = 50.0f; for (int i = connections.Count - 1; i >= 0; i--) { LocationConnection connection = connections[i]; if (Vector2.Distance(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minDistance) { continue; } locations.Remove(connection.Locations[0]); connections.Remove(connection); foreach (LocationConnection connection2 in connections) { if (connection2.Locations[0] == connection.Locations[0]) { connection2.Locations[0] = connection.Locations[1]; } if (connection2.Locations[1] == connection.Locations[0]) { connection2.Locations[1] = connection.Locations[1]; } } } foreach (LocationConnection connection in connections) { connection.Locations[0].Connections.Add(connection); connection.Locations[1].Connections.Add(connection); } for (int i = connections.Count - 1; i >= 0; i--) { i = Math.Min(i, connections.Count - 1); LocationConnection connection = connections[i]; for (int n = Math.Min(i - 1, connections.Count - 1); n >= 0; n--) { if (connection.Locations.Contains(connections[n].Locations[0]) && connection.Locations.Contains(connections[n].Locations[1])) { connections.RemoveAt(n); } } } foreach (LocationConnection connection in connections) { Vector2 start = connection.Locations[0].MapPosition; Vector2 end = connection.Locations[1].MapPosition; int generations = (int)(Math.Sqrt(Vector2.Distance(start, end) / 10.0f)); connection.CrackSegments = MathUtils.GenerateJaggedLine(start, end, generations, 5.0f); } AssignBiomes(); }
private void Generate() { Connections.Clear(); Locations.Clear(); List <Vector2> voronoiSites = new List <Vector2>(); for (float x = 10.0f; x < Width - 10.0f; x += generationParams.VoronoiSiteInterval.X) { for (float y = 10.0f; y < Height - 10.0f; y += generationParams.VoronoiSiteInterval.Y) { voronoiSites.Add(new Vector2( x + generationParams.VoronoiSiteVariance.X * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server), y + generationParams.VoronoiSiteVariance.Y * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server))); } } Voronoi voronoi = new Voronoi(0.5f); List <GraphEdge> edges = voronoi.MakeVoronoiGraph(voronoiSites, Width, Height); float zoneWidth = Width / generationParams.DifficultyZones; Vector2 margin = new Vector2( Math.Min(10, Width * 0.1f), Math.Min(10, Height * 0.2f)); float startX = margin.X, endX = Width - margin.X; float startY = margin.Y, endY = Height - margin.Y; if (!edges.Any()) { throw new Exception($"Generating a campaign map failed (no edges in the voronoi graph). Width: {Width}, height: {Height}, margin: {margin}"); } voronoiSites.Clear(); foreach (GraphEdge edge in edges) { if (edge.Point1 == edge.Point2) { continue; } if (edge.Point1.X < margin.X || edge.Point1.X > Width - margin.X || edge.Point1.Y < startY || edge.Point1.Y > endY) { continue; } if (edge.Point2.X < margin.X || edge.Point2.X > Width - margin.X || edge.Point2.Y < startY || edge.Point2.Y > endY) { continue; } Location[] newLocations = new Location[2]; newLocations[0] = Locations.Find(l => l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2); newLocations[1] = Locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.Point1 || l.MapPosition == edge.Point2)); for (int i = 0; i < 2; i++) { if (newLocations[i] != null) { continue; } Vector2[] points = new Vector2[] { edge.Point1, edge.Point2 }; int positionIndex = Rand.Int(1, Rand.RandSync.Server); Vector2 position = points[positionIndex]; if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) { position = points[1 - positionIndex]; } int zone = MathHelper.Clamp((int)Math.Floor(position.X / zoneWidth) + 1, 1, generationParams.DifficultyZones); newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.Server), requireOutpost: false, Locations); Locations.Add(newLocations[i]); } var newConnection = new LocationConnection(newLocations[0], newLocations[1]); Connections.Add(newConnection); } //remove connections that are too short float minConnectionDistanceSqr = generationParams.MinConnectionDistance * generationParams.MinConnectionDistance; for (int i = Connections.Count - 1; i >= 0; i--) { LocationConnection connection = Connections[i]; if (Vector2.DistanceSquared(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minConnectionDistanceSqr) { continue; } //locations.Remove(connection.Locations[0]); Connections.Remove(connection); foreach (LocationConnection connection2 in Connections) { if (connection2.Locations[0] == connection.Locations[0]) { connection2.Locations[0] = connection.Locations[1]; } if (connection2.Locations[1] == connection.Locations[0]) { connection2.Locations[1] = connection.Locations[1]; } } } HashSet <Location> connectedLocations = new HashSet <Location>(); foreach (LocationConnection connection in Connections) { connection.Locations[0].Connections.Add(connection); connection.Locations[1].Connections.Add(connection); connectedLocations.Add(connection.Locations[0]); connectedLocations.Add(connection.Locations[1]); } //remove orphans Locations.RemoveAll(c => !connectedLocations.Contains(c)); //remove locations that are too close to each other float minLocationDistanceSqr = generationParams.MinLocationDistance * generationParams.MinLocationDistance; for (int i = Locations.Count - 1; i >= 0; i--) { for (int j = Locations.Count - 1; j > i; j--) { float dist = Vector2.DistanceSquared(Locations[i].MapPosition, Locations[j].MapPosition); if (dist > minLocationDistanceSqr) { continue; } //move connections from Locations[j] to Locations[i] foreach (LocationConnection connection in Locations[j].Connections) { if (connection.Locations[0] == Locations[j]) { connection.Locations[0] = Locations[i]; } else { connection.Locations[1] = Locations[i]; } if (connection.Locations[0] != connection.Locations[1]) { Locations[i].Connections.Add(connection); } else { Connections.Remove(connection); } } Locations[i].Connections.RemoveAll(c => c.OtherLocation(Locations[i]) == Locations[j]); Locations.RemoveAt(j); } } for (int i = Connections.Count - 1; i >= 0; i--) { i = Math.Min(i, Connections.Count - 1); LocationConnection connection = Connections[i]; for (int n = Math.Min(i - 1, Connections.Count - 1); n >= 0; n--) { if (connection.Locations.Contains(Connections[n].Locations[0]) && connection.Locations.Contains(Connections[n].Locations[1])) { Connections.RemoveAt(n); } } } foreach (Location location in Locations) { for (int i = location.Connections.Count - 1; i >= 0; i--) { if (!Connections.Contains(location.Connections[i])) { location.Connections.RemoveAt(i); } } } foreach (LocationConnection connection in Connections) { connection.Difficulty = MathHelper.Clamp((connection.CenterPos.X / Width * 100) + Rand.Range(-10.0f, 0.0f, Rand.RandSync.Server), 1.2f, 100.0f); } AssignBiomes(); CreateEndLocation(); foreach (Location location in Locations) { location.LevelData = new LevelData(location); } foreach (LocationConnection connection in Connections) { connection.LevelData = new LevelData(connection); } }
private void GenerateConnections() { foreach (GraphEdge edge in graphEdges) { if (edge.point1 == edge.point2 || edge.isInternal) { continue; } Location[] newLocations = new Location[2]; newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2); newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2)); for (int i = 0; i < 2; i++) { if (newLocations[i] != null) { continue; } Vector2[] points = new Vector2[] { edge.point1, edge.point2 }; int positionIndex = Rand.Int(1, false); Vector2 position = points[positionIndex]; if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) { position = points[1 - positionIndex]; } newLocations[i] = Location.CreateRandom(position); // DEBUG //newLocations[i].Discovered = true; locations.Add(newLocations[i]); } LocationConnection newConnection = ConnectLocations(newLocations[0], newLocations[1]); newConnection.primaryNodes[0] = edge.node1; newConnection.primaryNodes[1] = edge.node2; newConnection.secondaryNodes = edge.secondaryNodes.ToArray(); /*if (!edge.isInternal && edge.node1 != null && edge.node2 != null && edge.cell1 != null && edge.cell2 != null) * { * Location newLocation1; * Location newLocation2; * * newLocation1 = Location.CreateRandom(edge.node1.mapPosition); * newLocation2 = Location.CreateRandom(edge.node2.mapPosition); * * if (!locations.Any(l => l.MapPosition == edge.node1.mapPosition)) * locations.Add(newLocation1); * else * newLocation2 = locations.Find(l => l.MapPosition == edge.node1.mapPosition); * if (!locations.Any(l => l.MapPosition == edge.node2.mapPosition)) * locations.Add(newLocation2); * else * newLocation2 = locations.Find(l => l.MapPosition == edge.node2.mapPosition); * * ConnectLocations(newLocation1, newLocation2); * }*/ } foreach (SecondaryNode node in secondaryNodes) { if (!node.isOnEdge) { Location nodeLocation = Location.CreateRandom(node.mapPosition); locations.Add(nodeLocation); foreach (SecondaryNode subNode in node.attachedNodes) { LocationConnection newConnection = ConnectLocations(nodeLocation, Location.CreateRandom(subNode.mapPosition)); subNode.connections.Add(newConnection); } } } }