Pathfinding improvements
This commit is contained in:
@@ -7,6 +7,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
@@ -51,7 +52,7 @@ public class ControlPathfinder{
|
||||
costLegs = (team, tile) ->
|
||||
PathTile.legSolid(tile) ? impassable : 1 +
|
||||
(PathTile.deep(tile) ? 6000 : 0) +
|
||||
(PathTile.solid(tile) ? 2 : 0),
|
||||
(PathTile.nearLegSolid(tile) ? 3 : 0),
|
||||
|
||||
costNaval = (team, tile) ->
|
||||
//impassable same-team neutral block, or non-liquid
|
||||
@@ -232,11 +233,11 @@ public class ControlPathfinder{
|
||||
req.curId = pathId;
|
||||
|
||||
//check for the unit getting stuck every N seconds
|
||||
if((req.stuckTimer += Time.delta) >= 60f * 2.5f){
|
||||
if((req.stuckTimer += Time.delta) >= 60f * 1.5f){
|
||||
req.stuckTimer = 0f;
|
||||
//force recalculate
|
||||
if(req.lastPos.within(unit, 1.5f)){
|
||||
req.lastWorldUpdate = -1;
|
||||
req.forceRecalculate();
|
||||
}
|
||||
req.lastPos.set(unit);
|
||||
}
|
||||
@@ -280,6 +281,18 @@ public class ControlPathfinder{
|
||||
Tile tile = tile(items[req.rayPathIndex]);
|
||||
out.set(tile);
|
||||
|
||||
if(req.rayPathIndex > 0){
|
||||
float angleToNext = tile(items[req.rayPathIndex - 1]).angleTo(tile);
|
||||
float angleToDest = unit.angleTo(tile);
|
||||
//force recalculate when the unit moves backwards
|
||||
if(Angles.angleDist(angleToNext, angleToDest) > 80f && !unit.within(tile, 1f)){
|
||||
if(showDebug){
|
||||
Fx.placeBlock.at(unit, 1f);
|
||||
}
|
||||
req.forceRecalculate();
|
||||
}
|
||||
}
|
||||
|
||||
if(unit.within(tile, range)){
|
||||
req.pathIndex = req.rayPathIndex = Math.max(req.pathIndex, req.rayPathIndex + 1);
|
||||
}
|
||||
@@ -482,6 +495,7 @@ public class ControlPathfinder{
|
||||
volatile PathCost cost;
|
||||
volatile int team;
|
||||
volatile int lastWorldUpdate;
|
||||
volatile boolean forcedRecalc;
|
||||
|
||||
final Vec2 lastPos = new Vec2();
|
||||
float stuckTimer = 0f;
|
||||
@@ -506,6 +520,7 @@ public class ControlPathfinder{
|
||||
|
||||
long lastUpdateId;
|
||||
long lastTime;
|
||||
long forceRecalcTime;
|
||||
|
||||
volatile int lastId, curId;
|
||||
|
||||
@@ -513,6 +528,13 @@ public class ControlPathfinder{
|
||||
this.thread = thread;
|
||||
}
|
||||
|
||||
public void forceRecalculate(){
|
||||
//keep it at 3 times/sec
|
||||
if(Time.timeSinceMillis(forceRecalcTime) < 1000 / 3) return;
|
||||
forcedRecalc = true;
|
||||
forceRecalcTime = Time.millis();
|
||||
}
|
||||
|
||||
void update(long maxUpdateNs){
|
||||
if(curId != lastId){
|
||||
clear(true);
|
||||
@@ -520,9 +542,10 @@ public class ControlPathfinder{
|
||||
lastId = curId;
|
||||
|
||||
//re-do everything when world updates, but keep the old path around
|
||||
if(Time.timeSinceMillis(lastTime) > 1000 * 3 && (worldUpdateId != lastWorldUpdate || !destination.epsilonEquals(lastDestination, 2f))){
|
||||
if(forcedRecalc || (Time.timeSinceMillis(lastTime) > 1000 * 3 && (worldUpdateId != lastWorldUpdate || !destination.epsilonEquals(lastDestination, 2f)))){
|
||||
lastTime = Time.millis();
|
||||
lastWorldUpdate = worldUpdateId;
|
||||
forcedRecalc = false;
|
||||
clear(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
@@ -153,7 +152,7 @@ public class Pathfinder implements Runnable{
|
||||
|
||||
/** Packs a tile into its internal representation. */
|
||||
public int packTile(Tile tile){
|
||||
boolean nearLiquid = false, nearSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.floor().isDeep();
|
||||
boolean nearLiquid = false, nearSolid = false, nearLegSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.floor().isDeep();
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
Tile other = tile.nearby(i);
|
||||
@@ -165,6 +164,7 @@ public class Pathfinder implements Runnable{
|
||||
if(osolid && !other.block().teamPassable) nearSolid = true;
|
||||
if(!floor.isLiquid) nearGround = true;
|
||||
if(!floor.isDeep()) allDeep = false;
|
||||
if(other.legSolid()) nearLegSolid = true;
|
||||
|
||||
//other tile is now near solid
|
||||
if(solid && !tile.block().teamPassable){
|
||||
@@ -180,10 +180,11 @@ public class Pathfinder implements Runnable{
|
||||
tid == 0 && tile.build != null && state.rules.coreCapture ? 255 : tid, //use teamid = 255 when core capture is enabled to mark out derelict structures
|
||||
solid,
|
||||
tile.floor().isLiquid,
|
||||
tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air),
|
||||
tile.legSolid(),
|
||||
nearLiquid,
|
||||
nearGround,
|
||||
nearSolid,
|
||||
nearLegSolid,
|
||||
tile.floor().isDeep(),
|
||||
tile.floor().damageTaken > 0.00001f,
|
||||
allDeep,
|
||||
@@ -564,6 +565,8 @@ public class Pathfinder implements Runnable{
|
||||
boolean nearGround;
|
||||
//whether this block is near a solid object
|
||||
boolean nearSolid;
|
||||
//whether this block is near a block that is solid for legged units
|
||||
boolean nearLegSolid;
|
||||
//whether this block is deep / drownable
|
||||
boolean deep;
|
||||
//whether the floor damages
|
||||
|
||||
@@ -5,7 +5,6 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
@@ -129,7 +128,7 @@ public class EntityCollisions{
|
||||
|
||||
public static boolean legsSolid(int x, int y){
|
||||
Tile tile = world.tile(x, y);
|
||||
return tile == null || tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air);
|
||||
return tile == null || tile.legSolid();
|
||||
}
|
||||
|
||||
public static boolean waterSolid(int x, int y){
|
||||
|
||||
@@ -547,6 +547,11 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
||||
return block.solid && block.fillsTile && !block.synthetic() ? data : 0;
|
||||
}
|
||||
|
||||
/** @return whether this tile is solid for legged units */
|
||||
public boolean legSolid(){
|
||||
return staticDarkness() >= 2 || (floor.solid && block == Blocks.air);
|
||||
}
|
||||
|
||||
/** @return true if these tiles are right next to each other. */
|
||||
public boolean adjacentTo(Tile tile){
|
||||
return relativeTo(tile) != -1;
|
||||
|
||||
Reference in New Issue
Block a user