you say it's so complicated to implement a path-finding algorithm, but it isn't...
and what's even better, once you have implemented one you can use that algorithm whenever needed again...
i can provide you with an simple one (A* it is - and it is easy) and it's so open you can use it on hexfields, squared fields or even on cubes...
private ArrayList<Node> oList = new ArrayList<Node>(); //open list
private ArrayList<Node> cList = new ArrayList<Node>(); //closed list
public ArrayList<Point> getShortestPath(
Point startPoint, Monster walker, StaticMap map,
Point targetPoint, int maxPathLength) {
int xs = startPoint.x;
int ys = startPoint.y;
//int zs = startPoint.z;
int xe = targetPoint.x;
int ye = targetPoint.y;
//int ze = targetPoint.z;
oList.clear();
cList.clear();
Node start = new Node(xs,ys); //Node start = new Node(xs,ys, zs); //
Node end = new Node(xe, ye); //Node end = new Node(xs,ys, zs); //
oList.add(start);
boolean noWayFound = false;
while(true){
Node current = getLeastF(oList);
if (current == null){
noWayFound = true;
break;
}
if (current.isSamePos(end) ){
noWayFound = false;
end.from = current.from;
break;
}
//this is just an abortion criteria if you can't
//guarantee a shortest path
if (current.g > maxPathLength*10){
noWayFound = true;
break;
}
oList.remove(current);
cList.add(current);
expandNode(current, map, walker, end);
}
ArrayList<Point> path = new ArrayList<Point>();
if (!noWayFound){
Node n = end;
while(n != null){
path.add(new Point(n.x, n.y) );
//path.add(new Point(n.x, n.y, n.z) );
n = n.from;
}
}
return path;
}
what's different on any map is expandNode
... this implementation depends on your map... it looks at the current node and looks into all neighbours (4 on a real squared map, 8 on a semi squared map, 6 on a hex map and also 6 on a 3d squared map )...
private void expandNode(Node current, StaticMap map, Monster walker, Node end) {
Node nNode = new Node(current.x, current.y-1);
Node eNode = new Node(current.x+1, current.y);
Node sNode = new Node(current.x, current.y+1);
Node wNode = new Node(current.x-1, current.y);
//Node upNode = new Node(current.x, current.y, current.z-1);
//Node nownNode = new Node(current.x, current.y, current.z+1);
if (checkIsPassable(nNode, walker, staticMap) ){ //true if you can go north
addIfRequired(nNode, current, end, 10); //10 is the walking cost
}
if (checkIsPassable(eNode, walker, staticMap) ){
addIfRequired(eNode, current, end, 10);
}
if (checkIsPassable(sNode, walker, staticMap) ){
addIfRequired(sNode, current, end, 10);
}
if (checkIsPassable(wNode, walker, staticMap) ){
addIfRequired(wNode, current, end, 10);
}
//if (checkIsPassable(upNode, walker, staticMap) ){
// addIfRequired(upNode, current, end, 10);
//}
//if (checkIsPassable(downNode, walker, staticMap) ){
// addIfRequired(downNode, current, end, 10);
//}
}
the last point is to add a field (a cube) if required ^^
private void addIfRequired(Node nNode, Node current, Node end, int distance) {
if ( !isPosInList(nNode, cList) ){
if ( isPosInList(nNode, oList) ){
Node can = getPos(nNode, oList);
if (can.g < nNode.g){
can.from = current;
can.g = current.g + distance;
can.f = can.h + can.g;
}
}else{
nNode.from = current;
nNode.h = 10* ( Math.abs(end.x-nNode.x)+Math.abs(end.y-nNode.y) );
//nNode.h = 10* ( Math.abs(end.x-nNode.x)+Math.abs(end.y-nNode.y) +Math.abs(end.z-nNode.z) );
nNode.g = current.g + distance;
nNode.f = nNode.h + nNode.g;
oList.add(nNode);
}
}
}
if you're wondering what a node is..
public class Node {
int f;
int g;
int h;
int x;
int y;
//int z;
Node from;
Node(int x, int y){
this.x=x; this.y=y;
}
//Node(int x, int y, int z){
// this.x=x; this.y=y;this.z=z;
//}
boolean isSamePos(Node n){
if (n != null && n.x==x && n.y==y) return true;
//if (n != null && n.x==x && n.y==y && n.z==z) return true;
return false;
}
@Override
public String toString() {
return ""+x+"/"+y+" g="+g+" h="+h+" f="+f;
//return ""+x+"/"+y+"/"+z+" g="+g+" h="+h+" f="+f;
}
}
this would be the a*algortihm for path finding....
i've added in comments //...
how you have to adjust that code for 3D path finding...