Hey,
my AStar implementation is sooo slow, maybe someone could look over it and give some hints?
It works basically OK for small paths, but when I calculate a path on my Map from say 500,500 to 400,400 (with no obstacles in between) it takes like 12 seconds, which is far too long.
Using a PriorityQueue is my latest test, but didn’t greatly (at all?) improve performance, unfortunately.
Semi-long wall of code incoming ->
public class PathFind {
private World world;
public Node thePath;
public Node oneStep;
public PriorityQueue<Node> open_list = new PriorityQueue<Node>();
public PriorityQueue<Node> closed_list = new PriorityQueue<Node>();
public long timeDelta;
public PathFind(World world) {
this.world = world;
thePath = new Node();
oneStep = new Node();
}
public void calculatePath(int startX, int startY, int tarX, int tarY) {
timeDelta = System.nanoTime();
open_list.clear();
closed_list.clear();
Node n = new Node();
n.posX = startX;
n.posY = startY;
n.parent = null;
n.g = 1;
//n.h = Math.abs( startX - tarX + startY - tarY );
n.h = (int)Math.sqrt( Math.abs(Math.pow(startX-tarX,2)) + Math.abs(Math.pow(startY-tarY,2)));
n.f = n.g + n.h;
open_list.add(n);
while( !open_list.isEmpty()) {
//Node current = getLowestFScore(open_list);
Node current = open_list.poll();
if( isInList(current, closed_list))
continue;
if( current.posX == tarX && current.posY == tarY) {
thePath = current;
while( current.parent.parent != null ) {
current = current.parent;
}
oneStep = current;
break;
}
if( world.getWorldDataAt(current.posX-1, current.posY).walkAble == true) { // tile left of current
Node next = new Node();
next.posX = current.posX-1;
next.posY = current.posY;
next.parent = current;
calculateCost(next, next.posX, next.posY, tarX, tarY);
if( !isInList(next, closed_list))
open_list.add(next);
}
if( world.getWorldDataAt(current.posX+1, current.posY).walkAble == true) { // tile right of current
Node next = new Node();
next.posX = current.posX+1;
next.posY = current.posY;
next.parent = current;
calculateCost(next, next.posX, next.posY, tarX, tarY);
if( !isInList(next, closed_list))
open_list.add(next);
}
if( world.getWorldDataAt(current.posX, current.posY-1).walkAble == true) { // tile top of current
Node next = new Node();
next.posX = current.posX;
next.posY = current.posY-1;
next.parent = current;
calculateCost(next, next.posX, next.posY, tarX, tarY);
if( !isInList(next, closed_list))
open_list.add(next);
}
if( world.getWorldDataAt(current.posX, current.posY+1).walkAble == true) { // tile bot of current
Node next = new Node();
next.posX = current.posX;
next.posY = current.posY+1;
next.parent = current;
calculateCost(next, next.posX, next.posY, tarX, tarY);
if( !isInList(next, closed_list))
open_list.add(next);
}
closed_list.add(current);
//open_list.remove(current);
}
timeDelta = System.nanoTime() - timeDelta;
}
private boolean isInList(Node next, PriorityQueue<Node> closed_list) {
for( Node n : closed_list )
{
if( n.posX == next.posX &&
n.posY == next.posY )
return true;
}
return false;
}
private Node getLowestFScore(PriorityQueue<Node> open_list) {
Node lowest = open_list.peek();
for( Node n : open_list ) {
if( lowest.f > n.f )
lowest = n;
if( lowest.f == n.f )
if( lowest.g > n.g )
lowest = n;
}
return lowest;
}
public void calculateCost(Node n, int startX, int startY, int tarX, int tarY) {
n.g = n.parent.g + 1;
//n.h = Math.abs( startX - tarX + startY - tarY );
n.h = (int)Math.sqrt( Math.abs(Math.pow(startX-tarX,2)) + Math.abs(Math.pow(startY-tarY,2)));
n.f = n.g + n.h;
}
public class Node implements Comparable<Node>{
public int posX;
public int posY;
public int f;
public int g;
public int h;
public Node parent;
@Override
public int compareTo(Node o) {
if( f > o.f )
return 1;
if( f < o.f )
return -1;
else return 0;
}
}
}