diff --git a/src/ei/game/algo/AStarPathFinder.java b/src/ei/game/algo/AStarPathFinder.java new file mode 100644 index 0000000..cdb935e --- /dev/null +++ b/src/ei/game/algo/AStarPathFinder.java @@ -0,0 +1,318 @@ +package ei.game.algo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +import ei.engine.math.Vector2i; + +/** + * A* path finder across a tile map + * + * @author Kevin Glass + */ +public strictfp class AStarPathFinder implements PathFinder { + /** To find the nearest path if destination is not avaliable */ + private static boolean findNearest = true; + /** 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 open = new ArrayList(); + + /** + * 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(); + Step nearest = null; + + 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)) { + Step s = new Step(step,xp,yp); + open.add(s); + if(nearest == null || s.h < nearest.h){ + nearest = s; + } + } + } + } + } + } + + step = findBest(); + if (step == null) { + if(nearest != null && findNearest){ + step = nearest; + break; + } + else{ + 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(); + ArrayList lol = path.getArray(); + for(int y=0; y 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)); + } +} diff --git a/src/ei/game/scene/units/Unit.java b/src/ei/game/scene/units/Unit.java index 3483afc..61013cd 100644 --- a/src/ei/game/scene/units/Unit.java +++ b/src/ei/game/scene/units/Unit.java @@ -329,14 +329,18 @@ public abstract class Unit extends GameEntity{ } else if(path != null && !path.isEmpty()){ Vector2i temp = path.poll(); + if(temp.getX() == oldPos.getX() && temp.getY() == oldPos.getY()){ + temp = path.poll(); + } if(InGameState.getMap().isPosEmpty(temp.getX(), temp.getY())){ oldVect = new Vector2i((int)moveTo.getX(), (int)moveTo.getY()); moveTo = Map.getPixelByPos(temp.getX(), temp.getY()); setPos(temp.getX(), temp.getY()); } else if(!path.isEmpty()){ - //removed because its making problem whit the bomber unit - //move(false, path.getLast().getX(), path.getLast().getY()); + //path = null; + System.out.println("lol: "+temp); + move(false, path.getLast().getX(), path.getLast().getY()); } } else{