This commit is contained in:
Anuken
2020-05-28 12:13:06 -04:00
parent ed795076f0
commit fbc2d13435
7 changed files with 68 additions and 37 deletions

View File

@ -17,7 +17,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class Pathfinder implements Runnable{ public class Pathfinder implements Runnable{
private static final long maxUpdate = Time.millisToNanos(4); private static final long maxUpdate = Time.millisToNanos(6);
private static final int updateFPS = 60; private static final int updateFPS = 60;
private static final int updateInterval = 1000 / updateFPS; private static final int updateInterval = 1000 / updateFPS;
private static final int impassable = -1; private static final int impassable = -1;
@ -37,6 +37,7 @@ public class Pathfinder implements Runnable{
private ObjectMap<Position, PathTarget> targetCache = new ObjectMap<>(); private ObjectMap<Position, PathTarget> targetCache = new ObjectMap<>();
/** Current pathfinding thread */ /** Current pathfinding thread */
private @Nullable Thread thread; private @Nullable Thread thread;
private IntArray tmpArray = new IntArray();
public Pathfinder(){ public Pathfinder(){
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
@ -198,14 +199,20 @@ public class Pathfinder implements Runnable{
if(target.refreshRate() > 0 && Time.timeSinceMillis(data.lastUpdateTime) > target.refreshRate()){ if(target.refreshRate() > 0 && Time.timeSinceMillis(data.lastUpdateTime) > target.refreshRate()){
data.lastUpdateTime = Time.millis(); data.lastUpdateTime = Time.millis();
tmpArray.clear();
data.target.getPositions(data.team, tmpArray);
synchronized(data.targets){ synchronized(data.targets){
//make sure the position actually changed
if(!(data.targets.size == 1 && tmpArray.size == 1 && data.targets.first() == tmpArray.first())){
data.targets.clear(); data.targets.clear();
data.target.getPositions(data.team, data.targets); data.target.getPositions(data.team, data.targets);
}
//queue an update //queue an update
queue.post(() -> updateTargets(data)); queue.post(() -> updateTargets(data));
} }
}
}
int[][] values = data.weights; int[][] values = data.weights;
int value = values[tile.x][tile.y]; int value = values[tile.x][tile.y];
@ -279,7 +286,7 @@ public class Pathfinder implements Runnable{
int tx = Point2.x(pos), ty = Point2.y(pos); int tx = Point2.x(pos), ty = Point2.y(pos);
path.weights[tx][ty] = 0; path.weights[tx][ty] = 0;
path.searches[tx][ty] = (short)path.search; path.searches[tx][ty] = path.search;
path.frontier.addFirst(pos); path.frontier.addFirst(pos);
} }
} }
@ -417,7 +424,7 @@ public class Pathfinder implements Runnable{
@Override @Override
public int refreshRate(){ public int refreshRate(){
return 1000 * 2; return 900;
} }
} }
@ -437,7 +444,7 @@ public class Pathfinder implements Runnable{
/** costs of getting to a specific tile */ /** costs of getting to a specific tile */
final int[][] weights; final int[][] weights;
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */ /** search IDs of each position - the highest, most recent search is prioritized and overwritten */
final short[][] searches; final int[][] searches;
/** search frontier, these are Pos objects */ /** search frontier, these are Pos objects */
final IntQueue frontier = new IntQueue(); final IntQueue frontier = new IntQueue();
/** all target positions; these positions have a cost of 0, and must be synchronized on! */ /** all target positions; these positions have a cost of 0, and must be synchronized on! */
@ -452,7 +459,7 @@ public class Pathfinder implements Runnable{
this.target = target; this.target = target;
this.weights = new int[width][height]; this.weights = new int[width][height];
this.searches = new short[width][height]; this.searches = new int[width][height];
this.frontier.ensureCapacity((width + height) * 3); this.frontier.ensureCapacity((width + height) * 3);
} }
} }

View File

