等距切片的C#A *寻路

时间:2016-03-21 19:09:26

标签: c#

我正在使用XNA中的Isometric游戏,并使用A *版本进行寻路。

它运作良好,但我在找对角线移动时找到最佳路线有问题。而不是沿对角线(最短的路线)返回的路径直接向上然后穿过。

我一直在网上阅读,但无法弄清楚如何改变它。我想我需要改变预测距离,而不是* 10,对于直接在上方或下方的瓷砖,这将是* 14,但这似乎不起作用......

 public List<Point> Pathfind(Point start, Point end)
    {
        // nodes that have already been analyzed and have a path from the start to them
        var closedSet = new List<Point>();
        // nodes that have been identified as a neighbor of an analyzed node, but have
        // yet to be fully analyzed
        var openSet = new List<Point> { start };
        // a dictionary identifying the optimal origin point to each node. this is used
        // to back-track from the end to find the optimal path
        var cameFrom = new Dictionary<Point, Point>();
        // a dictionary indicating how far each analyzed node is from the start
        var currentDistance = new Dictionary<Point, int>();
        // a dictionary indicating how far it is expected to reach the end, if the path
        // travels through the specified node.
        var predictedDistance = new Dictionary<Point, float>();
        // initialize the start node as having a distance of 0, and an estmated distance
        // of y-distance + x-distance, which is the optimal path in a square grid that
        // doesn't allow for diagonal movement
        currentDistance.Add(start, 0);
        predictedDistance.Add(
        start,
        0 + +Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y)
        );

        // if there are any unanalyzed nodes, process them
        while (openSet.Count > 0)
        {
            // get the node with the lowest estimated cost to finish
            var current = (from p in openSet orderby predictedDistance[p] ascending select p).First();
            // if it is the finish, return the path
            if (current.X == end.X && current.Y == end.Y)
            {
                // generate the found path
                return ReconstructPath(cameFrom, end);
            }
            // move current node from open to closed
            openSet.Remove(current);
            closedSet.Add(current);
            // process each valid node around the current node
            foreach (var neighbor in GetNeighborNodes(current))
            {
                var tempCurrentDistance = currentDistance[current] + 1;
                // if we already know a faster way to this neighbor, use that route and
                // ignore this one
                if (closedSet.Contains(neighbor) && tempCurrentDistance >= currentDistance[neighbor])
                {
                    continue;
                }
                // NOT PASSABLE
                if (Globals.mapArray[neighbor.X,neighbor.Y].Passable == false)
                {
                    continue;
                }
                // if we don't know a route to this neighbor, or if this is faster,
                // store this route
                if (!closedSet.Contains(neighbor)|| tempCurrentDistance < currentDistance[neighbor])
                {
                    if (cameFrom.Keys.Contains(neighbor))
                    {
                        cameFrom[neighbor] = current;
                    }
                    else
                    {
                        cameFrom.Add(neighbor, current);
                    }

                    currentDistance[neighbor] = tempCurrentDistance + 10;
                    predictedDistance[neighbor] = currentDistance[neighbor] + Math.Abs(neighbor.X - end.X) + Math.Abs(neighbor.Y - end.Y);
                    predictedDistance[neighbor] = predictedDistance[neighbor] * 10;

                    // if this is a new node, add it to processing
                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                }
            }
        }
        // unable to figure out a path, abort.
        List<Point> noPath = new List<Point>();
        Point n = new Point();
        n.X = -1; n.Y = -1;
        noPath.Add(n);
        return noPath;
    }

private IEnumerable<Point> GetNeighborNodes(Point node)
    {
        var nodes = new List<Point>();
        if (node.X > 0 && node.Y > 0 && node.X < Globals.xSize - 1 && node.Y < Globals.ySize - 1)
        {
            // up
            nodes.Add(new Point(node.X, node.Y - 2));             
            // right
            nodes.Add(new Point(node.X + 1, node.Y));
            // down
            nodes.Add(new Point(node.X, node.Y + 2));
            // left
            nodes.Add(new Point(node.X - 1, node.Y));

            // DIAGONAL
            if (node.Y % 2 == 0)
            {
                // UP LEFT
                nodes.Add(new Point(node.X, node.Y - 1));                
                // UP RIGHT
                nodes.Add(new Point(node.X - 1, node.Y - 1));
                // DOWN LEFT
                nodes.Add(new Point(node.X-1, node.Y + 1));
                // DOWN RIGHT
                nodes.Add(new Point(node.X, node.Y + 1));
            }
            else
            {
                // UP LEFT
                nodes.Add(new Point(node.X+1, node.Y - 1));
                // UP RIGHT
                nodes.Add(new Point(node.X, node.Y - 1));
                // DOWN LEFT
                nodes.Add(new Point(node.X, node.Y + 1));
                // DOWN RIGHT
                nodes.Add(new Point(node.X+1, node.Y + 1)); 
            }
        }

        return nodes;
    }

0 个答案:

没有答案