예제 #1
0
        private void BuildPatches()
        {
            var points = GetVoronoiPoints(NumPatches, Center).ToList();

            var v = Voronoi.Build(points);

            for (var i = 0; i < 3; i++)
            {
                var toRelax = v.Points.Take(3).ToList();
                toRelax.Add(v.Points[NumPatches]);
                v = Voronoi.Relax(v, toRelax);
            }

            v = Voronoi.Relax(v);

            var comparer = new Vector2LengthComparer();

            v.Points.Sort(comparer);

            var regions = v.Partitioning();

            Patches.Clear();
            foreach (var region in regions)
            {
                Patches.Add(Patch.FromRegion(this, region));
            }

            var patchesInTown = Patches.OrderBy(p => (Center - p.Center).magnitude).Take(NumPatches).ToList();

            // Find random patch at the outside of town to place water
            if (Options.Water)
            {
                var firstWaterPatch = patchesInTown.Where(p => p.GetAllNeighbours().Any(n => !n.WithinCity))
                                      .OrderBy(p => Random.value).First();
                firstWaterPatch.Water = true;

                Vector2 waterDirection = (firstWaterPatch.Center - Center).normalized;


                var toCheck = new List <Patch> {
                    firstWaterPatch
                };
                while (toCheck.Any())
                {
                    var checking = toCheck[0];
                    toCheck.RemoveAt(0);

                    var waterPatches = checking.GetAllNeighbours().Except(patchesInTown)
                                       .Where(n => Math.Abs(GeometryHelpers.AngleComparedTo(Center - n.Center, waterDirection)) < Math.PI / 4)
                                       .Where(n => !n.Water).ToList();
                    foreach (var waterPatch in waterPatches)
                    {
                        waterPatch.Water = true;
                        toCheck.Add(waterPatch);
                    }
                }
            }

            patchesInTown = Patches.Where(p => !p.Water).OrderBy(p => (Center - p.Center).magnitude).Take(NumPatches)
                            .ToList();

            foreach (var patch in patchesInTown)
            {
                patch.WithinCity  = true;
                patch.WithinWalls = true;
            }

            Castle = new Castle(patchesInTown.Last());

            Market = patchesInTown.First();
            Market.IsCityCenter = true;

            var circumference = FindCircumference(patchesInTown);
            var smoothAmount  = Math.Min(1f, 40f / circumference.Vertices.Count);

            if (Options.Walls)
            {
                SmoothPatches(circumference, smoothAmount);
            }

            if (Options.Water)
            {
                var waterCircumference = FindCircumference(Patches.Where(p => p.Water));
                SmoothPatches(waterCircumference, 0.2f);
                WaterBorder.Clear();
                WaterBorder.AddRange(waterCircumference.Vertices);
            }
        }