C# 寻路,平滑移动敌人到玩家。在固体周围走动

C# Pathfinding, smooth movement enemy to player. Walk around solids

我需要一种在我的游戏中实现寻路的方法。

例如 A*Euclidean 就可以很好地解决这个问题。

我的 Tile class 有一个多维数组,它有一个矩形 对于边界和 is_solid 变量。玩家不受瓷砖的限制,可以自由移动。所以敌人会顺利找到通往玩家的路。

我已经尝试在网络上或 Whosebug 数据库中实现示例。但无济于事,我无法修改它们以用于我的项目。

得到任何您认为适合我开发游戏的方式并且可以更轻松地实施到我的游戏中的 examples/tutorials

我是在 this great article 的帮助下这样做的:

public class MyEdge//used edges and notes for my graph
{
    public int To { get; private set; }
    public int From { get; private set; }

    protected MyNode from;
    protected MyNode to;


    public MyEdge(int from, int to, MyGraph g)
    {
        From = from;
        To = to;
        this.from = g.GetNode(from);
        this.to = g.GetNode(to);
    }

    public MyNode NodeFrom()
    {
        return from;
    }

    public MyNode NodeTo()
    {
        return to;
    }
}

public class MyNode
{
    public int Index { get; private set; }
    public Vector2D Pos { get; private set; }
    public List<MyEdge> Edges { get; private set; }

    public MyNode parent = null;
    public double G = double.MaxValue;
    public double H = 0;
    public double F { get { return G + H; } }


    public MyNode(int x, int y)
    {
        Edges = new List<MyEdge>();
        Pos = new Vector2D(x, y);
        Index = -1;
    }
    public MyNode(Vector2D pos)
    {
        Edges = new List<MyEdge>();
        Pos = pos;
        Index = -1;
    }

    public MyNode(int x, int y, int idx)
    {
        Edges = new List<MyEdge>();
        Pos = new Vector2D(x, y);
        Index = idx;
    }
    public MyNode(Vector2D pos, int idx)
    {
        Edges = new List<MyEdge>();
        Pos = pos;
        Index = idx;
    }
}

注意:边有节点,节点有边。这是为了更好的性能

public List<MyNode> GetPath(Vector2D startPoint, Vector2D endPoint)
    {
        //create the open list of nodes, initially containing only our starting node
        //create the closed list of nodes, initially empty
        List<MyNode> open = new List<MyNode>();
        List<MyNode> closed = new List<MyNode>();


        //Find the starting node
        MyNode start = FindNearestNode(startPoint);
        if (start == null)
            return null;

        //Find the ending node
        MyNode end = FindNearestNode(endPoint);
        if (end == null)
            return null;

        start.G = G(start.Pos, endPoint);
        start.H = H(start.Pos, endPoint);
        open.Add(start);


        while (open.Count != 0)
        {
            //consider the best node in the open list (the node with the lowest f value)
            double d = open.Min(x => x.F);
            MyNode curr = open.First(x => x.F.CompareTo(d) == 0);

            closed.Add(curr);
            open.Remove(curr);

            //If current node is goal              
            if (curr == end)
            {
                //Loop over the parents to get the path
                List<MyNode> ns = new List<MyNode>();
                MyNode n = end;
                ns.Add(n);
                while (n != start)
                {
                    ns.Add(n.parent);
                    n = n.parent;
                }
                ns.Reverse();
                return ns;
            }

            for (int i = 0; i < curr.Edges.Count; i++)
            {
                MyNode possibleNeigbour = curr.Edges[i].NodeTo();
                if (closed.Contains(possibleNeigbour))
                {
                    //ignore it
                }
                else if (!open.Contains(possibleNeigbour))
                {
                    possibleNeigbour.G = G(possibleNeigbour.Pos, endPoint);
                    possibleNeigbour.H = H(possibleNeigbour.Pos, endPoint);
                    possibleNeigbour.parent = curr;
                    open.Add(possibleNeigbour);
                }
                else if(open.Contains(possibleNeigbour))
                {
                    if (possibleNeigbour.G < curr.G)
                    {
                        possibleNeigbour.parent = curr;
                    }
                }
            }
        }
        
        return null;
    }