fixed some buggs but meny more remain
This commit is contained in:
parent
b2708fcd9c
commit
91c3e77465
2 changed files with 324 additions and 2 deletions
318
src/ei/game/algo/AStarPathFinder.java
Normal file
318
src/ei/game/algo/AStarPathFinder.java
Normal file
|
|
@ -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<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();
|
||||||
|
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<Vector2i> lol = path.getArray();
|
||||||
|
for(int y=0; y<map.getMapHeight() ;y++){
|
||||||
|
System.out.println();
|
||||||
|
for(int x=0; x<map.getMapWidth() ;x++){
|
||||||
|
for(int i=0; i<lol.size() ;i++){
|
||||||
|
if(lol.get(i).getX() == x && lol.get(i).getY() == y){
|
||||||
|
System.out.print('*');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(i==lol.size()-1){
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -329,14 +329,18 @@ public abstract class Unit extends GameEntity{
|
||||||
}
|
}
|
||||||
else if(path != null && !path.isEmpty()){
|
else if(path != null && !path.isEmpty()){
|
||||||
Vector2i temp = path.poll();
|
Vector2i temp = path.poll();
|
||||||
|
if(temp.getX() == oldPos.getX() && temp.getY() == oldPos.getY()){
|
||||||
|
temp = path.poll();
|
||||||
|
}
|
||||||
if(InGameState.getMap().isPosEmpty(temp.getX(), temp.getY())){
|
if(InGameState.getMap().isPosEmpty(temp.getX(), temp.getY())){
|
||||||
oldVect = new Vector2i((int)moveTo.getX(), (int)moveTo.getY());
|
oldVect = new Vector2i((int)moveTo.getX(), (int)moveTo.getY());
|
||||||
moveTo = Map.getPixelByPos(temp.getX(), temp.getY());
|
moveTo = Map.getPixelByPos(temp.getX(), temp.getY());
|
||||||
setPos(temp.getX(), temp.getY());
|
setPos(temp.getX(), temp.getY());
|
||||||
}
|
}
|
||||||
else if(!path.isEmpty()){
|
else if(!path.isEmpty()){
|
||||||
//removed because its making problem whit the bomber unit
|
//path = null;
|
||||||
//move(false, path.getLast().getX(), path.getLast().getY());
|
System.out.println("lol: "+temp);
|
||||||
|
move(false, path.getLast().getX(), path.getLast().getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue