예제 #1
0
        private static List<Tile> CalculateQuadrant(Tile source, int visionRadius, TileMap map, Line sourceVisionLine)
        {

            List<Tile> quadrant = new List<Tile>();
            List<Tile> visibleTiles = new List<Tile>();

            int xFactor = (int)(sourceVisionLine.start.x * 2 - 1);
            int yFactor = (int)(sourceVisionLine.end.y * 2 - 1);

            for (int x = 1; x <= visionRadius / Math.Cos(45); x++)
            {
                for (int y = 0; y <= x; y++)
                {
                    if (!(visionRadius < Math.Sqrt(Math.Pow(x - y, 2) + Math.Pow(y, 2))))
                    {
                        if (map.inMap(source.x + xFactor * (x - y), source.y + yFactor * y))
                        {
                            quadrant.Add(map[source.x + xFactor * (x - y), source.y + yFactor * y]);
                        }
                    }
                }
            }

#if(FOV)
            for (int i = 0; i < quadrant.Count; i++)
                quadrant[i].num = i;
#endif

            List<View> views = new List<View>();
            views.Add(new View(
                source.x + (int) sourceVisionLine.end.x,
                source.y + (int) sourceVisionLine.end.y, 
                source.x + xFactor * visionRadius + (int) sourceVisionLine.start.x, 
                source.y + (int) sourceVisionLine.start.y,
                source.x + (int) sourceVisionLine.start.x,
                source.y + (int) sourceVisionLine.start.y, 
                source.x + (int) sourceVisionLine.end.x, 
                source.y + yFactor * visionRadius + (int) sourceVisionLine.end.y)); // create shallow and steep initial lines
             
            for (int i = 0; i < quadrant.Count; i++)
            {
                List<View> currentViews = new List<View>();
                currentViews.AddRange(views);

                // fov calculation
                while (currentViews.Count > 0)
                {

                    int j = views.FindIndex(x => x.Equals(currentViews[0]));
                    visibilityStatus? vis = getVisibilityStatus(quadrant[i], source, map, currentViews.ElementAt(0), sourceVisionLine);
                    switch (vis)
                    {
                        case visibilityStatus.outside:
                            //Debug.WriteLine("Outside");
                            //do nothing
                            //quadrant[i].debug = Color.Gold;
                            break;

                        case visibilityStatus.between:
                            //Debug.WriteLine("Between");
#if(FOV)
                            quadrant[i].debug = Color.Green;
#endif
                            visibleTiles.Add(quadrant[i]);
                            if (!quadrant[i].Translucent)
                            {

                                Line possibleNewShallow = new Line(views[j].shallow.start, quadrant[i].position + sourceVisionLine.end);

                                View view = new View(possibleNewShallow, currentViews[0].steep);

                                foreach (Tile tile in View.steepBump)
                                {
                                    if (obstructionCheck(tile, source, view.shallow, sourceVisionLine))
                                    {
                                        view.shallow = new Line(tile.position + sourceVisionLine.start, view.shallow.end);
                                    }
                                }

                                if (!Line.sameLine(view.shallow, currentViews[0].steep))
                                {
                                    views.Add(view);
#if(FOV)
                                    linesToDraw.Add(view.shallow);
                                    linesToDraw.Add(view.steep);
#endif
                                }


                                Line possibleNewSteep = new Line(views[j].steep.start, quadrant[i].position + sourceVisionLine.start);

                                view = new View(currentViews[0].shallow, possibleNewSteep);

                                foreach (Tile tile in View.shallowBump)
                                {
                                    if (obstructionCheck(tile, source, view.steep, sourceVisionLine))
                                    {
                                        view.steep = new Line(tile.position + sourceVisionLine.end, view.steep.end);
                                    }
                                }

                                if (!Line.sameLine(currentViews[0].shallow, view.steep))
                                {
                                    views.Add(view);
#if(FOV)
                                    linesToDraw.Add(view.shallow);
                                    linesToDraw.Add(view.steep);
#endif
                                }

                                View.shallowBump.Add(quadrant[i]);
                                View.steepBump.Add(quadrant[i]);

                                views.RemoveAt(j);
                            }
                            break;

                        case visibilityStatus.blocking:
                            //Debug.WriteLine("Blocking");
#if(FOV)
                            quadrant[i].debug = Color.Indigo;
#endif
                            visibleTiles.Add(quadrant[i]);
                            if (!quadrant[i].Translucent)
                            {
                                views.RemoveAt(j);
                            }
                            break;

                        case visibilityStatus.shallowBump:
                            //Debug.WriteLine("Shallow");
#if(FOV)
                            quadrant[i].debug = Color.Orange;
#endif
                            visibleTiles.Add(quadrant[i]);
                            if (!quadrant[i].Translucent)
                            {
                                views[j].shallow = new Line(views[j].shallow.start, quadrant[i].position + sourceVisionLine.end);

                                foreach (Tile tile in View.steepBump)
                                {
                                    if (obstructionCheck(tile, source, views[j].shallow, sourceVisionLine))
                                    {
#if(FOV)
                                        tile.debug = Color.Firebrick;
                                        quadrant[i].debug = Color.DarkRed;
#endif
                                        views[j].shallow = new Line(tile.position + sourceVisionLine.start, views[j].shallow.end);
                                    }
                                }

                                if (Line.sameLine(views[j].shallow, views[j].steep))
                                {
                                    views.RemoveAt(j);
                                }
                                else
                                {
#if(FOV)
                                    linesToDraw.Add(views[j].shallow);
                                    linesToDraw.Add(views[j].steep);
#endif
                                }
                                View.shallowBump.Add(quadrant[i]);
                            }
                            break;

                        case visibilityStatus.steepBump:
                            //Debug.WriteLine("Steep");
#if(FOV)
                            quadrant[i].debug = Color.Aqua;
#endif
                            visibleTiles.Add(quadrant[i]);
                            if (!quadrant[i].Translucent)
                            {
                                views[j].steep = new Line(views[j].steep.start, quadrant[i].position + sourceVisionLine.start);

                                foreach (Tile tile in View.shallowBump)
                                {
                                    if (obstructionCheck(tile, source, views[j].steep, sourceVisionLine))
                                    {
#if(FOV)
                                        tile.debug = Color.Bisque;
                                        quadrant[i].debug = Color.Brown;
#endif
                                        views[j].steep = new Line(tile.position + sourceVisionLine.end, views[j].steep.end);
                                    }
                                }


                                if (Line.sameLine(views[j].shallow, views[j].steep))
                                {
                                    views.RemoveAt(j);
                                }
                                else
                                {
#if(FOV)
                                    linesToDraw.Add(views[j].shallow);
                                    linesToDraw.Add(views[j].steep);
#endif
                                }

                                View.steepBump.Add(quadrant[i]);
                            }
                            break;

                        default:
                            throw new ArgumentException("visibility status is null!!");
                    }

                    currentViews.Remove(currentViews[0]);
                }
            }

            View.Reset();

            return visibleTiles;
        }
