//public FovShapeType FovShape
        //{
        //    get { return fovProfile.FovShape; }
        //    set { fovProfile.FovShape = value; }
        //}

        #endregion

        #region IFovAlgorithm Members

        public FovResultset CalculateFov(TerrainMap terrain, Point origin, IFovProfile fovProfile)
        {
            visibleLocations = new FovResultset();
            //     fovProfile.FovShape = shapeType;

            if (terrain != null)
            {
                visibleLocations.Add(new FovObject()
                {
                    Location = { Coordinate = origin }, DistanceFromOrigin = 0
                });
                if (fovProfile.FovRadius > 0)
                {
                    ScanNorthwestToNorth(terrain, origin, fovProfile);
                    ScanNorthToNortheast(terrain, origin, fovProfile);
                    ScanNortheastToEast(terrain, origin, fovProfile);
                    ScanEastToSoutheast(terrain, origin, fovProfile);
                    ScanSoutheastToSouth(terrain, origin, fovProfile);
                    ScanSouthToSouthwest(terrain, origin, fovProfile);
                    ScanSouthwestToWest(terrain, origin, fovProfile);
                    ScanWestToNorthwest(terrain, origin, fovProfile);
                }
            }

            return(visibleLocations);
        }
Exemplo n.º 2
0
 public VisibilityMap(int width, int height, IFovProfile fovProfile, IFovAlgorithm fovAlgorithm)
     : base(new Size(width, height), () => new VisibilityObject())
 {
     this.fovProfile   = fovProfile;
     this.fovAlgorithm = fovAlgorithm;
 }
        private void ScanNorthwestToNorth(TerrainMap terrain, Point origin, IFovProfile fovProfile, float startSlope,
                                          float endSlope, int distance)
        {
            if (distance > fovProfile.FovRadius)
            {
                return;
            }

            var xStart = (int)Math.Floor(origin.X + 0.5 - (startSlope * distance));
            var xEnd   = (int)Math.Floor(origin.X + 0.5 - (endSlope * distance));
            int yCheck = origin.Y - distance;

            if ((fovProfile.FovShape == FovShapeType.Circle) || (fovProfile.FovShape == FovShapeType.RoundedSquare))
            {
                int xRadius;
                if ((fovProfile.FovShape == FovShapeType.RoundedSquare) && (distance == fovProfile.FovRadius))
                {
                    xRadius = origin.X - (fovProfile.FovRadius / 2);
                }
                else
                {
                    xRadius = origin.X - CalculateRadius(fovProfile.FovRadius, distance);
                }

                if (xStart < xRadius)
                {
                    xStart = xRadius;
                }
                if (xStart > xEnd)
                {
                    return;
                }
            }

            var currentLocation = new Point(xStart, yCheck);

            if (!terrain.Bounds.Contains(currentLocation))
            {
                return;
            }

            SetAsVisible(terrain, currentLocation, distance);
            bool prevLocationWasBlocked = fovProfile.LosIsBlockedByTerrain(terrain[currentLocation]);

            for (int xCheck = xStart + 1; xCheck <= xEnd; xCheck++)
            {
                currentLocation = new Point(xCheck, yCheck);
                if (!terrain.Bounds.Contains(currentLocation))
                {
                    return;
                }

                SetAsVisible(terrain, currentLocation, distance);

                if (fovProfile.LosIsBlockedByTerrain(terrain[currentLocation]))
                {
                    if (!prevLocationWasBlocked)
                    {
                        ScanNorthwestToNorth(terrain, origin, fovProfile, startSlope,
                                             InverseSlope(GetCenterCoordinate(origin),
                                                          PointF.Add(currentLocation, new SizeF(-0.0000001f, 0.9999999f))),
                                             distance + 1);
                    }
                    prevLocationWasBlocked = true;
                }
                else
                {
                    if (prevLocationWasBlocked)
                    {
                        startSlope = InverseSlope(GetCenterCoordinate(origin), currentLocation);
                    }
                    prevLocationWasBlocked = false;
                }
            }

            if (!prevLocationWasBlocked)
            {
                ScanNorthwestToNorth(terrain, origin, fovProfile, startSlope, endSlope, distance + 1);
            }
        }
        private void ScanWestToNorthwest(TerrainMap terrain, Point origin, IFovProfile fovProfile, float startSlope,
                                         float endSlope, int distance)
        {
            if (distance > fovProfile.FovRadius)
            {
                return;
            }

            var yStart = (int)Math.Floor((origin.Y + 0.5) - (startSlope * distance));
            var yEnd   = (int)Math.Floor((origin.Y + 0.5) - (endSlope * distance));
            int xCheck = origin.X - distance;

            if ((fovProfile.FovShape == FovShapeType.Circle) || (fovProfile.FovShape == FovShapeType.RoundedSquare))
            {
                int yRadius;
                if ((fovProfile.FovShape == FovShapeType.RoundedSquare) && (distance == fovProfile.FovRadius))
                {
                    yRadius = origin.Y - (fovProfile.FovRadius / 2);
                }
                else
                {
                    yRadius = origin.Y - CalculateRadius(fovProfile.FovRadius, distance);
                }

                if (yEnd < yRadius)
                {
                    yEnd = yRadius;
                }
                if (yStart < yEnd)
                {
                    return;
                }
            }

            var currentLocation = new Point(xCheck, yStart);

            if (!terrain.Bounds.Contains(currentLocation))
            {
                return;
            }

            SetAsVisible(terrain, currentLocation, distance);
            bool prevBlocked = fovProfile.LosIsBlockedByTerrain(terrain[currentLocation]);

            for (int yCheck = yStart - 1; yCheck >= yEnd; yCheck--)
            {
                currentLocation = new Point(xCheck, yCheck);
                if (!terrain.Bounds.Contains(currentLocation))
                {
                    return;
                }

                SetAsVisible(terrain, currentLocation, distance);

                if (fovProfile.LosIsBlockedByTerrain(terrain[currentLocation]))
                {
                    if (!prevBlocked)
                    {
                        ScanWestToNorthwest(terrain, origin, fovProfile, startSlope,
                                            Slope(GetCenterCoordinate(origin),
                                                  PointF.Add(currentLocation, new SizeF(0, 1))), distance + 1);
                    }
                    prevBlocked = true;
                }
                else
                {
                    if (prevBlocked)
                    {
                        startSlope = Slope(GetCenterCoordinate(origin),
                                           PointF.Add(currentLocation, new SizeF(0.9999999f, 0.9999999f)));
                    }
                    prevBlocked = false;
                }
            }

            if (!prevBlocked)
            {
                ScanWestToNorthwest(terrain, origin, fovProfile, startSlope, endSlope, distance + 1);
            }
        }
 public void ScanWestToNorthwest(TerrainMap terrain, Point origin, IFovProfile fovProfile)
 {
     ScanWestToNorthwest(terrain, origin, fovProfile, 0, 1, 1);
 }
 public void ScanSouthwestToWest(TerrainMap terrain, Point origin, IFovProfile fovProfile)
 {
     ScanSouthwestToWest(terrain, origin, fovProfile, -1, 0, 1);
 }
 public void ScanSoutheastToSouth(TerrainMap terrain, Point origin, IFovProfile fovProfile)
 {
     ScanSoutheastToSouth(terrain, origin, fovProfile, 1, 0, 1);
 }
 public void ScanNortheastToEast(TerrainMap terrain, Point origin, IFovProfile fovProfile)
 {
     ScanNortheastToEast(terrain, origin, fovProfile, -1, 0, 1);
 }