예제 #1
0
        protected void Initialize(int sx, int sy)
        {
            mx = sx;
            my = sy;

            map = new PathNode2D[mx, my];
            for (int x = 0; x < mx; x++)
            {
                for (int y = 0; y < my; y++)
                {
                    map[x, y] = new PathNode2D(x, y);
                }
            }
        }
예제 #2
0
        protected override bool VerifyPassConditions(PathNode2D node, PathNode2D parent, int d, Dictionary <string, int> passConditions)
        {
            bool isPassable = true;

            if (d % 2 == 0 & passConditions["diagonalBlocking"] == 1)
            {
                if (IsInMapBounds(parent.X + dirRectGrid2D[RectGrid2D_NextDir(d), 0], parent.Y + dirRectGrid2D[RectGrid2D_NextDir(d), 1]))
                {
                    isPassable = isPassable && map[parent.X + dirRectGrid2D[RectGrid2D_NextDir(d), 0], parent.Y + dirRectGrid2D[RectGrid2D_NextDir(d), 1]].GetBool("isPassable");
                }
                if (IsInMapBounds(parent.X + dirRectGrid2D[RectGrid2D_PrevDir(d), 0], parent.Y + dirRectGrid2D[RectGrid2D_PrevDir(d), 1]))
                {
                    isPassable = isPassable && map[parent.X + dirRectGrid2D[RectGrid2D_PrevDir(d), 0], parent.Y + dirRectGrid2D[RectGrid2D_PrevDir(d), 1]].GetBool("isPassable");
                }
            }

            return(isPassable && base.VerifyPassConditions(node, parent, d, passConditions));
        }
예제 #3
0
        public PathNode2D(PathNode2D source)
        {
            X = source.X;
            Y = source.Y;

            foreach (KeyValuePair <string, int> p in source.properties_i)
            {
                properties_i.Add(p.Key, p.Value);
            }
            foreach (KeyValuePair <string, string> p in source.properties_s)
            {
                properties_s.Add(p.Key, p.Value);
            }
            foreach (KeyValuePair <string, float> p in source.properties_f)
            {
                properties_f.Add(p.Key, p.Value);
            }
            foreach (KeyValuePair <string, bool> p in source.properties_b)
            {
                properties_b.Add(p.Key, p.Value);
            }
        }
예제 #4
0
 protected override void AssignNodeProperties(PathNode2D node, PathNode2D parent, int d, Dictionary <string, int> passConditions, Dictionary <string, int> pathWeights)
 {
     base.AssignNodeProperties(node, parent, d, passConditions, pathWeights);
 }
예제 #5
0
 private static int ComparePathWeights(PathNode2D a, PathNode2D b)
 {
     return(a.GetInt("pathWeight").CompareTo(b.GetInt("pathWeight")));
 }
예제 #6
0
 public GridPath2D(List <PathNode2D> path)
 {
     Path      = path;
     PathStart = Path.Count > 0 ? Path[Path.Count - 1] : null;
     PathEnd   = Path.Count > 0 ? Path[0] : null;
 }