예제 #2
0
        static visibilityStatus? getVisibilityStatus(Tile tile, Tile source, TileMap map, View view, Line sourceVisionLine) 
        {
            int factor = (int) (sourceVisionLine.end.y * 2 - 1);

            Vector2 convertedTile = tile.position - source.position;
            Vector2 convertedTopEdge = convertedTile + sourceVisionLine.end;
            Vector2 convertedBottomEdge = convertedTile + sourceVisionLine.start;
            Line convertedObjectLine = new Line(convertedTopEdge, convertedBottomEdge);

            Line convertedSteep = new Line(view.steep.start - source.position, view.steep.end - source.position);
            Line convertedShallow = new Line(view.shallow.start - source.position, view.shallow.end - source.position);

            Vector2 steepIntersect = Line.Intersect(convertedObjectLine, convertedSteep);
            Vector2 shallowIntersect = Line.Intersect(convertedObjectLine, convertedShallow);

            if (steepIntersect.y * factor <= convertedBottomEdge.y * factor || shallowIntersect.y * factor >= convertedTopEdge.y * factor) 
            {
                return visibilityStatus.outside;
            }

            if (shallowIntersect.y * factor > convertedBottomEdge.y * factor && shallowIntersect.y * factor < convertedTopEdge.y * factor)
            {
                return visibilityStatus.shallowBump;
            }

            if (steepIntersect.y * factor > convertedBottomEdge.y * factor && steepIntersect.y * factor < convertedTopEdge.y * factor)
            {
                return visibilityStatus.steepBump;
            }

            if (steepIntersect.y * factor >= convertedTopEdge.y * factor && shallowIntersect.y * factor <= convertedBottomEdge.y * factor)
            {
                return visibilityStatus.between;
            }

            if (steepIntersect.y * factor < convertedTopEdge.y * factor && shallowIntersect.y * factor > convertedBottomEdge.y * factor)
            {
                return visibilityStatus.blocking;
            }

            return null;

        }