Implemented inefficient pathfinding
This commit is contained in:
29
core/src/io/anuke/mindustry/ai/HGraph.java
Normal file
29
core/src/io/anuke/mindustry/ai/HGraph.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.ai.pfa.HierarchicalGraph;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
public class HGraph implements HierarchicalGraph<Tile> {
|
||||
|
||||
@Override
|
||||
public int getLevelCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(int level) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile convertNodeBetweenLevels(int inputLevel, Tile node, int outputLevel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<Connection<Tile>> getConnections(Tile fromNode) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public class OptimizedPathFinder {
|
||||
NodeRecord current;
|
||||
|
||||
private int searchId;
|
||||
private Tile end;
|
||||
|
||||
private static final byte UNVISITED = 0;
|
||||
private static final byte OPEN = 1;
|
||||
@@ -29,14 +30,12 @@ public class OptimizedPathFinder {
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
public static boolean unop = false;
|
||||
public static boolean step = true;
|
||||
|
||||
public OptimizedPathFinder() {
|
||||
this.openList = new BinaryHeap<>();
|
||||
}
|
||||
|
||||
public boolean searchNodePath(Tile startNode, Tile endNode, GraphPath<Tile> outPath) {
|
||||
this.end = endNode;
|
||||
|
||||
// Perform AStar
|
||||
boolean found = search(startNode, endNode);
|
||||
@@ -135,13 +134,13 @@ public class OptimizedPathFinder {
|
||||
protected void visitChildren(Tile endNode) {
|
||||
if(debug) Effects.effect(Fx.node3, current.node.worldx(), current.node.worldy());
|
||||
|
||||
jps(current.node, current.from == null ? -1 : relDirection(current.node, current.from), endNode, node -> {
|
||||
nodes(current.node, node -> {
|
||||
float addCost = estimate(current.node, node);
|
||||
|
||||
float nodeCost = current.costSoFar + addCost;
|
||||
|
||||
float nodeHeuristic;
|
||||
NodeRecord nodeRecord = getNodeRecord(node);;
|
||||
NodeRecord nodeRecord = getNodeRecord(node);
|
||||
|
||||
if (nodeRecord.category == CLOSED) { // The node is closed
|
||||
|
||||
@@ -182,19 +181,17 @@ public class OptimizedPathFinder {
|
||||
});
|
||||
}
|
||||
|
||||
protected void nodes(Tile current, Consumer<Tile> cons){
|
||||
if(obstacle(current)) return;
|
||||
for(int i = 0; i < 4; i ++){
|
||||
Tile n = current.getNearby(i);
|
||||
if(!obstacle(n)) cons.accept(n);
|
||||
}
|
||||
}
|
||||
|
||||
protected void jps(Tile current, int direction, Tile end, Consumer<Tile> cons){
|
||||
if(obstacle(current)) return; //skip solid or off-the-screen stuff
|
||||
|
||||
//Log.info("jps {0} {1} // {2}", current.x, current.y, direction);
|
||||
|
||||
if(unop){
|
||||
for(int i = 0; i < 4; i ++){
|
||||
if(!obstacle(current.getNearby(i))) cons.accept(current.getNearby(i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//if there's no start point, scan everything.
|
||||
if(direction == -1){
|
||||
for(int i = 0; i < 8; i ++){
|
||||
@@ -267,7 +264,6 @@ public class OptimizedPathFinder {
|
||||
}
|
||||
|
||||
protected Tile scanDir(Tile tile, Tile end, int direction){
|
||||
|
||||
while(!obstacle(tile)){
|
||||
if(debug) Effects.effect(Fx.node2, tile.worldx(), tile.worldy());
|
||||
if(tile == end) return tile;
|
||||
@@ -303,12 +299,12 @@ public class OptimizedPathFinder {
|
||||
}
|
||||
|
||||
protected boolean obstacle(Tile tile){
|
||||
return tile == null || tile.solid();
|
||||
return tile == null || (tile.solid() && end.target() != tile && tile.target() != end);
|
||||
}
|
||||
|
||||
protected float estimate(Tile tile, Tile other){
|
||||
return Math.abs(tile.worldx() - other.worldx()) + Math.abs(tile.worldy() - other.worldy()) +
|
||||
(tile.occluded ? tilesize*2 : 0) + (other.occluded ? tilesize*2 : 0);
|
||||
(tile.occluded ? tilesize : 0) + (other.occluded ? tilesize : 0);
|
||||
}
|
||||
|
||||
protected int relDirection(Tile from, Tile current){
|
||||
|
||||
@@ -1,46 +1,42 @@
|
||||
package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
||||
import com.badlogic.gdx.ai.pfa.PathSmoother;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.function.Listenable;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
public class Pathfinder {
|
||||
OptimizedPathFinder find = new OptimizedPathFinder();
|
||||
OptimizedPathFinder find2 = new OptimizedPathFinder();
|
||||
Tile start, end;
|
||||
private OptimizedPathFinder find;
|
||||
private AsyncExecutor executor = new AsyncExecutor(8);
|
||||
private PathSmoother<Tile, Vector2> smoother = new PathSmoother<>(new Raycaster());
|
||||
//private HierarchicalPathFinder<Tile> hfinder = new HierarchicalPathFinder<>();
|
||||
|
||||
public Pathfinder(){
|
||||
Events.on(WorldLoadEvent.class, this::clear);
|
||||
}
|
||||
|
||||
public void findPath(Tile start, Tile end, SmoothGraphPath path,
|
||||
OptimizedPathFinder finder, Listenable completed){
|
||||
executor.submit(() -> {
|
||||
finder.searchNodePath(start, end, path);
|
||||
smoother.smoothPath(path);
|
||||
completed.listen();
|
||||
return path;
|
||||
});
|
||||
}
|
||||
|
||||
public void test(Tile start, Tile end){
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
DefaultGraphPath<Tile> p = new DefaultGraphPath<>();
|
||||
|
||||
OptimizedPathFinder.unop = false;
|
||||
Timers.markNs();
|
||||
find.searchNodePath(start, end, p);
|
||||
|
||||
Log.info("JSFSAF elapsed: {0}", Timers.elapsedNs());
|
||||
|
||||
for(Tile tile : p){
|
||||
Effects.effect(Fx.breakBlock, tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
SmoothGraphPath p2 = new SmoothGraphPath();
|
||||
|
||||
OptimizedPathFinder.unop = true;
|
||||
Timers.markNs();
|
||||
find2.searchNodePath(start, end, p2);
|
||||
find.searchNodePath(start, end, p2);
|
||||
new PathSmoother<Tile, Vector2>(new Raycaster()).smoothPath(p2);
|
||||
|
||||
Log.info("UNOP elapsed: {0}", Timers.elapsedNs());
|
||||
@@ -56,6 +52,6 @@ public class Pathfinder {
|
||||
}
|
||||
|
||||
private void clear(){
|
||||
|
||||
find = new OptimizedPathFinder();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user