예제 #7
0
        public GridPath2D FindPath(
            int startX, int startY,
            int endX, int endY,
            bool allowStraight = true,
            bool allowDiagonal = true,
            Options options    = null,
            Dictionary <string, int> sortingOptions = null,
            Dictionary <string, int> passConditions = null,
            Dictionary <string, int> pathWeights    = null
            )
        {
            // Pre-check
            if (map == null)
            {
                throw new Exception("Map array is not initialized!");
            }
            if (!IsInMapBounds(startX, startY))
            {
                throw new Exception("Starting coordinates are out of map bounds!");
            }
            if (!IsInMapBounds(endX, endY))
            {
                throw new Exception("Target coordinates are out of map bounds!");
            }

            // Clear map/path flags
            for (int x = 0; x < mx; x++)
            {
                for (int y = 0; y < my; y++)
                {
                    map[x, y].SetProperty("isProcessed", false);
                    map[x, y].SetProperty("isPath", false);
                    map[x, y].SetProperty("isBetterCheckEnabled", Math.Sqrt(Math.Pow(x - endX, 2) + Math.Pow(y - endY, 2)) < options.isBetterCheckRadius);
                }
            }

            // Init.
            if (options == null)
            {
                options = new Options();
            }
            List <PathNode2D> toBeProcessed = new List <PathNode2D>();
            List <PathNode2D> processed     = new List <PathNode2D>();
            List <PathNode2D> endPoints     = new List <PathNode2D>();

            map[startX, startY].SetProperty("isProcessed", true);

            // Starting node
            PathNode2D n = new PathNode2D(map[startX, startY]);

            n.SetProperty("parent", -1);
            n.SetProperty("stack", 0);
            processed.Add(n);
            toBeProcessed.Add(n);

            /// Find path
            /// ---------
            while (toBeProcessed.Count > 0 && endPoints.Count < options.maxResults)
            {
                // Sort open stack
                if (options.enableOpenStackSorting)
                {
                    SortOpenStack(ref toBeProcessed, sortingOptions);
                }

                // Process open stack
                for (int i = toBeProcessed.Count - 1; i >= 0; i--)
                {
                    PathNode2D node = toBeProcessed[i];

                    for (int j = 7; j >= 0; j--)
                    {
                        // Get direction
                        int d = dirRectGrid2DEnumHelper[node.Dir][j];
                        if (!allowStraight && d % 2 == 1)
                        {
                            continue;
                        }
                        if (!allowDiagonal && d % 2 == 0)
                        {
                            continue;
                        }

                        // Get & validate coords
                        int newX = node.X + dirRectGrid2D[d, 0];
                        int newY = node.Y + dirRectGrid2D[d, 1];
                        if (!IsInMapBounds(newX, newY))
                        {
                            continue;
                        }

                        // Check conditions
                        PathNode2D mapNode = map[newX, newY];
                        if (mapNode.GetBool("isProcessed") && (!mapNode.GetBool("isBetterCheckEnabled") || !IsBetterThan(node, mapNode)))
                        {
                            continue;
                        }
                        if (!VerifyPassConditions(mapNode, node, d, passConditions))
                        {
                            continue;
                        }

                        // Process node
                        PathNode2D nextNode = new PathNode2D(map[newX, newY]);
                        nextNode.SetProperty("isProcessed", true);
                        nextNode.SetProperty("parent", node.GetInt("stack"));
                        nextNode.SetProperty("stack", processed.Count);
                        SetDistance(nextNode, node);
                        AssignNodeProperties(nextNode, node, d, passConditions, pathWeights);         // use this to propagate additional data like accumulated custom weights (number of direction changes, hazards encountered, etc.) from source to target node
                        processed.Add(nextNode);
                        map[newX, newY] = nextNode;

                        // Target found
                        if (nextNode.X == endX && nextNode.Y == endY)
                        {
                            endPoints.Add(nextNode);
                        }
                        else
                        {
                            toBeProcessed.Add(nextNode);
                        }
                    }

                    toBeProcessed.RemoveAt(i);
                }
            }
            /// ---------

            List <PathNode2D> path = new List <PathNode2D>();

            /// Construct path
            /// ---------
            if (endPoints.Count > 0)
            {
                SortOpenStack(ref endPoints, sortingOptions);
                int pathFound = endPoints.Count - 1;

                map[endPoints[pathFound].X, endPoints[pathFound].Y].SetProperty("isPath", true);
                path.Add(endPoints[pathFound]);

                int parent = endPoints[pathFound].GetInt("parent");
                do
                {
                    int px = processed[parent].X;
                    int py = processed[parent].Y;
                    map[px, py].SetProperty("isPath", true);
                    if (px != startX || py != startY)
                    {
                        path.Add(processed[parent]);
                    }
                    parent = processed[parent].GetInt("parent");
                } while (parent != -1);
            }
            /// ---------

            // Result
            GridPath2D result = new GridPath2D(path);

            return(result);
        }
예제 #8
0
 protected virtual bool IsBetterThan(PathNode2D a, PathNode2D b)
 {
     return((a.Dist + 1) < b.Dist);
 }
예제 #9
0
 protected virtual void AssignNodeProperties(PathNode2D node, PathNode2D parent, int d, Dictionary <string, int> passConditions, Dictionary <string, int> pathWeights)
 {
     node.Dir = d;
 }
예제 #10
0
 protected virtual void SetDistance(PathNode2D node, PathNode2D parent)
 {
     node.Dist = parent.Dist + 1;
 }
예제 #11
0
 protected virtual bool VerifyPassConditions(PathNode2D node, PathNode2D parent, int d, Dictionary <string, int> passConditions)
 {
     return(node.GetBool("isPassable"));
 }