Files
sunny9898/task8/_ref/xxx_flow-field-pathfinding-processing-master/flow_field/Group.pde
louiscklaw 5637fbf94f update,
2025-02-01 02:07:58 +08:00

180 lines
4.9 KiB
Plaintext

// Formations
final int NONE = 0;
final int BOX = 1;
final int LINE = 2;
final int VEE = 3;
// Spacing
final int DIRECT_SPACING = 12;
final int DIAGONAL_SPACING = 8;
class Group {
int curFormation;
ArrayList<Agent> agents;
Group(int formation, ArrayList<Agent> agents) {
this.agents = agents;
SetFormation(formation);
}
void RmAgents(ArrayList<Agent> rmAgents) {
for (int i = 0; i < rmAgents.size(); ++i) {
if (agents.contains(rmAgents.get(i))) {
agents.remove(rmAgents.get(i));
}
}
}
void AddAgent(Agent a) {
this.agents.add(a);
}
void SetDest(PVector dest) {
if (this.curFormation == NONE) {
for (int i = 0; i < agents.size(); ++i) {
agents.get(i).SetDest(dest,
grid.Pathing(grid.CalcFromScreenCoords(agents.get(i).GetPos()), grid.CalcFromScreenCoords(dest)));
}
return;
}
// Pathfind the leader only
agents.get(0).SetDest(dest,
grid.Pathing(grid.CalcFromScreenCoords(agents.get(0).GetPos()), grid.CalcFromScreenCoords(dest)));
SetFollowDestinations();
}
void Move() {
if (this.curFormation == NONE) {
for (int i = 0; i < agents.size(); ++i) {
agents.get(i).GridPathing();
}
return;
}
agents.get(0).GridPathing();
SetFollowDestinations();
for (int i = 1; i < agents.size(); ++i) {
agents.get(i).FollowerPathing(agents.get(0).GetPos());
}
}
private void SetFollowDestinations() {
if (this.curFormation == NONE) {
return;
}
for (int i = 1; i < agents.size(); ++i) {
PVector nextPos = NextPosition(this.curFormation, i);
float s = sin(agents.get(0).orientation);
float c = cos(agents.get(0).orientation);
nextPos = new PVector((nextPos.x * c) - (nextPos.y * s), (nextPos.x * s) + (nextPos.y * c));
nextPos.add(agents.get(0).GetPos());
agents.get(i).SetDest(nextPos, null);
}
}
void SwapAgents(int a, int b) {
Agent aa = agents.get(a);
agents.set(a, agents.get(b));
agents.set(b, aa);
}
void SetFormation(int f) {
this.curFormation = f;
if (f == NONE) {
return;
}
// Get leader and move him to index 0
float totalX = 0;
float totalY = 0;
for (int i = 0; i < agents.size(); ++i) {
totalX += agents.get(i).GetPos().x;
totalY += agents.get(i).GetPos().y;
}
PVector centerPos = new PVector(totalX / agents.size(), totalY / agents.size());
int leader = GetUnitClosestTo(centerPos, 0);
SwapAgents(leader, 0);
agents.get(0).SetDest(centerPos, null);
for (int i = 1; i < agents.size(); ++i) {
PVector nextPos = NextPosition(f, i);
float s = sin(agents.get(0).orientation);
float c = cos(agents.get(0).orientation);
nextPos = new PVector(nextPos.x * c - nextPos.y * s, nextPos.x * s + nextPos.y * c);
nextPos.add(agents.get(0).GetPos());
int nextUnit = GetUnitClosestTo(nextPos, i);
SwapAgents(nextUnit, i);
agents.get(i).SetDest(nextPos, null);
}
}
private int GetUnitClosestTo(PVector pos, int from) {
float closestDist = Float.MAX_VALUE;
int closest = from;
for (int i = from; i < agents.size(); ++i) {
PVector aPos = agents.get(i).GetPos();
float dist = dist(aPos.x, aPos.y, pos.x, pos.y);
if (dist < closestDist) {
closestDist = dist;
closest = i;
}
}
return closest;
}
private PVector NextPosition(int f, int unit) {
switch(f) {
case BOX:
return Box(unit);
case LINE:
return Line(unit);
case VEE:
return Vee(unit);
default:
return new PVector(0, 0);
}
}
// All formation functions return an offset from the leader
private PVector Box(int unit) {
int multiple = ((unit-1) / 8)+1;
int counter = (unit-1) % 8;
switch(counter) {
case 0:
return new PVector(multiple * DIRECT_SPACING, 0);
case 1:
return new PVector(multiple * DIRECT_SPACING, multiple * DIRECT_SPACING);
case 2:
return new PVector(0, multiple * DIRECT_SPACING);
case 3:
return new PVector(multiple * -DIRECT_SPACING, multiple * DIRECT_SPACING);
case 4:
return new PVector(multiple * -DIRECT_SPACING, 0);
case 5:
return new PVector(multiple * -DIRECT_SPACING, multiple * -DIRECT_SPACING);
case 6:
return new PVector(0, multiple * -DIRECT_SPACING);
case 7:
return new PVector(multiple * DIRECT_SPACING, multiple * -DIRECT_SPACING);
default:
return new PVector(0, 0);
}
}
private PVector Line(int unit) {
if (unit % 2 == 0) {
return new PVector((unit-(unit/2)) * DIRECT_SPACING, 0);
}
return new PVector((unit-(unit/2)) * -DIRECT_SPACING, 0);
}
private PVector Vee(int unit) {
if (unit % 2 == 0) {
return new PVector((unit-(unit/2)) * DIRECT_SPACING, (unit/2) * -DIAGONAL_SPACING);
}
return new PVector((unit-(unit/2)) * -DIRECT_SPACING, ((unit/2)+1) * -DIAGONAL_SPACING);
}
}