@ -24,6 +24,11 @@ public class FormationAI extends AIController implements FormationMember{
@Override @Override
public void update(){ public void update(){
if(leader.dead()){
unit.resetController();
return;
}
unit.controlWeapons(leader.isRotate(), leader.isShooting()); unit.controlWeapons(leader.isRotate(), leader.isShooting());
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed)); // unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
if(leader.isShooting()){ if(leader.isShooting()){
@ -45,6 +50,11 @@ public class FormationAI extends AIController implements FormationMember{
unit.moveAt(realtarget.sub(unit).limit(unit.type().speed)); unit.moveAt(realtarget.sub(unit).limit(unit.type().speed));
} }
@Override
public void removed(Unitc unit){
formation.removeMember(this);
}
@Override @Override
public boolean isBeingControlled(Unitc player){ public boolean isBeingControlled(Unitc player){
return leader == player; return leader == player;

View File

@ -71,6 +71,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return controller; return controller;
} }
public void resetController(){
controller(type.createController());
}
@Override @Override
public void set(UnitType def, UnitController controller){ public void set(UnitType def, UnitController controller){
type(type); type(type);
@ -125,6 +129,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void remove(){ public void remove(){
teamIndex.updateCount(team(), -1); teamIndex.updateCount(team(), -1);
controller.removed(this);
} }
@Override @Override

View File

@ -15,6 +15,10 @@ public interface UnitController{
} }
default void removed(Unitc unit){
}
default boolean isBeingControlled(Unitc player){ default boolean isBeingControlled(Unitc player){
return false; return false;
} }

View File

@ -21,6 +21,8 @@ public enum Binding implements KeyBind{
pickupCargo(KeyCode.leftBracket), pickupCargo(KeyCode.leftBracket),
dropCargo(KeyCode.rightBracket), dropCargo(KeyCode.rightBracket),
command(KeyCode.g),
clear_building(KeyCode.q), clear_building(KeyCode.q),
pause_building(KeyCode.e), pause_building(KeyCode.e),
rotate(new Axis(KeyCode.scroll)), rotate(new Axis(KeyCode.scroll)),

View File

@ -4,7 +4,6 @@ import arc.*;
import arc.Graphics.*; import arc.Graphics.*;
import arc.Graphics.Cursor.*; import arc.Graphics.Cursor.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.input.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.scene.*; import arc.scene.*;
@ -211,31 +210,6 @@ public class DesktopInput extends InputHandler{
Call.onUnitClear(player); Call.onUnitClear(player);
controlledType = null; controlledType = null;
} }
//TODO this is for debugging, remove later
if(Core.input.keyTap(KeyCode.g) && !player.dead() && player.unit() instanceof Commanderc){
Commanderc commander = (Commanderc)player.unit();
if(commander.isCommanding()){
commander.clearCommand();
}else{
FormationPattern pattern = new SquareFormation();
Formation formation = new Formation(new Vec3(player.x(), player.y(), player.unit().rotation()), pattern);
formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern);
units.clear();
Fx.commandSend.at(player);
Units.nearby(player.team(), player.x(), player.y(), 200f, u -> {
if(u.isAI()){
units.add(u);
}
});
commander.command(formation, units);
}
}
} }
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){ if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
@ -628,5 +602,33 @@ public class DesktopInput extends InputHandler{
pay.dropLastPayload(); pay.dropLastPayload();
} }
} }
if(unit instanceof Commanderc){
Commanderc commander = (Commanderc)unit;
if(Core.input.keyTap(Binding.command)){
if(commander.isCommanding()){
commander.clearCommand();
}else{
FormationPattern pattern = new SquareFormation();
Formation formation = new Formation(new Vec3(player.x(), player.y(), player.unit().rotation()), pattern);
formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern);
units.clear();
Fx.commandSend.at(player);
Units.nearby(player.team(), player.x(), player.y(), 200f, u -> {
if(u.isAI()){
units.add(u);
}
});
units.sort(u -> u.dst2(player.unit()));
units.truncate(unit.type().commandLimit);
commander.command(formation, units);
}
}
}
} }
} }

View File

@ -42,6 +42,7 @@ public class UnitType extends UnlockableContent{
public boolean canBoost = false; public boolean canBoost = false;
public float sway = 1f; public float sway = 1f;
public int payloadCapacity = 1; public int payloadCapacity = 1;
public int commandLimit = 24;
public int legCount = 4; public int legCount = 4;
public float legLength = 24f, legSpeed = 0.1f, legTrns = 1f; public float legLength = 24f, legSpeed = 0.1f, legTrns = 1f;