Fixed OutOfMemory error for pathfinding

This commit is contained in:
Anuken
2018-01-25 21:50:00 -05:00
parent 9001fb0dcc
commit 5f131723c4
6 changed files with 30 additions and 37 deletions
@@ -2,12 +2,14 @@ package io.anuke.mindustry.ai;
import com.badlogic.gdx.ai.pfa.*; import com.badlogic.gdx.ai.pfa.*;
import com.badlogic.gdx.utils.BinaryHeap; import com.badlogic.gdx.utils.BinaryHeap;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
/**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<N> implements PathFinder<N> { public class OptimizedPathFinder<N> implements PathFinder<N> {
OptimizedGraph<N> graph; OptimizedGraph<N> graph;
NodeRecord<N>[] nodeRecords; //NodeRecord<N>[] nodeRecords; //TODO remove.
IntMap<NodeRecord<N>> records = new IntMap<>();
BinaryHeap<NodeRecord<N>> openList; BinaryHeap<NodeRecord<N>> openList;
NodeRecord<N> current; NodeRecord<N> current;
@@ -23,22 +25,13 @@ public class OptimizedPathFinder<N> implements PathFinder<N> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public OptimizedPathFinder(OptimizedGraph<N> graph) { public OptimizedPathFinder(OptimizedGraph<N> graph) {
this.graph = graph; this.graph = graph;
this.nodeRecords = (NodeRecord<N>[]) new NodeRecord[graph.getNodeCount()]; //this.nodeRecords = (NodeRecord<N>[]) new NodeRecord[graph.getNodeCount()];
this.openList = new BinaryHeap<>(); this.openList = new BinaryHeap<>();
} }
@Override @Override
public boolean searchConnectionPath(N startNode, N endNode, Heuristic<N> heuristic, GraphPath<Connection<N>> outPath) { public boolean searchConnectionPath(N startNode, N endNode, Heuristic<N> heuristic, GraphPath<Connection<N>> outPath) {
return false;
// Perform AStar
boolean found = search(startNode, endNode, heuristic);
if (found) {
// Create a path made of connections
generateConnectionPath(startNode, outPath);
}
return found;
} }
@Override @Override
@@ -196,27 +189,13 @@ public class OptimizedPathFinder<N> implements PathFinder<N> {
} }
protected void generateConnectionPath(N startNode, GraphPath<Connection<N>> outPath) {
//do ABSOLUTELY NOTHING
/*
// Work back along the path, accumulating connections
// outPath.clear();
while (current.node != startNode) {
outPath.add(current.connection);
current = nodeRecords[graph.getIndex(current.connection.getFromNode())];
}
// Reverse the path
outPath.reverse();*/
}
protected void generateNodePath(N startNode, GraphPath<N> outPath) { protected void generateNodePath(N startNode, GraphPath<N> outPath) {
// Work back along the path, accumulating nodes // Work back along the path, accumulating nodes
// outPath.clear(); // outPath.clear();
while (current.from != null) { while (current.from != null) {
outPath.add(current.node); outPath.add(current.node);
current = nodeRecords[graph.getIndex(current.from)]; current = records.get(graph.getIndex(current.from));
} }
outPath.add(startNode); outPath.add(startNode);
@@ -230,6 +209,16 @@ public class OptimizedPathFinder<N> implements PathFinder<N> {
} }
protected NodeRecord<N> getNodeRecord(N node) { protected NodeRecord<N> getNodeRecord(N node) {
if(!records.containsKey(graph.getIndex(node))){
NodeRecord<N> record = new NodeRecord<>();
record.node = node;
record.searchId = searchId;
records.put(graph.getIndex(node), record);
return record;
}else{
return records.get(graph.getIndex(node));
}
/*
int index = graph.getIndex(node); int index = graph.getIndex(node);
NodeRecord<N> nr = nodeRecords[index]; NodeRecord<N> nr = nodeRecords[index];
if (nr != null) { if (nr != null) {
@@ -242,7 +231,7 @@ public class OptimizedPathFinder<N> implements PathFinder<N> {
nr = nodeRecords[index] = new NodeRecord<>(); nr = nodeRecords[index] = new NodeRecord<>();
nr.node = node; nr.node = node;
nr.searchId = searchId; nr.searchId = searchId;
return nr; return nr;*/
} }
/** /**
@@ -127,6 +127,7 @@ public class Pathfind{
if(point.finder.search(point.request, maxTime)){ if(point.finder.search(point.request, maxTime)){
smoother.smoothPath(point.path); smoother.smoothPath(point.path);
point.pathTiles = point.path.nodes.toArray(Tile.class); point.pathTiles = point.path.nodes.toArray(Tile.class);
point.finder = null;
} }
}catch (ArrayIndexOutOfBoundsException e){ }catch (ArrayIndexOutOfBoundsException e){
//no path //no path
@@ -421,11 +421,9 @@ public class Control extends Module{
Timers.run(i*2, ()-> Effects.effect(Fx.explosion, core.worldx()+Mathf.range(40), core.worldy()+Mathf.range(40))); Timers.run(i*2, ()-> Effects.effect(Fx.explosion, core.worldx()+Mathf.range(40), core.worldy()+Mathf.range(40)));
} }
Effects.effect(Fx.coreexplosion, core.worldx(), core.worldy()); Effects.effect(Fx.coreexplosion, core.worldx(), core.worldy());
Timers.run(60, () -> { ui.restart.show();
ui.restart.show(); if(Net.active() && Net.server()) netServer.handleGameOver();
if(Net.active() && Net.server()) netServer.handleGameOver();
});
} }
public boolean isGameOver(){ public boolean isGameOver(){
@@ -613,7 +611,7 @@ public class Control extends Module{
} }
if(Inputs.keyTap(Keys.G)){ if(Inputs.keyTap(Keys.G)){
addItem(Item.stone, 1000); Vars.world.pathfinder().benchmark();
} }
if(Inputs.keyDown(Keys.I)){ if(Inputs.keyDown(Keys.I)){
@@ -645,6 +643,10 @@ public class Control extends Module{
if(!GameState.is(State.menu)){ if(!GameState.is(State.menu)){
input.update(); input.update();
if(core.block() != ProductionBlocks.core && !ui.restart.isShown()){
coreDestroyed();
}
if(Inputs.keyTap("pause") && !ui.restart.isShown() && !Net.active() && (GameState.is(State.paused) || GameState.is(State.playing))){ if(Inputs.keyTap("pause") && !ui.restart.isShown() && !Net.active() && (GameState.is(State.paused) || GameState.is(State.playing))){
GameState.set(GameState.is(State.playing) ? State.paused : State.playing); GameState.set(GameState.is(State.playing) ? State.paused : State.playing);
@@ -20,7 +20,7 @@ public class EnemySpawn{
/**The tier this spawn starts at.*/ /**The tier this spawn starts at.*/
protected int tier = 1; protected int tier = 1;
/**Maximum amount of enemies that spawn*/ /**Maximum amount of enemies that spawn*/
protected int max = 17; protected int max = 60;
/**How many waves need to pass before the amount of enemies increases by 1*/ /**How many waves need to pass before the amount of enemies increases by 1*/
protected float scaling = 9999f; protected float scaling = 9999f;
/**Amount of enemies spawned initially, with no scaling*/ /**Amount of enemies spawned initially, with no scaling*/
@@ -11,6 +11,7 @@ public class Map{
public boolean visible = true; public boolean visible = true;
public boolean flipBase = false; public boolean flipBase = false;
public boolean custom = false; public boolean custom = false;
public boolean oreGen = true;
public Color backgroundColor = Color.valueOf("646464"); public Color backgroundColor = Color.valueOf("646464");
public transient Pixmap pixmap; public transient Pixmap pixmap;
@@ -57,8 +57,8 @@ public class WorldGenerator {
block = rocks.get(floor); block = rocks.get(floor);
} }
if(floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone || if(Vars.world.getMap().oreGen && (floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone ||
floor == Blocks.snow || floor == Blocks.sand){ floor == Blocks.snow || floor == Blocks.sand)){
if(Noise.nnoise(x, y, 8, 1) > 0.21){ if(Noise.nnoise(x, y, 8, 1) > 0.21){
floor = Blocks.iron; floor = Blocks.iron;
} }