コード例 #1
0
ファイル: LOS.cs プロジェクト: Tomash667/Rogue-Survivor
        public static HashSet <Point> ComputeFOVFor(Rules rules, Actor actor, WorldTime time, Weather weather)
        {
            Location        fromLocation = actor.Location;
            HashSet <Point> visibleSet   = new HashSet <Point>();
            Point           from         = fromLocation.Position;
            Map             map          = fromLocation.Map;
            int             maxRange     = rules.ActorFOV(actor, time, weather);

            //////////////////////////////////////////////
            // Brute force ray-casting with wall fix pass
            //////////////////////////////////////////////
            int xmin = from.X - maxRange;
            int xmax = from.X + maxRange;
            int ymin = from.Y - maxRange;
            int ymax = from.Y + maxRange;

            map.TrimToBounds(ref xmin, ref ymin);
            map.TrimToBounds(ref xmax, ref ymax);
            Point        to         = new Point();
            List <Point> wallsToFix = new List <Point>();

            // 1st pass : trace line and remember walls that are not visible for 2nd pass.
            for (int x = xmin; x <= xmax; x++)
            {
                to.X = x;
                for (int y = ymin; y <= ymax; y++)
                {
                    to.Y = y;

                    // Distance check.
                    if (rules.LOSDistance(from, to) > maxRange)
                    {
                        continue;
                    }

                    // If we already know tile is visible, pass.
                    if (visibleSet.Contains(to))
                    {
                        continue;
                    }

                    // Trace line.
                    if (!FOVSub(fromLocation, to, maxRange, ref visibleSet))
                    {
                        // if its a wall (in FoV terms), remember.
                        bool      isFovWall = false;
                        Tile      tile      = map.GetTileAt(x, y);
                        MapObject mapObj    = map.GetMapObjectAt(x, y);
                        if (!tile.Model.IsTransparent && !tile.Model.IsWalkable)
                        {
                            isFovWall = true;
                        }
                        else if (mapObj != null)
                        {
                            isFovWall = true;
                        }
                        if (isFovWall)
                        {
                            wallsToFix.Add(to);
                        }

                        // next.
                        continue;
                    }

                    // Visible.
                    visibleSet.Add(to);
                }
            }

            // 2nd pass : wall fix.
            List <Point> fixedWalls = new List <Point>(wallsToFix.Count);

            foreach (Point wallP in wallsToFix)
            {
                int count = 0;
                foreach (Direction d in Direction.COMPASS)
                {
                    Point next = wallP + d;
                    if (visibleSet.Contains(next))
                    {
                        Tile tile = map.GetTileAt(next.X, next.Y);
                        if (tile.Model.IsTransparent && tile.Model.IsWalkable)
                        {
                            ++count;
                        }
                    }
                }
                if (count >= 3)
                {
                    fixedWalls.Add(wallP);
                }
            }
            foreach (Point fixedWall in fixedWalls)
            {
                visibleSet.Add(fixedWall);
            }

            return(visibleSet);
        }