This commit is contained in:
parent
0f98073f0e
commit
e038b83732
2 changed files with 0 additions and 294 deletions
|
|
@ -1,294 +0,0 @@
|
|||
package ei.game.algo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* A* path finder across a tile map
|
||||
*
|
||||
* @author Kevin Glass
|
||||
*/
|
||||
public strictfp class AStarPathFinder implements PathFinder {
|
||||
/** The map being searched */
|
||||
private TileMap map;
|
||||
/** The set describing the properties of the tiles on the map */
|
||||
private TileSet set;
|
||||
/** The distance from the end point each point on the map is */
|
||||
private int[] distance;
|
||||
/** The maximum search depth before giving up */
|
||||
private int maxsearch;
|
||||
/** The starting x coordinate */
|
||||
private int sx;
|
||||
/** The starting y coordiante */
|
||||
private int sy;
|
||||
/** The callback notified as nodes are processed */
|
||||
private PathFinderCallback callback;
|
||||
/** The currently open nodes */
|
||||
private ArrayList<Step> open = new ArrayList<Step>();
|
||||
|
||||
/**
|
||||
* Create a new path finder based on the A* algorithm
|
||||
*
|
||||
* @param map The map being searched
|
||||
* @param set The set describing the tiles on the map
|
||||
*/
|
||||
public AStarPathFinder(TileMap map,TileSet set) {
|
||||
this(map,set,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new path finder based on the A* algorithm
|
||||
*
|
||||
* @param map The map being searched
|
||||
* @param set The set describing the tiles on the map
|
||||
* @param callback The callback notified as nodes are traversed
|
||||
*/
|
||||
public AStarPathFinder(TileMap map,TileSet set,PathFinderCallback callback) {
|
||||
this.map = map;
|
||||
this.set = set;
|
||||
this.callback = callback;
|
||||
distance = new int[map.getMapWidth()*map.getMapHeight()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.util.map.PathFinder#reset()
|
||||
*/
|
||||
public void reset() {
|
||||
open.clear();
|
||||
Arrays.fill(distance,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.util.map.PathFinder#getSearchData()
|
||||
*/
|
||||
public int[] getSearchData() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.util.map.PathFinder#findPath(int, int, int, int, int)
|
||||
*/
|
||||
public synchronized Path findPath(int sx,int sy,int dx,int dy,int maxsearch) {
|
||||
this.sx = sx;
|
||||
this.sy = sy;
|
||||
|
||||
this.maxsearch = maxsearch;
|
||||
|
||||
Step step = new Step(null,dx,dy);
|
||||
open.add(step);
|
||||
|
||||
return processNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the nodes of the search graph
|
||||
*
|
||||
* @return The path found or null if no path could be found
|
||||
*/
|
||||
private Path processNodes() {
|
||||
Step step = findBest();
|
||||
|
||||
while (!step.is(sx,sy)) {
|
||||
for (int x=-1;x<2;x++) {
|
||||
for (int y=-1;y<2;y++) {
|
||||
if ((x != 0) || (y != 0)) {
|
||||
int xp = step.x + x;
|
||||
int yp = step.y + y;
|
||||
|
||||
if (!checkDiaganolBlock(step.x,step.y,x,y)) {
|
||||
if (validNode(xp,yp)) {
|
||||
open.add(new Step(step,xp,yp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step = findBest();
|
||||
if (step == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
distance[step.x+(step.y*map.getMapWidth())] = 1;
|
||||
callback.fireNode(step.x,step.y);
|
||||
}
|
||||
}
|
||||
|
||||
Path path = new Path();
|
||||
|
||||
while (step.parent != null) {
|
||||
path.addPoint(step.x,step.y);
|
||||
step = step.parent;
|
||||
}
|
||||
path.addPoint(step.x,step.y);
|
||||
|
||||
System.out.println();
|
||||
for(int y=0; y<map.getMapHeight() ;y++){
|
||||
System.out.println();
|
||||
for(int x=0; x<map.getMapWidth() ;x++){
|
||||
System.out.print(map.getTileAt(x, y, 0));
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a particular move is actually valid
|
||||
*
|
||||
* @param x The original x coordinate
|
||||
* @param y The original y coordinate
|
||||
* @param xo The x direction of movement
|
||||
* @param yo The y direction of movement
|
||||
* @return True if the move is valid
|
||||
*/
|
||||
private boolean checkDiaganolBlock(int x,int y,int xo,int yo) {
|
||||
if ((xo == 0) || (yo == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isBlocked(x+xo,y)) {
|
||||
return true;
|
||||
}
|
||||
if (isBlocked(x,y+yo)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a particular node on the graph is valid to check
|
||||
*
|
||||
* @param x The x position of the node to check
|
||||
* @param y The y position of the node to check
|
||||
* @return True if the node is valid to evaluate
|
||||
*/
|
||||
private boolean validNode(int x,int y) {
|
||||
if (isBlocked(x,y)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return distance[x+(y*map.getMapWidth())] == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the best open state currently available, i.e. the
|
||||
* best direction to move in
|
||||
*
|
||||
* @return The best step to take or null if there are no more
|
||||
* steps left (no path)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Step findBest() {
|
||||
Collections.sort(open);
|
||||
|
||||
if (open.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
Step best = (Step) open.get(0);
|
||||
best.count++;
|
||||
if ((best.count > 9) || (best.depth > maxsearch)) {
|
||||
open.remove(best);
|
||||
return findBest();
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the heuristic for a particular node
|
||||
*
|
||||
* @param x The x position of the node to evaluate
|
||||
* @param y The y position of the node to evaluate
|
||||
* @return The heuristic for the specified node
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private int evalH(int x,int y) {
|
||||
return Math.abs(sx-x) + Math.abs(sy-y);
|
||||
}
|
||||
|
||||
/**
|
||||
* A step on the search path
|
||||
*
|
||||
* @author Kevin Glass
|
||||
*/
|
||||
private class Step implements Comparable {
|
||||
/** The x position of this step */
|
||||
public int x;
|
||||
/** The y position of this step */
|
||||
public int y;
|
||||
/** The heuristic for this step's node */
|
||||
public int h;
|
||||
/** The number of times this step has been used as a source */
|
||||
public int count;
|
||||
/** The depth of this search */
|
||||
public int depth;
|
||||
/** The parent step this step was spawned from */
|
||||
public Step parent;
|
||||
|
||||
/**
|
||||
* Create a new step
|
||||
*
|
||||
* @param parent The step we came from
|
||||
* @param x The x position we've moved to
|
||||
* @param y The y position we've moved to
|
||||
*/
|
||||
public Step(Step parent,int x,int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = parent;
|
||||
if (parent != null) {
|
||||
depth = parent.depth+1;
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
h = Math.abs(sx-x) + Math.abs(sy-y);
|
||||
|
||||
if (depth <= maxsearch) {
|
||||
distance[x+(y*map.getMapWidth())] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Like an equals method, only for the data inside
|
||||
*
|
||||
* @param x The x position to check against
|
||||
* @param y The y position to check against
|
||||
* @return True if this steps position is that specified
|
||||
*/
|
||||
public boolean is(int x,int y) {
|
||||
return (x == this.x) && (y == this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
public int compareTo(Object o) {
|
||||
return h - ((Step) o).h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a particular location on the map blocks movement
|
||||
*
|
||||
* @param x The x location to check
|
||||
* @param y The y location to check
|
||||
* @return True if the locaiton is blocked
|
||||
*/
|
||||
public boolean isBlocked(int x,int y) {
|
||||
if(x == sx && y == sy){
|
||||
return false;
|
||||
}
|
||||
if (map.isBlocked(x,y)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return set.blocksMovement(map.getTileAt(x,y,0));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue