首页 文章

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

提问于
浏览
1

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

  • 不要从游戏开始移动

  • 游戏开始后开始移动,但是一旦我移动玩家,所有都会冻结 .

我已经想到位于我的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 中检索,并且是路径查找算法的播放器坐标"goal" . 错误是它来自,例如 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));

}

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

我怎样才能防止这种情况发生?我想到了,而不是在findPath()中设置前一个节点,只需将它添加到要返回的路径中 .

在上面测试并且没有工作,因为我相信有多个 neighbor Node 比当前正在计算的节点"better",导致相同的 Node 在路径中多次 .

1 回答

  • 1

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

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

    但是,我建议您稍微更改设计 . 现在,您希望存储"previous nodes"以保留字符' paths. I would store a path object in each character that would accumulate each node the character has been to. That way each character stores it'自己的数据的历史记录,并且每个节点存储它自己的数据,而不是特定于任何一个字符 . 这样,当你想要你的回溯路径时,你可以只使用你一直在构建的成员变量 .

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

    您可以简单地通过以下方式合并这个新设计:

    public Path backtrackPath() {
        return pathHistory;
    }
    

    或者,如果要使用 fromNode 参数,您实际上将搜索该节点的 pathHistory ,然后返回该节点后面的所有内容的路径,否则根本不返回任何路径 .

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

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

相关问题