public static void Normalize(int min, int max) { Console.WriteLine("Normalizing..."); Console.WriteLine("Before - Max is: " + Map.max() + ", min is: " + Map.min()); Map = Map.normalize(min, max); Console.WriteLine("After - Max is: " + Map.max() + ", min is: " + Map.min()); }
//from here: http://terraineer.sourceforge.net/plugins/hills.php public static Heightmap Hills(Heightmap seed, int numHills, double Steepness = 1, double ValleyProb = 0, int MaxRadius = 25, bool ellipse = false, HashSet<Point> holds = null, Random Random = null) { Map = new Heightmap(seed.Map, holds??new HashSet<Point>()); Random rand = Random??new Random(); for (int c = 0; c < numHills; c++) { Hill(Steepness, ValleyProb, MaxRadius, ellipse, rand); } return Map; }
//From here: http://terraineer.sourceforge.net/plugins/fault.php public static Heightmap Faults(Heightmap seed, int numFaults, int Displacement = 2, HashSet<Point> holds = null, Random random = null) { Map = new Heightmap(seed.Map, holds ?? new HashSet<Point>()); Random rand = random ?? new Random(); for (int f = 0; f < numFaults; f++) { Fault(Displacement, rand); } return Map; }
/// <summary> /// Generates a heightmap using the diamond-square method explained here: http://www.gameprogrammer.com/fractal.html /// For any given input size, it returns a square heightmap of dimension 2^size + 1 /// </summary> /// <param name="ReqSize">The size of the resultant heightmap; it will be 2^size+1</param> /// <param name="variability">The initial variability in height</param> /// <param name="seed">The seeded values</param> /// <param name="roughness">How quickly the variability drops off; should be less than one</param> /// <param name="holds">Set of points whose seeded value should be maintained</param> /// <returns></returns> public static Heightmap DiamondSquare(int ReqSize, int variability, double roughness, Heightmap seed = null, HashSet<Point> holds = null, Random Random = null) { int size = (1 << ReqSize); List<List<int>> map = (seed ?? new Heightmap(size)).Map; for (int i = 0; i < size; i++) { if (map.Count <= i) { map.Add(new List<int>(size)); } if (map[i].Count < size) { for (int j = 0; j < size; j++) { map[i].Add(0); } } } if(seed == null) { //A default seeding - mountains in the "middle" (actually corners, but whatever). map[0][0] = 1000; map[0][size-1] = 1000; map[size-1][0] = 1000; map[size-1][size-1] = 1000; } int step = size/2; Map = new Heightmap(map); Holds = holds ?? new HashSet<Point>(); vstep = roughness; rand = Random??new Random(); DiamondSquare_Recursive(step, variability, size/2, size/2); return Map; }
public static List<List<Heightmap>> ChopHeightmap(int SquareSize, Heightmap input) { List<List<Heightmap>> ret = new List<List<Heightmap>>(); List<List<int>> rawmap = input.Map; IEnumerable<List<int>> RestColumns; IEnumerable<IEnumerable<int>> RestRows; RestColumns = rawmap; int count = 0; do { IEnumerable<List<int>> CurrentColumns = RestColumns.Take(SquareSize); RestColumns = RestColumns.Skip(SquareSize); ret.Add(new List<Heightmap>()); RestRows = CurrentColumns; do { IEnumerable<IEnumerable<int>> CurrentRows = RestRows.Select((x) => x.Take(SquareSize)); RestRows = RestRows.Select((x) => x.Skip(SquareSize)); List<List<int>> CurrentMap = CurrentRows.Select((x) => x.ToList()).ToList(); ret[count].Add(new Heightmap(CurrentMap)); } while (RestRows.Max((x)=>x.Count()) > 0); count++; } while (RestColumns.Count() > 0); return ret; }
//Executes various different heightmap forming functions at random public static Heightmap Arbitrary(Heightmap seed, SortedList<double, Action> functions, int iterations = 10000, Random random = null, Func<int, bool> StepCallback = null) { Map = seed; Random rand = random ?? new Random(); //Want to make sure that they're sorted in descending order and normalized. double total = functions.Aggregate<KeyValuePair<double, Action>, double>(0, (current, next) => current + next.Key); var actionsSorted = (from kvp in functions select new {Key = kvp.Key/total, Value = kvp.Value}).OrderBy((x)=>x.Key); List<int> actionsDone = new List<int>(functions.Count); for (int i = 0; i < functions.Count; i++) { actionsDone.Add(0); } for (int i = 0; i < iterations; i++) { //try to "roll under" the key value; we perform the first action whose key + cumulative value is higher than this value. double randomValue = rand.NextDouble(); double cumulativeValue = 0; for(int j = 0; j < actionsSorted.Count(); j++) { var kvp = actionsSorted.ElementAt(j); cumulativeValue += kvp.Key; if (randomValue < cumulativeValue) { actionsDone[j]++; kvp.Value(); break; } } if (StepCallback != null) { bool Continue = StepCallback(i); if (!Continue) break; } } return Map; }