public void SetupMap(double PerlinDiff, double Seed, double HeightBias, double Zoom) { map = new MapTile[width, height]; PerlinNoise p = new PerlinNoise(); //Generate tiles for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { //Map generation //Calculate perlin double mHeight = p.perlin(x * PerlinDiff, y * PerlinDiff, Seed); //Modify perlin value for more extremes mHeight = mHeight * Zoom - HeightBias; mHeight = mHeight < 0 ? 0 : mHeight; //Remove negative values mHeight = mHeight > 1 ? 1 : mHeight; //Remove values larger than 1 MapTileTypeEnum mapTileEnum = MapTileTypeEnum.land; if (mHeight < 0.2) { mapTileEnum = MapTileTypeEnum.deepWater; } else if (mHeight < 0.4) { mapTileEnum = MapTileTypeEnum.shallowWater; } else if (mHeight < 0.6) { mapTileEnum = MapTileTypeEnum.land; } else if (mHeight < 0.8) { mapTileEnum = MapTileTypeEnum.hill; } else if (mHeight <= 1.0) { mapTileEnum = MapTileTypeEnum.mountain; } map[x, y] = new MapTile(new Point(x, y), new MapTileType { type = mapTileEnum }, mHeight); } } //Add neighbours as they are now initialised for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { map[x, y].GetNeighbours(this); } } //Generate continents int counter = 0; Random colorGenerator = new Random(); continents = new List <Continent>(); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (map[x, y].continent == null) { Continent continent = new Continent(); map = continent.NewContinent(this, new Point(x, y), counter++.ToString(), colorGenerator).map; continents.Add(continent); } } } //Find largest land continent for road TODO: Do this for all continents of certain size int maxSize = 0; Continent maxContinent = new Continent(); foreach (Continent continent in continents) { if (continent.Type == MapTileTypeEnum.land && maxSize < continent.tiles.Count) { maxSize = continent.tiles.Count; maxContinent = continent; } } maxContinent.color = Color.Black; //TODO: For edges in continents find all the different zones, not only side //TODO: Create a road between each of the zones goals = new List <MapTile>(); while (true) { if (maxContinent.edges.top.Count != 0) { MapTile toAdd = maxContinent.edges.top[colorGenerator.Next(maxContinent.edges.top.Count)]; if (!goals.Contains(toAdd)) { goals.Add(toAdd); break; } } else { break; } } while (true) { if (maxContinent.edges.bottom.Count != 0) { MapTile toAdd = maxContinent.edges.bottom[colorGenerator.Next(maxContinent.edges.bottom.Count)]; if (!goals.Contains(toAdd)) { goals.Add(toAdd); break; } } else { break; } } while (true) { if (maxContinent.edges.left.Count != 0) { MapTile toAdd = maxContinent.edges.left[colorGenerator.Next(maxContinent.edges.left.Count)]; if (!goals.Contains(toAdd)) { goals.Add(toAdd); break; } } else { break; } } while (true) { if (maxContinent.edges.right.Count != 0) { MapTile toAdd = maxContinent.edges.right[colorGenerator.Next(maxContinent.edges.right.Count)]; if (!goals.Contains(toAdd)) { goals.Add(toAdd); break; } } else { break; } } //Skip code to create path when there are to few goals if (goals.Count <= 1) { return; } for (int x = 0; x <= map.GetUpperBound(0); x++) { for (int y = 0; y <= map.GetUpperBound(1); y++) { map[x, y].InitialiseDistances(goals.Count); map[x, y].GoalIDs = goals.ConvertAll(g => g.id).ToArray(); for (int i = 0; i < goals.Count; i++) { map[x, y].Costs[i] = -1; } } } CalculateCost(ref map); //Path creation List <MapTile> toDraw = new List <MapTile>(goals); int positionsLength = toDraw.Count; IEnumerable <IEnumerable <int> > rawPossibilites = GetPermutations(Enumerable.Range(0, positionsLength).ToList(), positionsLength); List <List <int> > possibilites = rawPossibilites.ToList().ConvertAll(i => i.ToList()); //Save shortest path double shortestLength = double.MaxValue; MapTile[] shortestGoals = new MapTile[positionsLength]; //Calculate the length of each path option foreach (IEnumerable <int> possibility in possibilites) { //Generate order MapTile[] order = new MapTile[positionsLength]; foreach (int index in possibility) { order[index] = toDraw[index]; } //Initialise variables for path finding //Copy map MapTile[,] localMap = new MapTile[map.GetUpperBound(0) + 1, map.GetUpperBound(1) + 1]; for (int x = 0; x <= map.GetUpperBound(0); x++) { for (int y = 0; y <= map.GetUpperBound(1); y++) { localMap[x, y] = (MapTile)map[x, y].Clone(); } } double length = 0; List <MapTile> localGoals = order.ToList(); localGoals.RemoveAt(0); //Calculate path length FindPath(order.ToList(), ref localMap, ref length, localGoals.ToArray()); //Check if shortest if (length < shortestLength) { shortestLength = length; shortestGoals = order; } } //Draw path pathLength = 0; //This is starting position toDraw.Remove(goals[0]); FindPath(shortestGoals.ToList(), ref map, ref pathLength, goals.ToArray()); //Clean up path //CleanPath(); }
public Map NewContinent(Map map, Point point, string ID, Random rng) { color = Color.FromArgb(100, rng.Next(255), rng.Next(255), rng.Next(255)); id = ID; MapTile activeTile = map.map[point.X, point.Y]; Type = activeTile.type.type; map.map[point.X, point.Y].isBeingChecked = true; toCheck = new List <MapTile>(); tiles = new List <MapTile>(); //Find tiles while (true) { //Add new tiles to continent List <MapTile> neighbours = activeTile.neighbours.GetSameType(Type); if (neighbours.Count != 0) { foreach (MapTile tile in neighbours) { map.map[tile.position.X, tile.position.Y].isBeingChecked = true; } toCheck.AddRange(neighbours); } tiles.Add(map.map[activeTile.position.X, activeTile.position.Y]); map.map[activeTile.position.X, activeTile.position.Y].continent = this; //Choose new tile if (toCheck.Count != 0) { activeTile = toCheck[0]; toCheck.RemoveAt(0); } //End else { break; } } //Find edges List <MapTile> top = new List <MapTile>(); List <MapTile> bottom = new List <MapTile>(); List <MapTile> left = new List <MapTile>(); List <MapTile> right = new List <MapTile>(); foreach (MapTile tile in tiles) { if (tile.position.X == 0) { left.Add(tile); } if (tile.position.X == map.map.GetUpperBound(0)) { right.Add(tile); } if (tile.position.Y == 0) { top.Add(tile); } if (tile.position.Y == map.map.GetUpperBound(1)) { bottom.Add(tile); } } edges = new EdgeArray(top.ToArray(), bottom.ToArray(), left.ToArray(), right.ToArray()); return(map); }