Пример #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="width">Width in pixels</param>
        /// <param name="height">Height in pixels</param>
        /// <param name="g">Game Reference</param>
        /// <param name="_gw">GameWorld Reference</param>
        public NavMeshManager(int width, int height, Game g)
        {
            nodeList = new List <PolygonNode>();
            PolygonNode root = new PolygonNode(new Rectangle(0, 0, width, height));

            nodeList.Add(root);
            game = g;
        }
Пример #2
0
        /// <summary>
        /// Returns an array of polygons that form a path
        /// between the two provided points from start to finish.
        /// </summary>
        /// <param name="start">Starting point</param>
        /// <param name="finish">Finish</param>
        /// <returns>Path</returns>
        public PolygonNode[] getPath(Point start, Point finish)
        {
            List <PolygonNode> closedSet = new List <PolygonNode>();
            List <PolygonNode> openSet   = new List <PolygonNode>();
            List <PolygonNode> came_from = new List <PolygonNode>();
            int         g_score          = 0;
            int         h_score          = getHScore(start, finish);
            int         f_score          = 0;
            PolygonNode endzone          = getNodeFromPosition(finish);

            openSet.Add(getNodeFromPosition(start));
            PolygonNode current = openSet.ElementAt <PolygonNode>(0);

            openSet.Remove(current);
            closedSet.Add(current);
            while (true)
            {
                if (current == endzone)
                {
                    break;
                }
                foreach (PolygonNode pn in current.getAdjacentNodes())
                {
                    if (closedSet.Contains(pn))
                    {
                        continue;
                    }
                    if (!openSet.Contains(pn))
                    {
                        openSet.Add(pn);
                        pn.parent = current;
                    }
                }


                current = getNodeWithLowestFScore(openSet, g_score, finish);
                if (current == null)
                {
                    throw new Exception("There is no spoon.");
                }
                openSet.Remove(current);
                closedSet.Add(current);
            }

            List <PolygonNode> output = new List <PolygonNode>();

            while (current != null)
            {
                output.Add(current);
                current = current.parent;
            }
            output.Reverse();
            nullParents();
            return(output.ToArray());
        }
Пример #3
0
        /// <summary>
        /// Add a new unwalkable rectangle
        /// </summary>
        /// <param name="rect">Rectangle to block.</param>
        public void addRectangle(Rectangle rect)
        {
            tex = game.Content.Load <Texture2D>("White");
            PolygonNode[]      overlaps = getOverlappingNodes(rect);
            List <PolygonNode> newNodes = new List <PolygonNode>();
            List <Point>       vertices = new List <Point>();

            addVertex(vertices, new Point(rect.Left, rect.Top));
            addVertex(vertices, new Point(rect.Left, rect.Bottom));
            addVertex(vertices, new Point(rect.Right, rect.Top));
            addVertex(vertices, new Point(rect.Right, rect.Bottom));
            foreach (PolygonNode pn in overlaps)
            {
                Rectangle oldRect = pn.rectangle;
                addVertex(vertices, new Point(oldRect.Left, oldRect.Top));
                addVertex(vertices, new Point(oldRect.Left, oldRect.Bottom));
                addVertex(vertices, new Point(oldRect.Right, oldRect.Top));
                addVertex(vertices, new Point(oldRect.Right, oldRect.Bottom));
                addOverlapVerts(vertices, oldRect, rect);
            }

            Point badPoint = new Point(-1, -1);

            foreach (Point origin in vertices)
            {
                Point left   = getClosestLeft(origin, vertices);
                Point bottom = getClosestBottom(origin, vertices);
                if (left.Equals(badPoint) || bottom.Equals(badPoint))
                {
                    continue;
                }
                int       width   = left.X - origin.X;
                int       height  = bottom.Y - origin.Y;
                Rectangle newRect = new Rectangle(origin.X, origin.Y, width, height);
                if (rect.Contains(newRect.Center))
                {
                    continue;
                }
                if (!newRect.Equals(rect))
                {
                    PolygonNode newPoly = new PolygonNode(newRect);
                    // newPoly.rectangle.Inflate(1,1);
                    nodeList.Add(newPoly);
                    newNodes.Add(newPoly);
                }
            }
            redoAdj(overlaps, newNodes.ToArray());

            foreach (PolygonNode pn in overlaps.ToArray())
            {
                nodeList.Remove(pn);
            }
        }
Пример #4
0
 /// <summary>
 /// Adds each node to the other's adjacency list.
 /// </summary>
 /// <param name="p1">First node.</param>
 /// <param name="p2">Second node.</param>
 public static void linkPolygons(PolygonNode p1, PolygonNode p2)
 {
     if (p1 == p2)
     {
         throw new Exception("A polygon can't be adjacent to itself.");
     }
     if (!p1.adjacentNodes.Contains(p2))
     {
         p1.addNode(p2);
     }
     if (!p2.adjacentNodes.Contains(p1))
     {
         p2.addNode(p1);
     }
 }
