mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-04 15:27:30 +07:00
Implemented a JPS path finder (see #63)
This commit is contained in:
@ -28,7 +28,7 @@ public class MapGraph {
|
||||
return getOrCreate(tmpPoint.set(src));
|
||||
}
|
||||
|
||||
private Point2 getOrCreate(int x, int y) {
|
||||
public Point2 getOrCreate(int x, int y) {
|
||||
return getOrCreate(tmpPoint.set(x, y));
|
||||
}
|
||||
|
||||
@ -74,9 +74,14 @@ public class MapGraph {
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
private void tryNeighbor(Array<Point2> neighbors, int flags, int x, int y) {
|
||||
if (map.flags(x, y) != 0) return;
|
||||
public boolean tryNeighbor(Array<Point2> neighbors, int flags, int x, int y) {
|
||||
if (!isWalkable(x, y, flags)) return false;
|
||||
Point2 point = getOrCreate(x, y);
|
||||
neighbors.add(point);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isWalkable(int x, int y, int flags) {
|
||||
return map.flags(x, y) == 0;
|
||||
}
|
||||
}
|
||||
|
123
core/src/com/riiablo/map/pfa/JPSPathFinder.java
Normal file
123
core/src/com/riiablo/map/pfa/JPSPathFinder.java
Normal file
@ -0,0 +1,123 @@
|
||||
package com.riiablo.map.pfa;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.riiablo.map.MapGraph;
|
||||
|
||||
public class JPSPathFinder extends AStarPathFinder {
|
||||
final MapGraph graph;
|
||||
private final Array<Point2> neighbors = new Array<>(false, 8);
|
||||
|
||||
public JPSPathFinder(MapGraph graph) {
|
||||
super(graph);
|
||||
this.graph = graph;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitChildren(Point2 startNode, Point2 endNode, int flags, int size) {
|
||||
identifySuccessors(startNode, endNode, flags, size);
|
||||
}
|
||||
|
||||
protected void identifySuccessors(Point2 startNode, Point2 endNode, int flags, int size) {
|
||||
Array<Point2> neighbors = getPrunedNeighbors(startNode, flags, this.neighbors);
|
||||
for (Point2 neighbor : neighbors) {
|
||||
Point2 jump = jump(startNode, neighbor, flags, endNode);
|
||||
if (jump != null) {
|
||||
float g = startNode.g() + heuristic.estimate(startNode, jump);
|
||||
|
||||
float h;
|
||||
reset(jump);
|
||||
switch (jump.category) {
|
||||
case Point2.UNVISITED:
|
||||
h = heuristic.estimate(jump, endNode);
|
||||
break;
|
||||
case Point2.OPEN:
|
||||
if (jump.g() <= g) continue;
|
||||
openList.remove(jump);
|
||||
h = jump.f() - jump.g();
|
||||
break;
|
||||
case Point2.CLOSED:
|
||||
if (jump.g() <= g) continue;
|
||||
h = jump.f() - jump.g();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Invalid nodeRecord category: " + jump.category);
|
||||
}
|
||||
|
||||
jump.g = g;
|
||||
jump.parent = startNode;
|
||||
|
||||
addToOpenList(jump, g + h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Array<Point2> getPrunedNeighbors(Point2 startNode, int flags, Array<Point2> neighbors) {
|
||||
Point2 parent = startNode.parent;
|
||||
if (parent == null) {
|
||||
return graph.getNeighbors(startNode, flags, neighbors);
|
||||
} else {
|
||||
neighbors.clear();
|
||||
final int x = startNode.x;
|
||||
final int y = startNode.y;
|
||||
final int dx = (x - parent.x) / Math.max(Math.abs(x - parent.x), 1);
|
||||
final int dy = (y - parent.y) / Math.max(Math.abs(y - parent.y), 1);
|
||||
if (dx != 0 && dy != 0) {
|
||||
boolean b1 = graph.tryNeighbor(neighbors, flags, x, y + dy);
|
||||
boolean b2 = graph.tryNeighbor(neighbors, flags, x + dx, y);
|
||||
if (b1 || b2) neighbors.add(graph.getOrCreate(x + dx, y + dy));
|
||||
if (b1 && !graph.isWalkable(x - dx, y, flags)) neighbors.add(graph.getOrCreate(x - dx, y + dy));
|
||||
if (b2 && !graph.isWalkable(x, y - dy, flags)) neighbors.add(graph.getOrCreate(x + dx, y - dy));
|
||||
} else if (dx == 0) {
|
||||
boolean b1 = graph.tryNeighbor(neighbors, flags, x, y + dy);
|
||||
if (b1) {
|
||||
if (!graph.isWalkable(x + 1, y, flags)) neighbors.add(graph.getOrCreate(x + 1, y + dy));
|
||||
if (!graph.isWalkable(x - 1, y, flags)) neighbors.add(graph.getOrCreate(x - 1, y + dy));
|
||||
}
|
||||
} else {
|
||||
boolean b2 = graph.tryNeighbor(neighbors, flags, x + dx, y);
|
||||
if (b2) {
|
||||
if (!graph.isWalkable(x, y + 1, flags)) neighbors.add(graph.getOrCreate(x + dx, y + 1));
|
||||
if (!graph.isWalkable(x, y - 1, flags)) neighbors.add(graph.getOrCreate(x + dx, y - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
private Point2 jump(Point2 startNode, Point2 node, int flags, Point2 endNode) {
|
||||
final int x = node.x;
|
||||
final int y = node.y;
|
||||
if (!graph.isWalkable(x, y, flags)) return null;
|
||||
if (node == endNode) return endNode;
|
||||
final int dx = x - startNode.x;
|
||||
final int dy = y - startNode.y;
|
||||
if (dx != 0 && dy != 0) {
|
||||
if ((graph.isWalkable(x - dx, y + dy, flags) && !graph.isWalkable(x - dx, y, flags))
|
||||
|| (graph.isWalkable(x + dx, y - dy, flags) && !graph.isWalkable(x, y - dy, flags))) {
|
||||
return node;
|
||||
}
|
||||
} else if (dx != 0) {
|
||||
if ((graph.isWalkable(x + dx, y + 1, flags) && !graph.isWalkable(x, y + 1, flags))
|
||||
|| (graph.isWalkable(x + dx, y - 1, flags) && !graph.isWalkable(x, y - 1, flags))) {
|
||||
return node;
|
||||
}
|
||||
} else {
|
||||
if ((graph.isWalkable(x + 1, y + dy, flags) && !graph.isWalkable(x + 1, y, flags))
|
||||
|| (graph.isWalkable(x - 1, y + dy, flags) && !graph.isWalkable(x - 1, y, flags))) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
if (dx != 0 && dy != 0) {
|
||||
if (jump(node, graph.getOrCreate(x + dx, y), flags, endNode) != null) return node;
|
||||
if (jump(node, graph.getOrCreate(x, y + dy), flags, endNode) != null) return node;
|
||||
}
|
||||
|
||||
if (graph.isWalkable(x + dx, y, flags) || graph.isWalkable(x, y + dy, flags)) {
|
||||
return jump(node, graph.getOrCreate(x + dx, y + dy), flags, endNode);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -149,6 +149,10 @@ size:
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
public boolean equals(int x, int y) {
|
||||
return x == this.x && y == this.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + x + ", " + y + ")";
|
||||
|
Reference in New Issue
Block a user