Skip to content

Commit

Permalink
Pathfinding improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Anuken committed Jun 19, 2023
1 parent 974d19f commit c718199
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 9 deletions.
31 changes: 27 additions & 4 deletions core/src/mindustry/ai/ControlPathfinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -232,11 +233,11 @@ public boolean getPathPosition(Unit unit, int pathId, Vec2 destination, Vec2 out
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);
}
Expand Down Expand Up @@ -280,6 +281,18 @@ public boolean getPathPosition(Unit unit, int pathId, Vec2 destination, Vec2 out
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);
}
Expand Down Expand Up @@ -482,6 +495,7 @@ static class PathRequest{
volatile PathCost cost;
volatile int team;
volatile int lastWorldUpdate;
volatile boolean forcedRecalc;

final Vec2 lastPos = new Vec2();
float stuckTimer = 0f;
Expand All @@ -506,23 +520,32 @@ static class PathRequest{

long lastUpdateId;
long lastTime;
long forceRecalcTime;

volatile int lastId, curId;

public PathRequest(PathfindThread thread){
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);
}
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);
}

Expand Down
9 changes: 6 additions & 3 deletions core/src/mindustry/ai/Pathfinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
Expand Down Expand Up @@ -153,7 +152,7 @@ private void clearCache(){

/** 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);
Expand All @@ -165,6 +164,7 @@ public int packTile(Tile tile){
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){
Expand All @@ -180,10 +180,11 @@ public int packTile(Tile tile){
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,
Expand Down Expand Up @@ -564,6 +565,8 @@ class PathTileStruct{
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
Expand Down
3 changes: 1 addition & 2 deletions core/src/mindustry/entities/EntityCollisions.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;

Expand Down Expand Up @@ -129,7 +128,7 @@ public <T extends Hitboxc> void updatePhysics(EntityGroup<T> group){

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){
Expand Down
5 changes: 5 additions & 0 deletions core/src/mindustry/world/Tile.java
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ public int staticDarkness(){
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;
Expand Down

0 comments on commit c718199

Please sign in to comment.