示例#1
0
 public RichArea(Patch patch) : base(patch)
 {
 }
示例#2
0
 public PoorArea(Patch patch) : base(patch)
 {
 }
示例#3
0
 public OutsideWallArea(Patch patch) : base(patch)
 {
 }
示例#4
0
 public EmptyArea(Patch patch) : base(patch)
 {
 }
示例#5
0
 public CastleArea(Patch patch) : base(patch)
 {
 }
示例#6
0
 public TownArea(Patch patch) : base(patch)
 {
     _town = patch.Town;
 }
示例#7
0
 public FarmArea(Patch patch) : base(patch)
 {
 }
示例#8
0
 protected Area(Patch patch)
 {
     Patch  = patch;
     random = patch.Town.Random;
 }
示例#9
0
 public Polygon FindCircumference(Patch patch)
 {
     return(FindCircumference(new List <Patch> {
         patch
     }));
 }
示例#10
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).Length).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 => Rnd.NextDouble()).First();
                firstWaterPatch.Water = true;

                var waterDirection = Vector2.Normalize(firstWaterPatch.Center - Center);

                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((Center - n.Center).AngleComparedTo(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).Length).Take(NumPatches)
                            .ToList();

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

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

            Market = patchesInTown.First();

            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);
            }
        }
示例#11
0
 protected Area(Patch patch)
 {
     Patch = patch;
 }
示例#12
0
        private void PlaceGatesAndTowers(IEnumerable <Vector2> allowedTowerPositions, int minNumberOfGates, int maxNumberOfGates, List <Vector2> illegalGatePositions)
        {
            var cityPatches    = _town.Patches.Where(p => p.WithinCity).ToList();
            var outsidePatches = _town.Patches.Except(cityPatches).ToList();
            var possibleGates  = allowedTowerPositions
                                 .Where(v => cityPatches.Count(cp => cp.Shape.Vertices.Contains(v)) > 1)
                                 .Except(illegalGatePositions)
                                 .OrderByDescending(v => (_town.Castle.Patch.Center - v).Length)
                                 .ToList();

            var towers = Circumference.ToList();
            var gates  = new List <Vector2> ();

            var attempts = 0;

            while ((gates.Count < minNumberOfGates || attempts < 4) && possibleGates.Any() && gates.Count < maxNumberOfGates)
            {
                attempts++;
                var newGate = possibleGates.First();

                try
                {
                    possibleGates.Remove(newGate);
                    possibleGates.RemoveFirstIfPossible();
                    possibleGates.RemoveFirstIfPossible();

                    var outerNeighbours = outsidePatches
                                          .Where(p => p.Shape.Vertices.Any(v => v.Equals(newGate)))
                                          .ToList();

                    if (outerNeighbours.Count == 1)
                    {
                        var neighbour = outerNeighbours.Single();
                        var wallPoint = neighbour.Shape.GetNextVertex(newGate) -
                                        neighbour.Shape.GetPreviousVertex(newGate);
                        var outPoint            = new Vector2(wallPoint.y, -wallPoint.x);
                        var possibleSplitPoints = neighbour.Shape.Vertices.Except(Circumference).ToList();
                        var farthest            = possibleSplitPoints.OrderByDescending(p =>
                        {
                            var dir = p - newGate;
                            return(Vector2.Dot(dir, outPoint) / dir.Length);
                        }).First();

                        var newPatches = neighbour.Shape.Split(newGate, farthest).Select(p => Patch.FromPolygon(_town, p)).ToList();
                        if (newPatches.Any(p => p.Shape.Vertices.Count < 3))
                        {
                            farthest   = neighbour.Shape.GetNextVertex(farthest);
                            newPatches = neighbour.Shape.Split(newGate, farthest).Select(p => Patch.FromPolygon(_town, p)).ToList();
                            if (newPatches.Any(p => p.Shape.Vertices.Count < 3))
                            {
                                throw new InvalidOperationException(
                                          "Splitting patch resulted in polygon with only two points");
                            }
                        }
                        _town.Patches.Remove(neighbour);
                        _town.Patches.AddRange(newPatches);
                    }

                    gates.Add(newGate);
                    towers.Remove(newGate);
                }
                catch (InvalidOperationException) { }
            }

            _town.Gates.AddRange(gates);
            Gates.AddRange(gates);
            Towers.AddRange(towers);
        }