Пример #5
0
        /// <summary>
        /// Method for getting the node with the f_score from the given set.
        /// </summary>
        /// <param name="set">Nodes to check</param>
        /// <param name="g_score">Current g_score</param>
        /// <param name="end">Finish</param>
        /// <returns></returns>
        private PolygonNode getNodeWithLowestFScore(IEnumerable <PolygonNode> set, int g_score, Point end)
        {
            int         lowest   = int.MaxValue;
            PolygonNode pnLowest = null;

            foreach (PolygonNode pn in set)
            {
                int _f = getHScore(pn.rectangle.Center, end) + g_score;
                if (_f < lowest)
                {
                    lowest   = _f;
                    pnLowest = pn;
                }
            }
            return(pnLowest);
        }
Пример #6
0
        /// <summary>
        /// This is not really working it should be the point
        /// that one should pass through between to polygons.
        /// </summary>
        /// <param name="pn1">First Polygon</param>
        /// <param name="pn2">Second Polygon</param>
        /// <returns>the sweet spot</returns>
        public static Point getConnectionPoint(PolygonNode pn1, PolygonNode pn2)
        {
            if (pn1 == pn2)
            {
                throw new Exception("A node cannot be connected to itself.");
            }
            if (!pn1.adjacentNodes.Contains(pn2))
            {
                throw new Exception("These nodes are not adjacent and therefore have no connection point.");
            }
            Rectangle r1 = pn1.rectangle;
            Rectangle r2 = pn2.rectangle;
            int       x  = -10;
            int       y  = -10;

            if (r1.Top == r2.Bottom)
            {
                y = r1.Top;
            }
            if (r1.Bottom == r2.Top)
            {
                y = r1.Bottom;
            }
            if (r1.Left == r2.Right)
            {
                x = r1.Left;
            }
            if (r1.Right == r2.Left)
            {
                x = r1.Right;
            }

            if (x == -10)
            {
                int n = (Math.Max(r1.Width, r2.Width) - Math.Abs(r1.X - r2.X));
                x = n / 2 + Math.Max(r1.X, r2.X);
            }

            if (y == -10)
            {
                int n = (Math.Max(r1.Height, r2.Height) - Math.Abs(r1.Y - r2.Y));
                y = n / 2 + Math.Max(r1.Y, r2.Y);
            }

            return(new Point(x, y));
        }
Пример #7
0
        /// <summary>
        /// Check if two PolygonNodes are adjacent.
        /// </summary>
        /// <param name="p1">First Node</param>
        /// <param name="p2">Second Node</param>
        /// <returns>True if they are next to each other.</returns>
        public static bool areTheseAdjacent(PolygonNode p1, PolygonNode p2)
        {
            Rectangle r1 = p1.rectangle;
            Rectangle r2 = p2.rectangle;

            r1.Inflate(1, 0);
            if (r1.Intersects(r2))
            {
                return(true);
            }
            r1.Inflate(-1, 1);
            if (r1.Intersects(r2))
            {
                return(true);
            }
            r1.Inflate(0, -1);
            return(false);
        }
Пример #8
0
        /// <summary>
        /// Redoes the adjacency's of all of the effected polygons.
        /// </summary>
        /// <param name="oldNodes">Nodes to be deleted</param>
        /// <param name="newNodes">New nodes generated</param>
        private void redoAdj(IEnumerable <PolygonNode> oldNodes, IEnumerable <PolygonNode> newNodes)
        {
            foreach (PolygonNode pnOld in oldNodes)
            {
                foreach (PolygonNode pnAdj in pnOld.getAdjacentNodes())
                {
                    pnAdj.removeNode(pnOld);
                    foreach (PolygonNode pnNew in newNodes)
                    {
                        if (pnNew == pnAdj)
                        {
                            continue;
                        }
                        if (PolygonNode.areTheseAdjacent(pnNew, pnAdj))
                        {
                            PolygonNode.linkPolygons(pnNew, pnAdj);
                        }
                    }
                }
            }

            foreach (PolygonNode pn1 in newNodes)
            {
                foreach (PolygonNode pn2 in newNodes)
                {
                    if (pn1 == pn2)
                    {
                        continue;
                    }
                    if (PolygonNode.areTheseAdjacent(pn1, pn2))
                    {
                        PolygonNode.linkPolygons(pn1, pn2);
                    }
                }
            }
        }
Пример #9
0
 /// <summary>
 /// Adds an adjacent node from this node.
 /// </summary>
 /// <param name="pn">Node to add</param>
 /// <returns>True</returns>
 public bool addNode(PolygonNode pn)
 {
     adjacentNodes.Add(pn);
     return(true);
 }
Пример #10
0
 /// <summary>
 /// Removes an adjacent node from this node.
 /// </summary>
 /// <param name="pn">Node to remove</param>
 /// <returns>True if it was in the list, false otherwise.</returns>
 public bool removeNode(PolygonNode pn)
 {
     return(adjacentNodes.Remove(pn));
 }