using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; using System.Text; using Voronoi2; namespace Subsurface { class Map { private List levels; private List locations; private List connections; private int seed; private int size; private Texture2D iceTexture; private Texture2D iceCraters; private Texture2D iceCrack; private Location currentLocation; private Location selectedLocation; public Map(int seed, int size) { this.seed = seed; this.size = size; levels = new List(); locations = new List(); connections = new List(); iceTexture = Game1.textureLoader.FromFile("Content/Map/iceSurface.png"); iceCraters = Game1.textureLoader.FromFile("Content/Map/iceCraters.png"); iceCrack = Game1.textureLoader.FromFile("Content/Map/iceCrack.png"); GenerateLocations(); currentLocation = locations[locations.Count/2]; } private void GenerateLocations() { Voronoi voronoi = new Voronoi(0.5f); List sites = new List(); for (int i = 0; i < 50; i++) { sites.Add(new Vector2(Rand.Range(0.0f, size), Rand.Range(0.0f, size))); } List 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); 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]); } connections.Add(new LocationConnection(newLocations[0], newLocations[1], Level.CreateRandom())); } 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 (connection == connection2) continue; 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]; } } for (int i = connections.Count - 1; i >= 0; i--) { LocationConnection connection = connections[i]; for (int n = i-1; n >= 0; n--) { if (connection.Locations.Contains(connections[n].Locations[0]) && connection.Locations.Contains(connections[n].Locations[1])) { connections.RemoveAt(i); } } } 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 = GenerateCrack(start, end, generations); } } private List GenerateCrack(Vector2 start, Vector2 end, int generations) { List segments = new List(); segments.Add(new Vector2[] {start, end}); float offsetAmount = 5.0f; for (int n = 0; n CrackSegments; public Location[] Locations { get { return locations; } } public Level Level { get { return level; } } public LocationConnection(Location location1, Location location2, Level level) { locations = new Location[] { location1, location2 }; this.level = level; } } }