Proper pathfinding fixes

This commit is contained in:
Anuken 2022-02-17 15:15:51 -05:00
parent ba475b681c
commit 49a39d42e7
5 changed files with 65 additions and 10 deletions

View File

@ -1,6 +1,7 @@
package mindustry.annotations.impl; package mindustry.annotations.impl;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.annotations.*; import mindustry.annotations.*;
@ -63,23 +64,28 @@ public class StructProcess extends BaseProcessor{
int size = varSize(var); int size = varSize(var);
TypeName varType = var.tname(); TypeName varType = var.tname();
String varName = var.name(); String varName = var.name();
boolean isBool = varType == TypeName.BOOLEAN;
//add val param to constructor //add val param to constructor
constructor.addParameter(varType, varName); constructor.addParameter(varType, varName);
//[get] field(structType) : fieldType //[get] field(structType) : fieldType
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.name().toString()) MethodSpec.Builder getter = MethodSpec.methodBuilder(var.name())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(varType) .returns(varType)
.addParameter(structType, structParam); .addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType //[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.name().toString()) MethodSpec.Builder setter = MethodSpec.methodBuilder(var.name())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType) .returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value"); .addParameter(structType, structParam).addParameter(varType, "value");
//field for offset
classBuilder.addField(FieldSpec.builder(structType, "bitMask" + Strings.capitalize(varName), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer(!isBool ? "($T)($L)" : "($T)(1L << $L)", structType, isBool ? offset : bitString(offset, size, structTotalSize)).build());
//[getter] //[getter]
if(varType == TypeName.BOOLEAN){ if(isBool){
//bools: single bit, is simplified //bools: single bit, is simplified
getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset); getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset);
}else if(varType == TypeName.FLOAT){ }else if(varType == TypeName.FLOAT){
@ -124,7 +130,7 @@ public class StructProcess extends BaseProcessor{
classBuilder.addJavadoc(doc.toString()); classBuilder.addJavadoc(doc.toString());
//add constructor final statement + add to class and build //add constructor final statement + add to class and build
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3)); constructor.addStatement("return ($T)($L)", structType, cons.substring(3));
classBuilder.addMethod(constructor.build()); classBuilder.addMethod(constructor.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer); JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);

View File

@ -298,13 +298,27 @@ public class ControlPathfinder{
if(avoid(type, x + y * wwidth)) return true; if(avoid(type, x + y * wwidth)) return true;
if(x == x2 && y == y2) return false; if(x == x2 && y == y2) return false;
//no diagonals //TODO no diagonals???? is this a good idea?
/*
//no diagonal ver
if(2 * err + dy > dx - 2 * err){ if(2 * err + dy > dx - 2 * err){
err -= dy; err -= dy;
x += sx; x += sx;
}else{ }else{
err += dx; err += dx;
y += sy; y += sy;
}*/
//diagonal ver
e2 = 2 * err;
if(e2 > -dy){
err -= dy;
x += sx;
}
if(e2 < dx){
err += dx;
y += sy;
} }
} }

View File

@ -92,7 +92,7 @@ public class Pathfinder implements Runnable{
for(int i = 0; i < tiles.length; i++){ for(int i = 0; i < tiles.length; i++){
Tile tile = world.tiles.geti(i); Tile tile = world.tiles.geti(i);
tiles[i] = packTile(tile); tiles[i] = packTile(tile, 0);
} }
preloadPath(getField(state.rules.waveTeam, costGround, fieldCore)); preloadPath(getField(state.rules.waveTeam, costGround, fieldCore));
@ -108,6 +108,34 @@ public class Pathfinder implements Runnable{
Events.on(ResetEvent.class, event -> stop()); Events.on(ResetEvent.class, event -> stop());
Events.on(TileChangeEvent.class, event -> updateTile(event.tile)); Events.on(TileChangeEvent.class, event -> updateTile(event.tile));
//remove nearSolid flag for tiles
Events.on(TilePreChangeEvent.class, event -> {
Tile tile = event.tile;
if(tile.solid()){
for(int i = 0; i < 4; i++){
Tile other = tile.nearby(i);
if(other != null){
//other tile needs to update its nearSolid to be false if it's not solid and this tile just got un-solidified
if(!other.solid()){
boolean otherNearSolid = false;
for(int j = 0; j < 4; j++){
Tile othernear = other.nearby(i);
if(othernear != null && othernear.solid()){
otherNearSolid = true;
break;
}
}
//the other tile is no longer near solid, remove the solid bit
if(!otherNearSolid){
tiles[other.array()] &= ~(PathTile.bitMaskNearSolid);
}
}
}
}
}
});
} }
private void clearCache(){ private void clearCache(){
@ -115,17 +143,23 @@ public class Pathfinder implements Runnable{
} }
/** Packs a tile into its internal representation. */ /** Packs a tile into its internal representation. */
private int packTile(Tile tile){ private int packTile(Tile tile, int prev){
boolean nearLiquid = false, nearSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.floor().isDeep(); boolean nearLiquid = false, nearSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.floor().isDeep();
for(int i = 0; i < 4; i++){ for(int i = 0; i < 4; i++){
Tile other = tile.nearby(i); Tile other = tile.nearby(i);
if(other != null){ if(other != null){
Floor floor = other.floor(); Floor floor = other.floor();
boolean osolid = other.solid();
if(floor.isLiquid) nearLiquid = true; if(floor.isLiquid) nearLiquid = true;
if(other.solid()) nearSolid = true; if(osolid) nearSolid = true;
if(!floor.isLiquid) nearGround = true; if(!floor.isLiquid) nearGround = true;
if(!floor.isDeep()) allDeep = false; if(!floor.isDeep()) allDeep = false;
//other tile is now near solid
if(solid){
tiles[other.array()] |= PathTile.bitMaskNearSolid;
}
} }
} }
@ -173,7 +207,7 @@ public class Pathfinder implements Runnable{
tile.getLinkedTiles(t -> { tile.getLinkedTiles(t -> {
int pos = t.array(); int pos = t.array();
if(pos < tiles.length){ if(pos < tiles.length){
tiles[pos] = packTile(t); tiles[pos] = packTile(t, tiles[pos]);
} }
}); });

View File

@ -70,7 +70,7 @@ public class CommandAI extends AIController{
faceTarget(); faceTarget();
} }
if(attackTarget == null && unit.within(targetPos, Math.max(5f, unit.hitSize) / 2.5f)){ if(attackTarget == null && unit.within(targetPos, Math.max(5f, unit.hitSize / 2.5f))){
targetPos = null; targetPos = null;
} }
}else if(target != null){ }else if(target != null){

View File

@ -253,6 +253,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
if(other != null){ if(other != null){
if(pass == 0){ if(pass == 0){
//first pass: delete existing blocks - this should automatically trigger removal if overlap exists //first pass: delete existing blocks - this should automatically trigger removal if overlap exists
//TODO pointless setting air to air?
other.setBlock(Blocks.air); other.setBlock(Blocks.air);
}else{ }else{
//second pass: assign changed data //second pass: assign changed data