Java A*路径查找算法运行非常慢
我目前正在为android开发我的第一款游戏,也是我第一次创建a*路径查找算法。这是一个2d游戏。我已经创建了一个包含此算法的敌人(即,每帧运行一次),它会将性能从60fps降低到1-2fps。显然有些地方出了大问题,我试着在网上寻找解决方案,但还没有找到答案。以下是我的寻路课程:Java A*路径查找算法运行非常慢,java,performance,2d,a-star,Java,Performance,2d,A Star,我目前正在为android开发我的第一款游戏,也是我第一次创建a*路径查找算法。这是一个2d游戏。我已经创建了一个包含此算法的敌人(即,每帧运行一次),它会将性能从60fps降低到1-2fps。显然有些地方出了大问题,我试着在网上寻找解决方案,但还没有找到答案。以下是我的寻路课程: package com.frog8fly.nunca; 导入com.badlogic.gdx.utils.Array 导入java.util.Comparator 公共类寻路{ private static Nod
package com.frog8fly.nunca;
导入com.badlogic.gdx.utils.Array
导入java.util.Comparator
公共类寻路{
private static Node[][] grid;
private static NodeComparator nodeComparator;
static{
nodeComparator = new NodeComparator();
}
public static class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node node1, Node node2) {
if(node1.F > node2.F){
return 1;
}
else if(node1.F < node2.F){
return -1;
}
else{
return 0;
}
}
}
public static Array<Node> findPath(Node start, Node finish, Node[][] _grid) {
Array<Node> path = new Array<Node>();
Array<Node> openList = new Array<Node>();
Array<Node> closedList = new Array<Node>();
grid = _grid;
Node currentNode = start;
currentNode.parent = null;
currentNode.G = 0;
currentNode.H = getHeuristic(currentNode, finish);
openList.add(currentNode);
System.out.println("PATHFINDING STARTED ||| startPos : " + start.position + " finishPos : " + finish.position);
while (openList.size > 0) {
//Sorts open nodes lowest F value to heighest
openList.sort(nodeComparator);
currentNode = openList.first();
//If path is found, return
if (currentNode == finish) {
System.out.println("PATH FOUND...RETURNING -gat5");
return constructPath(currentNode);
}
openList.removeValue(currentNode, true);
closedList.add(currentNode);
int counter = 0;
for (Node neighbor : getNeighbors(currentNode)) {
if (!closedList.contains(neighbor, true)) { //If neighbor not in closed list
if(neighbor != null) { //If neighbor not wall
if(counter == 4){
counter++;
}
int movementCost = checkMovementCost(counter);
if (openList.contains(neighbor, true)) {
if (currentNode.G + movementCost < neighbor.G) {
neighbor.parent = currentNode;
}
} else {
openList.add(neighbor);
neighbor.parent = currentNode;
neighbor.H = getHeuristic(currentNode, finish);
neighbor.G = neighbor.parent.G + movementCost;
}
counter++;
}
}
}
}
System.out.println("NO PATH FOUND RETURNING...");
path.add(start);
return path;
}
private static int checkMovementCost(int neighbor) {
int movementCost = 0;
switch (neighbor) {
//Diagonal
case 0:
case 2:
case 6:
case 8:
movementCost = 16;
break;
//Not Diagonal
case 1:
case 3:
case 5:
case 7:
movementCost = 10;
break;
}
return movementCost;
}
public static Array<Node> constructPath(Node finish) {
Array<Node> pathNodes = new Array<Node>();
Node currentNode = finish;
pathNodes.add(currentNode);
while (currentNode.parent != null) {
currentNode = currentNode.parent;
pathNodes.add(currentNode);
System.out.println("Anotha");
}
pathNodes.reverse();
return pathNodes;
}
private static float getHeuristic(Node start, Node finish){
int H = 0;
System.out.println(start.position);
System.out.println(finish.position);
H += Math.abs(start.position.x - finish.position.x);
H += Math.abs(start.position.y - finish.position.y);
return H;
}
private static Array<Node> getNeighbors(Node node){
Array<Node> neighbors = new Array<Node>();
int x = (int)node.position.x;
int y = (int)node.position.y;
if(x - 1 > 0 && x - 1 < grid.length && y + 1 < grid.length && y + 1 > 0){
neighbors.add(grid[x - 1][y + 1]);
}
else{
neighbors.add(null);
}
if(x > 0 && x < grid.length && y + 1 < grid.length && y + 1 > 0){
neighbors.add(grid[x][y + 1]);
}
else{
neighbors.add(null);
}
if(x + 1 > 0 && x + 1 < grid.length && y + 1 < grid.length && y + 1 > 0){
neighbors.add(grid[x + 1][y + 1]);
}
else{
neighbors.add(null);
}
if(x - 1 > 0 && x - 1 < grid.length && y < grid.length && y > 0){
neighbors.add(grid[x - 1][y]);
}
else{
neighbors.add(null);
}
if(x > 0 && x < grid.length && y < grid.length && y > 0){
neighbors.add(grid[x][y]);
}
else{
neighbors.add(null);
}
if(x + 1 > 0 && x + 1 < grid.length && y < grid.length && y > 0){
neighbors.add(grid[x + 1][y]);
}
else{
neighbors.add(null);
}
if(x - 1 > 0 && x - 1 < grid.length && y - 1 < grid.length && y - 1> 0){
neighbors.add(grid[x - 1][y - 1]);
}
else{
neighbors.add(null);
}
if(x > 0 && x < grid.length && y - 1 < grid.length && y - 1 > 0){
neighbors.add(grid[x][y - 1]);
}
else{
neighbors.add(null);
}
if(x + 1 > 0 && x + 1 < grid.length && y - 1 < grid.length && y - 1 > 0){
neighbors.add(grid[x + 1][y - 1]);
}
else{
neighbors.add(null);
}
for(Node nodee : neighbors){
if(node.position != null){
}
}
return neighbors;
}
你的启发式函数是错误的。我相信你想要:
H += Math.abs(start.position.x - finish.position.x);
H += Math.abs(start.position.y - finish.position.y);
使用不正确的启发式肯定会将*搜索拖慢到爬行,因为它基本上会将其减少到广度优先搜索。您的启发式函数是错误的。我相信您希望:
H += Math.abs(start.position.x - finish.position.x);
H += Math.abs(start.position.y - finish.position.y);
使用不正确的启发式搜索肯定会使*搜索变慢为爬行,因为它基本上会将*搜索简化为广度优先搜索。A*本质上很慢。您必须分析代码以确定CPU时间花在哪里,并对其进行优化(通常,这不是一个编写问题,而是一个设计问题).游戏中经常出现这种情况。-用于(节点节点:邻居)的
循环不编译,顺便说一句。感谢您的回复,您会推荐什么样的优化?据我所知,由于我只在一帧内运行一次此算法,它真的会有这么大的不同吗?这取决于您的CPU时间花在哪里。它可能包括更改您正在使用的列表实现,或者在开关列表中如果可以确定相关区域而不影响算法的行为,则可以将s转换为数组,或事件减少适用图形的大小。最后,它可能包括执行双a*(从当前位置和目标位置开始,在它们相遇时停止)而不是一个单独的。一旦一个框架不能告诉我多少:你的图形有多大和复杂?@Shlublu我的图形是100 x 100。好的,没有那么大,但完全相连。@AustinD是对的,但已经提出了一个类似的问题,它得到的答案适用于这里。a*本质上很慢。你必须分析你的代码以确定CP的位置花费时间,并对其进行优化(通常,这不是一个写作问题,而是一个设计问题)。游戏通常就是这样。-的(Node nodee:neights)
循环不编译,顺便说一句。感谢您的回复,您会推荐什么样的优化?据我所知,由于我只在一帧内运行一次此算法,它真的会有这么大的不同吗?这取决于您的CPU时间花在哪里。它可能包括更改您正在使用的列表实现,或者在开关列表中如果可以确定相关区域而不影响算法的行为,则可以将s转换为数组,或事件减少适用图形的大小。最后,它可能包括执行双a*(从当前位置和目标位置开始,在它们相遇时停止)而不是一个。一旦一个框架不能告诉我多少:你的图形有多大和复杂?@Shlublu我的图形是100 x 100。好的,没有那么大,但完全相连。@AustinD是对的,但已经提出了一个类似的问题,得到的答案适用于这里。谢谢你的回答!修复了启发式,但仍然像以前一样慢:\@Wyatt,方向4和方向5的移动成本为零。执行return(neighbor==0 | |(neighbor&1==0))之类的操作会更安全/更容易/可能更便宜16:10;
如果0代表北方,我怀疑10和16是颠倒的。@Shlublu 4不使用,因为它是中心。5的移动成本应该是10,不是吗?0是左上角,1是右上角,2是右上角,3是右中角,依此类推……4是我说的中心正方形,所以它没有被选中。@Wyatt好的,忘记我说的了。我误解了d移动地图!感谢您的回复!修复了启发式,但仍然像以前一样慢:\@Wyatt,方向4和方向5的移动成本为零。执行return(neighbor==0 | |(neighbor&1==0))这样的操作会更安全/更容易/可能更便宜16:10;
如果0代表北方,我怀疑10和16是颠倒的。@Shlublu 4不使用,因为它是中心。5的移动成本应该是10,不是吗?0是左上角,1是右上角,2是右上角,3是右中角,依此类推……4是我说的中心正方形,所以它没有被选中。@Wyatt好的,忘记我说的了。我误解了d运动地图!