KAgent example 2d flock
From KokkugiaWiki
in addition to the kAgent class this example has a world class to control the population of agents.
the world class holds an arrayList of all the agents and uses this array list to pass each agent to every other agent in order that they can interact.
applet - kAgent population
sketch
import kGeom.*;
kWorld world1;
void setup(){
size(500,500);
frameRate(30);
smooth();
world1 = new kWorld();
for (int i = 0; i < 50; i++) {
world1.addAgent(new kAgent(new kVec(random(500),random(500)), new kVec(random(-1,1),random(-1,1)), 5, 0.2));
}
}
void draw(){
background(125);
world1.run();
}
kAgent
// simple 2D agent class - using code from dan shiffman
// roland snooks | kokkugia.com | 2007
class kAgent{
kVec acc;
kVec vel;
kVec pos;
kVec vec;
float maxVel;
float maxForce;
float wandertheta;
// constructor
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
acc = new kVec(0,0);
vel = new kVec(0,0);
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
}
// calculates new location
void update(ArrayList pop){
//this.wander();
//this.seek(new kVec(mx,my));
kVec sep = separate(pop); // Separation
kVec ali = align(pop); // Alignment
kVec coh = cohesion(pop); // Cohesion
// Arbitrarily weight these forces
sep.scale(5.0);
ali.scale(1.0);
coh.scale(1.0);
// Add the force vectors to acceleration
acc.plus(sep);
acc.plus(ali);
acc.plus(coh);
vel.plus(acc);
vel.limit(maxVel);
pos.plus(vel);
acc = new kVec(0,0); // reset acc to 0 each iteration
borders();
render();
}
// seek
void seek(kVec target) {
acc.plus(steer(target));
}
// steer
kVec steer(kVec target) {
kVec steer; // The steering vector
target.minus(pos);
float distance = target.length();
if (distance > 0) {
target.normalize();
target.scale(maxVel);
target.minus(vel);
//steer = kVec.clone(target);
target.limit(maxForce);
}
else {
target = new kVec(0,0);
}
return target;
}
void wander() {
float wanderR = 16;
float wanderD = 60;
float change = 0.25;
wandertheta += random(-change,change);
kVec circleloc = kVec.clone(vel);
circleloc.normalize();
circleloc.scale(wanderD);
circleloc.plus(pos);
kVec circleOffSet = new kVec(wanderR*cos(wandertheta),wanderR*sin(wandertheta));
circleOffSet.plus(circleloc);
acc.plus(steer(circleOffSet));
}
// separation
kVec separate (ArrayList pop) {
float desiredseparation = 25.0;
kVec sum = new kVec(0,0,0);
int count = 0;
for (int i = 0 ; i < pop.size(); i++) {
kAgent other = (kAgent) pop.get(i);
float dist = pos.distance(other.pos);
// if the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((dist > 0) && (dist < desiredseparation)) {
// calculate vector pointing away from neighbor
kVec diff = kVec.clone(pos);
diff.minus(other.pos);
diff.normalize();
diff.scale(1/dist); // weight by distance
sum.plus(diff);
count++; // keep track of how many
}
}
// average -- divide by how many
if (count > 0) {
sum.scale(1/(float)count);
}
return sum;
}
// alignment
kVec align (ArrayList pop) {
float neighbordist = 50.0;
kVec sum = new kVec(0,0,0);
int count = 0;
for (int i = 0 ; i < pop.size(); i++) {
kAgent other = (kAgent) pop.get(i);
float dist = pos.distance(other.pos);
if ((dist > 0) && (dist < neighbordist)) {
sum.plus(other.vel);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
sum.limit(maxForce);
}
return sum;
}
// cohesion
kVec cohesion (ArrayList pop) {
float neighbordist = 50.0f;
kVec sum = new kVec(0,0,0);
int count = 0;
for (int i = 0 ; i < pop.size(); i++) {
kAgent other = (kAgent) pop.get(i);
float dist = pos.distance(other.pos);
if ((dist > 0) && (dist < neighbordist)) {
sum.plus(other.pos); // Add location
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
return steer(sum); // steer towards the location
}
return sum;
}
void render() {
fill(200);
stroke(255);
ellipse(pos.x,pos.y,10,10);
}
void borders() {
if (pos.x < 0) pos.x = width;
if (pos.y < 0) pos.y = height;
if (pos.x > width) pos.x = 0;
if (pos.y > height) pos.y = 0;
}
}
kWorld
class kWorld {
ArrayList population;
kWorld() {
population = new ArrayList(); // initialize the arraylist
}
// cycles through each agent passing the population to it
void run(){
for (int i = 0; i < population.size(); i++) {
kAgent a = (kAgent) population.get(i);
a.update(population);
}
}
// add agent
void addAgent(kAgent a) {
population.add(a);
}
}
