Exemple #1
0
 private void CollectRiver(Corner c, RiverBranch riverBranch)
 {
     foreach (var edge in c.Edges)
     {
         if (edge.WaterFlow > 1)
         {
             if (!_rivers.Contains(edge))
             {
                 var newBranch = new RiverBranch {
                     Edge = edge, ParentBranch = riverBranch
                 };
                 riverBranch.Branches.Add(newBranch);
                 _rivers.Add(edge);
                 CollectRiver(edge.GetOpposite(c), newBranch);
             }
         }
     }
 }
Exemple #2
0
        private int FillRiver(RiverBranch branch)
        {
            int flood;

            if (branch.Final)
            {
                flood = 1;
            }
            else
            {
                flood = branch.Branches.Sum(b => FillRiver(b)) + 1;
            }
            if (branch.Edge != null)
            {
                branch.Edge.WaterFlow = flood;
            }
            return(flood);
        }
Exemple #3
0
 private void EnumerateTree(RiverBranch branch, Action <RiverBranch> action)
 {
     action(branch);
     branch.Branches.ForEach(b => EnumerateTree(b, action));
 }
Exemple #4
0
        /// <summary>
        /// Starts plan generation process
        /// </summary>
        public void Generate()
        {
            var datapoints = new List <Vector>(Parameters.PolygonsCount);

            var r = new Random(Parameters.GridSeed);

            for (int i = 0; i < Parameters.PolygonsCount; i++)
            {
                datapoints.Add(new Vector(r.Next(0, Parameters.MapSize.X), r.Next(0, Parameters.MapSize.Y)));
            }

            var graph = Fortune.ComputeVoronoiGraph(datapoints);

            for (int i = 0; i < Parameters.RelaxCount; i++)
            {
                Relax(graph, datapoints);
                graph = Fortune.ComputeVoronoiGraph(datapoints);
            }

            FillMap(graph);

            {
                // adding elevation data

                var elevationNoise = new SimplexNoise(new Random(Parameters.ElevationSeed));
                elevationNoise.SetParameters(0.0008, SimplexNoise.InflectionMode.NoInflections, SimplexNoise.ResultScale.ZeroToOne);

                foreach (var poly in this)
                {
                    var noiseVal = elevationNoise.GetNoise2DValue(poly.Center.X, poly.Center.Y, 4, 0.8);
                    var col      = 255 / noiseVal.MaxValue * noiseVal.Value;
                    poly.Elevation = (int)col;
                }

                //// elevate each corner
                //if (!Parameters.CenterElevation)
                //    ElevateCorners();
            }

            if (Parameters.CenterElevation)
            {
                var poly = GetAtPoint(new Point(Parameters.MapSize.X / 2, Parameters.MapSize.Y / 2));
                poly.Elevation = 200;
                StartPropagation(poly, 15);
            }

            // making island
            {
                //r = new Random((int)voronoiSeedNumeric.Value);
                var borderElevation = 80;
                var step            = 20;
                for (int x = 0; x < Parameters.MapSize.X; x += 5)
                {
                    var poly = GetAtPoint(new Point(x, 0));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);


                    poly           = GetAtPoint(new Point(x, Parameters.MapSize.Y));
                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);
                }

                for (int y = 0; y < Parameters.MapSize.Y; y += 5)
                {
                    var poly = GetAtPoint(new Point(0, y));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);


                    poly = GetAtPoint(new Point(Parameters.MapSize.X, y));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);
                }
            }

            ElevateCorners();

            #region Moisturizing
            {
                var noise = new SimplexNoise(new Random(Parameters.ElevationSeed));
                noise.SetParameters(0.0008d, SimplexNoise.InflectionMode.NoInflections, SimplexNoise.ResultScale.ZeroToOne);

                foreach (var poly in this)
                {
                    var noiseVal = noise.GetNoise2DValue(poly.Center.X, poly.Center.Y, 2, 0.8);
                    var col      = 100 / noiseVal.MaxValue * noiseVal.Value;
                    poly.Moisture = (int)col;

                    foreach (var corner in poly.Corners)
                    {
                        noiseVal         = noise.GetNoise2DValue(corner.Point.X, corner.Point.Y, 2, 0.8);
                        col              = 2 / noiseVal.MaxValue * noiseVal.Value;
                        corner.WaterFlow = (int)col;
                    }
                }

                // fix heights

                foreach (var poly in this)
                {
                    foreach (var neighbor in poly.Neighbors)
                    {
                        if (poly.Elevation == neighbor.Elevation)
                        {
                            neighbor.Elevation = (int)neighbor.Neighbors.Average(n => n.Elevation);
                        }
                    }
                }

                // calculate rivers
                _corners1 = new HashSet <Corner>();

                // get unique corners
                foreach (var poly in this)
                {
                    foreach (var corner in poly.Corners)
                    {
                        if (!_corners1.Contains(corner) && corner.Polygons.Find(p => p.Elevation <= 127) == null)
                        {
                            _corners1.Add(corner);
                        }
                    }
                }

                var list = new List <Corner>(_corners1);
                list.Sort(new CornerHeightComparer());

                // propagate flow
                foreach (var corner in list)
                {
                    // find lowest edge
                    Edge lowestEdge = corner.Edges[0];
                    int  height     = lowestEdge.GetOpposite(corner).Elevation;
                    for (int i = 0; i < corner.Edges.Count; i++)
                    {
                        var tmp = corner.Edges[i].GetOpposite(corner).Elevation;
                        if (tmp < height)
                        {
                            height     = tmp;
                            lowestEdge = corner.Edges[i];
                        }
                    }

                    lowestEdge.WaterFlow += corner.WaterFlow;
                    lowestEdge.GetOpposite(corner).WaterFlow += corner.WaterFlow;
                }

                // remove rivers that not going to oceans

                _waterCorners = new List <Corner>();

                foreach (var poly in this)
                {
                    foreach (var corner in poly.Corners)
                    {
                        int solid = corner.Polygons.Count(p => p.Elevation > 127);

                        if (solid == 2)
                        {
                            _waterCorners.Add(corner);
                        }
                    }
                }

                // collect all correct edges
                _rivers.Clear();

                foreach (var waterCorner in _waterCorners)
                {
                    var root = new RiverBranch();
                    CollectRiver(waterCorner, root);
                    if (!root.Final)
                    {
                        _riverRoots.Add(root);
                    }
                }

                // fix river flows
                // stage 1: remove all flows
                foreach (var riverBranch in _riverRoots)
                {
                    EnumerateTree(riverBranch, b => { if (b.Edge != null)
                                                      {
                                                          b.Edge.WaterFlow = 0;
                                                      }
                                  });
                }
                // stage 2: reflow it
                foreach (var riverBranch in _riverRoots)
                {
                    FillRiver(riverBranch);
                }

                // remove all non-river
                foreach (var poly in this)
                {
                    foreach (var edge in poly.Edges)
                    {
                        if (edge.WaterFlow > 0 && !_rivers.Contains(edge))
                        {
                            edge.WaterFlow = 0;
                        }
                    }
                }

                // update moisture for polygons
                foreach (var poly in this)
                {
                    if (poly.Elevation > 127)
                    {
                        poly.Moisture = poly.Neighbors.Sum(p =>
                        {
                            var v = p.Neighbors.Sum(n => n.Edges.Sum(ed => ed.WaterFlow > 0 ? 1 : 0));
                            v     = v + p.Neighbors.Sum(n => n.Elevation < 127 && !n.Ocean ? 3 : 0);
                            return(p.Edges.Sum(ed => ed.WaterFlow > 0 ? 1 : 0) + v);
                        });
                    }
                }
            }
            #endregion

            // detect ocean
            {
                SetOcean(GetAtPoint(new Point(0, 0)));
                SetOcean(GetAtPoint(new Point(Parameters.MapSize.X, 0)));
                SetOcean(GetAtPoint(new Point(0, Parameters.MapSize.Y)));
                SetOcean(GetAtPoint(new Point(Parameters.MapSize.X, Parameters.MapSize.Y)));
            }

            // set biomes
            {
                foreach (var poly in this)
                {
                    if (poly.Elevation > 127)
                    {
                        poly.Biome = _biome.GetBiomeWith(poly.Elevation, poly.Moisture > _biome.Moisture.Maximum ? _biome.Moisture.Maximum : poly.Moisture);
                    }
                }
            }

            //find coastline
            foreach (var polygon in this)
            {
                foreach (var edge in polygon.Edges)
                {
                    Polygon poly;
                    Polygon poly2;
                    if (((poly = edge.Polygons.Find(p => p.Elevation > 127)) != null) && ((poly2 = edge.Polygons.Find((p => p.Elevation <= 127))) != null))
                    {
                        poly.Coast  = true;
                        poly2.Coast = true;
                        edge.Coast  = true;
                    }
                }
            }
        }