自顶向下游戏中多线程A *寻路冻结

时间:2015-02-26 01:48:15

标签: java multithreading path-finding a-star

我一直在做一个自上而下的射击游戏,当我产生多个HostileEntity时(任何"敌人"的超类,它包含所有的寻路功能) ),敌人要么:

  • 不要从游戏开始移动
  • 游戏开始后开始移动,但一旦移动播放器,所有内容都会冻结。

我认为在我的Algorithm类中它会冻结在这个函数

public Path backtrackPath(Node fromNode) {
    Path path = new Path();

    while(fromNode.getPreviousNode() != null) { 
        path.prependWaypoint(fromNode);
        fromNode = fromNode.getPreviousNode();
    }

    reset(); //Resets all of the previousNodes to null
             //so the next iteration will(should) work correctly
    return path;
}

从方法fromNode中检索findPath,并且是路径寻找算法的"目标",即播放器的坐标。问题在于它来自,Node A,previousNodeNode B,而Node B有previousNodeNode A,所以while循环无限地来回运行。

一片findPath()

if(neighborIsBetter) { //if the next neighbor node is closer to the goal then current node being checked
    neighbor.setPreviousNode(current); //connects the current Node to the better neighbor Node
    neighbor.setDistanceFromStart(neighborDistanceFromStart);
    neighbor.setHeuristic(getManhattanDistance(neighbor.getCol(), neighbor.getRow(), goalX, goalY)); 

}

我相信这可能是因为,因为每个敌人只会在玩家的坐标自上一次寻路以来发生变化时找到路径,一旦玩家移动,每个敌人的路径都会在同一时间找到, {1}},并对相同的findPath()进行计算,混合以前的节点。

如何防止这种情况发生? 我想到了,而不是在Node中设置前一个节点,只需将其添加到要返回的路径中。

上面测试过并且没有用,因为我相信有多个findPath() neighbor"更好"比当前正在计算的节点,导致相同的Node在路径中多次。

1 个答案:

答案 0 :(得分:1)

您在每个路径节点(特定字符路径上的上一个节点)中保存特定于字符的信息。问题是多个字符可能正在使用路径节点,并且每个节点一次只能容纳一个前一个节点,因此如果多个字符使用它,则数据将混淆。

现在,如果你想保持设计的原样,你可以使每个节点都是线程安全的,阻止其他字符修改它直到当前字符完成。我不会在这里深入研究同步,你可以在这里找到这些信息:http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html

然而,我建议您稍微更改设计。现在,您希望存储“以前的节点”以保留角色路径的历史记录。我会在每个字符中存储一个路径对象,它将累积该字符所处的每个节点。这样每个字符都存储它自己的数据,每个节点存储它自己的数据,不是特定于任何一个字符。这样,当你想要你的回溯路径时,你可以使用你一直在构建的成员变量。

因此,假设您的Path pathHistory;课程中有变量HostileEntity。每次实体设置新的目标节点时,都可以将当前节点添加到pathHistory变量中。如果它超过某种最大阈值,你也可以删除路径历史中真正的旧节点,你也可以在你不再需要它时清除整个节点。它与在桌面程序中维护撤消历史记录非常相似。

您可以简单地通过说:

来合并这个新设计
public Path backtrackPath() {
    return pathHistory;
}

或者如果你想使用fromNode参数,你基本上会搜索pathHistory该节点,然后返回该节点后面的所有内容的路径,否则根本不返回任何路径。

为了告诉实体走向目标点,您甚至不需要路径历史记录,只需要一种算法来查找下一个目标节点并将其存储在实体中。

祝你好好设计你的寻路系统!我希望这个答案很有帮助。