Attempts to further optimize pathfinding
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#Autogenerated file. Do not modify.
|
#Autogenerated file. Do not modify.
|
||||||
#Sat Apr 21 01:07:37 EDT 2018
|
#Sat Apr 21 11:52:24 EDT 2018
|
||||||
version=release
|
version=release
|
||||||
androidBuildCode=1077
|
androidBuildCode=1079
|
||||||
name=Mindustry
|
name=Mindustry
|
||||||
code=3.5
|
code=3.5
|
||||||
build=custom build
|
build=custom build
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import io.anuke.ucore.function.Consumer;
|
|||||||
import io.anuke.ucore.util.Geometry;
|
import io.anuke.ucore.util.Geometry;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
|
||||||
/**An IndexedAStarPathfinder that uses an OptimizedGraph, and therefore has less allocations.*/
|
/**An IndexedAStarPathfinder that uses an OptimizedGraph, and therefore has less allocations.*/
|
||||||
public class OptimizedPathFinder {
|
public class OptimizedPathFinder {
|
||||||
IntMap<NodeRecord> records = new IntMap<>();
|
IntMap<NodeRecord> records = new IntMap<>();
|
||||||
@@ -20,7 +22,6 @@ public class OptimizedPathFinder {
|
|||||||
NodeRecord current;
|
NodeRecord current;
|
||||||
|
|
||||||
private int searchId;
|
private int searchId;
|
||||||
private Tile cameFrom = null;
|
|
||||||
|
|
||||||
private static final byte UNVISITED = 0;
|
private static final byte UNVISITED = 0;
|
||||||
private static final byte OPEN = 1;
|
private static final byte OPEN = 1;
|
||||||
@@ -63,30 +64,12 @@ public class OptimizedPathFinder {
|
|||||||
|
|
||||||
visitChildren(endNode);
|
visitChildren(endNode);
|
||||||
|
|
||||||
cameFrom = current.node;
|
|
||||||
|
|
||||||
} while (openList.size > 0);
|
} while (openList.size > 0);
|
||||||
|
|
||||||
// We've run out of nodes without finding the goal, so there's no solution
|
// We've run out of nodes without finding the goal, so there's no solution
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runStep(Tile startNode, Tile endNode){
|
|
||||||
if(openList.size > 0) {
|
|
||||||
// Retrieve the node with smallest estimated total cost from the open list
|
|
||||||
current = openList.pop();
|
|
||||||
current.category = CLOSED;
|
|
||||||
|
|
||||||
// Terminate if we reached the goal node
|
|
||||||
if (current.node == endNode) return;
|
|
||||||
|
|
||||||
visitChildren(endNode);
|
|
||||||
|
|
||||||
cameFrom = current.node;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean search(PathFinderRequest<Tile> request, long timeToRun) {
|
public boolean search(PathFinderRequest<Tile> request, long timeToRun) {
|
||||||
|
|
||||||
long lastTime = TimeUtils.nanoTime();
|
long lastTime = TimeUtils.nanoTime();
|
||||||
@@ -138,7 +121,6 @@ public class OptimizedPathFinder {
|
|||||||
|
|
||||||
// Initialize the open list
|
// Initialize the open list
|
||||||
openList.clear();
|
openList.clear();
|
||||||
cameFrom = null;
|
|
||||||
|
|
||||||
// Initialize the record for the start node and add it to the open list
|
// Initialize the record for the start node and add it to the open list
|
||||||
NodeRecord startRecord = getNodeRecord(startNode);
|
NodeRecord startRecord = getNodeRecord(startNode);
|
||||||
@@ -233,11 +215,11 @@ public class OptimizedPathFinder {
|
|||||||
}else{ //moving diagonal
|
}else{ //moving diagonal
|
||||||
//forced neighbor in the diagonal pattern
|
//forced neighbor in the diagonal pattern
|
||||||
if(obstacle(rel(current, direction + 3)) && !obstacle(rel(current, direction + 2)) && !obstacle(rel(current, direction -2))) {
|
if(obstacle(rel(current, direction + 3)) && !obstacle(rel(current, direction + 2)) && !obstacle(rel(current, direction -2))) {
|
||||||
cons.accept(rel(current, direction + 2));//jps(rel(current, direction + 2), Mathf.mod(direction + 2, 8), end, cons);
|
cons.accept(rel(current, direction + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(obstacle(rel(current, direction - 3)) && !obstacle(rel(current, direction - 2))&& !obstacle(rel(current, direction + 2))){
|
if(obstacle(rel(current, direction - 3)) && !obstacle(rel(current, direction - 2))&& !obstacle(rel(current, direction + 2))){
|
||||||
cons.accept(rel(current, direction - 2));//jps(rel(current, direction - 2), Mathf.mod(direction - 2, 8), end, cons);
|
cons.accept(rel(current, direction - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,10 +228,10 @@ public class OptimizedPathFinder {
|
|||||||
//moving straight
|
//moving straight
|
||||||
if(direction % 2 == 0){
|
if(direction % 2 == 0){
|
||||||
Tile sf = scanDir(rel(current, direction), end, direction); //check if there's anything of interest going straight
|
Tile sf = scanDir(rel(current, direction), end, direction); //check if there's anything of interest going straight
|
||||||
if(sf != null){ //if there is, jump to that location immediately and stop
|
if(sf != null){ //if there is, jump to that location immediately and stop. else, nothing must be there, end.
|
||||||
cons.accept(sf);
|
cons.accept(sf);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}else{ //moving diagonal
|
}else{ //moving diagonal
|
||||||
Tile sl = scanDir(rel(current, Mathf.mod(direction - 1, 8)), end, Mathf.mod(direction - 1, 8));
|
Tile sl = scanDir(rel(current, Mathf.mod(direction - 1, 8)), end, Mathf.mod(direction - 1, 8));
|
||||||
|
|
||||||
@@ -285,13 +267,16 @@ public class OptimizedPathFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Tile scanDir(Tile tile, Tile end, int direction){
|
protected Tile scanDir(Tile tile, Tile end, int direction){
|
||||||
|
|
||||||
while(!obstacle(tile)){
|
while(!obstacle(tile)){
|
||||||
if(debug) Effects.effect(Fx.node2, tile.worldx(), tile.worldy());
|
if(debug) Effects.effect(Fx.node2, tile.worldx(), tile.worldy());
|
||||||
if(tile == end) return tile;
|
if(tile == end) return tile;
|
||||||
if(direction % 2 == 0){
|
if(direction % 2 == 0){
|
||||||
|
|
||||||
//forced neighbor in the straight pattern
|
//forced neighbor in the straight pattern
|
||||||
if((obstacle(rel(tile, direction + 2)) && !obstacle(rel(tile, direction + 1))) ||
|
if((obstacle(rel(tile, direction + 2)) && !obstacle(rel(tile, direction + 1))) ||
|
||||||
(obstacle(rel(tile, direction - 2)) && !obstacle(rel(tile, direction - 1)))){
|
(obstacle(rel(tile, direction - 2)) && !obstacle(rel(tile, direction - 1)))){
|
||||||
|
//Log.info("Found forced linear neighbor {0} {1} // {2}", tile.x, tile.y, direction);
|
||||||
if(debug) Effects.effect(Fx.node4, tile.worldx(), tile.worldy());
|
if(debug) Effects.effect(Fx.node4, tile.worldx(), tile.worldy());
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
@@ -300,6 +285,7 @@ public class OptimizedPathFinder {
|
|||||||
if((obstacle(rel(tile, direction + 3)) && !obstacle(rel(tile, direction + 2)) && !obstacle(rel(tile, direction - 2))) ||
|
if((obstacle(rel(tile, direction + 3)) && !obstacle(rel(tile, direction + 2)) && !obstacle(rel(tile, direction - 2))) ||
|
||||||
(obstacle(rel(tile, direction - 3)) && !obstacle(rel(tile, direction - 2)) && !obstacle(rel(tile, direction + 2)))) {
|
(obstacle(rel(tile, direction - 3)) && !obstacle(rel(tile, direction - 2)) && !obstacle(rel(tile, direction + 2)))) {
|
||||||
if(debug) Effects.effect(Fx.node4, tile.worldx(), tile.worldy());
|
if(debug) Effects.effect(Fx.node4, tile.worldx(), tile.worldy());
|
||||||
|
//Log.info("Found forced diagonal neighbor {0} {1} // {2}", tile.x, tile.y, direction);
|
||||||
return tile;
|
return tile;
|
||||||
}else{
|
}else{
|
||||||
return null;
|
return null;
|
||||||
@@ -321,7 +307,8 @@ public class OptimizedPathFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected float estimate(Tile tile, Tile other){
|
protected float estimate(Tile tile, Tile other){
|
||||||
return Math.abs(tile.worldx() - other.worldx()) + Math.abs(tile.worldy() - other.worldy());
|
return Math.abs(tile.worldx() - other.worldx()) + Math.abs(tile.worldy() - other.worldy()) +
|
||||||
|
(tile.occluded ? tilesize*2 : 0) + (other.occluded ? tilesize*2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int relDirection(Tile from, Tile current){
|
protected int relDirection(Tile from, Tile current){
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package io.anuke.mindustry.ai;
|
package io.anuke.mindustry.ai;
|
||||||
|
|
||||||
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
||||||
|
import com.badlogic.gdx.ai.pfa.PathSmoother;
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import io.anuke.mindustry.content.fx.Fx;
|
import io.anuke.mindustry.content.fx.Fx;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
@@ -11,6 +13,7 @@ import io.anuke.ucore.util.Log;
|
|||||||
|
|
||||||
public class Pathfinder {
|
public class Pathfinder {
|
||||||
OptimizedPathFinder find = new OptimizedPathFinder();
|
OptimizedPathFinder find = new OptimizedPathFinder();
|
||||||
|
OptimizedPathFinder find2 = new OptimizedPathFinder();
|
||||||
Tile start, end;
|
Tile start, end;
|
||||||
|
|
||||||
public Pathfinder(){
|
public Pathfinder(){
|
||||||
@@ -20,21 +23,36 @@ public class Pathfinder {
|
|||||||
public void test(Tile start, Tile end){
|
public void test(Tile start, Tile end){
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
|
|
||||||
DefaultGraphPath<Tile> p = new DefaultGraphPath<>();
|
DefaultGraphPath<Tile> p = new DefaultGraphPath<>();
|
||||||
|
|
||||||
OptimizedPathFinder.unop = false;
|
OptimizedPathFinder.unop = false;
|
||||||
Timers.markNs();
|
Timers.markNs();
|
||||||
find.searchNodePath(start, end, p);
|
find.searchNodePath(start, end, p);
|
||||||
|
|
||||||
|
Log.info("JSFSAF elapsed: {0}", Timers.elapsedNs());
|
||||||
|
|
||||||
for(Tile tile : p){
|
for(Tile tile : p){
|
||||||
Effects.effect(Fx.node1, tile.worldx(), tile.worldy());
|
Effects.effect(Fx.breakBlock, tile.worldx(), tile.worldy());
|
||||||
|
}
|
||||||
|
|
||||||
|
SmoothGraphPath p2 = new SmoothGraphPath();
|
||||||
|
|
||||||
|
OptimizedPathFinder.unop = true;
|
||||||
|
Timers.markNs();
|
||||||
|
find2.searchNodePath(start, end, p2);
|
||||||
|
new PathSmoother<Tile, Vector2>(new Raycaster()).smoothPath(p2);
|
||||||
|
|
||||||
|
Log.info("UNOP elapsed: {0}", Timers.elapsedNs());
|
||||||
|
|
||||||
|
for(Tile tile : p2){
|
||||||
|
Effects.effect(Fx.place, tile.worldx(), tile.worldy());
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("JSFSAF elapsed: {0}", Timers.elapsedNs());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void step(){
|
public void step(){
|
||||||
find.runStep(start, end);
|
//find.runStep(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear(){
|
private void clear(){
|
||||||
|
|||||||
Reference in New Issue
Block a user