Matt evans, gordon lai + chris ward
From KokkugiaWiki
Board 1:
Iteration 3:

Iteration 2:

Iteration 1:

LATEST CODE:
import kGeom.*;
import kRender.*;
PrintWriter output;
kSpace space;
kWorld world1;
float envSize = 300;
void setup(){
size(500,500,P3D);
frameRate(50);
space = new kSpace(this);
space.cam.jump(-600,-550,-500);
world1 = new kWorld();
// create structure
for (int i = 0; i < 1000; i++) {
world1.addAgentStructure(new kAgentStructure(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 10, 0.5));
}
//create volume
for (int i = 0; i < 5; i++) {
world1.addAgentVolume(new kAgentVolume(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 0.5, 0.06));
}
//create skin
for (int i = 0; i < 500; i++) {
world1.addAgentSkin(new kAgentSkin(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 5, 0.06));
}
}
void draw(){
background(255);
int mx = mouseX;
int my = mouseY;
world1.run();
kRange rng = new kRange(300);
rng.setColor(100);
space.append(rng);
if (mousePressed) {
exportToTxt();
}
space.render();
space.init();
}
void mouseDragged(){
space.mouseDragged();
}
void exportToTxt() {
output = createWriter("networkExport.txt");
for (int i = 0; i < world1.lines.size(); i++) { // LINES
kLine l = (kLine) world1.lines.get(i);
kVec start = l.StartPoint();
kVec end = l.EndPoint();
output.println(start.x + "," + start.y + "," + start.z + " " + end.x + "," + end.y + "," + end.z);
}
output.flush();
output.close();
}
// kAGent
// simple 3D agent class - based on code from dan shiffman
// roland snooks | kokkugia.com | 2007
class kAgent{
kVec acc;
kVec vel;
kVec pos;
kVec vec;
float maxVel;
float maxForce;
float sepScale;
float aliScale;
float cohScale;
float rangeOfVision;
float wandertheta;
float attOffset = 200;
float ht = envSize*2;
int drawColor;
String agentType = "kAgent";
kVec sumSep = new kVec(0,0,0);
// constructor simple
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
acc = new kVec(0,0,0);
vel = new kVec(random(-1,1),random(-1,1),random(-1,1));
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = 7;
aliScale = 0.7;
cohScale = 1;
rangeOfVision = 70;
drawColor = 255;
}
// constructor complete
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce,
kVec _vel,
float _sepScale,
//float _aliScale, //**
float _cohScale,
float _rangeOfVision){
acc = new kVec(0,0,0);
vel = kVec.clone(_vel);
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = _sepScale;
//aliScale = _aliScale; //**
cohScale = _cohScale;
rangeOfVision = _rangeOfVision;
drawColor = 255;
}
// calculates new location
void step(kWorld world){
updatePop(world);
vel.plus(acc);
vel.limit(maxVel);
pos.plus(vel);
acc = new kVec(0,0,0); // reset acc to 0 each iteration
borders(envSize);
render();
}
void updatePop(kWorld world){
}
// steer
kVec steer(kVec target, float threshold) {
target.minus(pos);
float dist = target.length();
if (dist > 0 && dist < threshold) {
target.normalize();
target.scale(maxVel);
target.minus(vel);
target.limit(maxForce);
}
else {
target = new kVec(0,0,0);
}
return target;
}
// seek
void seek(kVec target, float threshold) {
acc.plus(steer(target, threshold));
}
// separation
kVec separate (ArrayList pop, float sepDist) {
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 < sepDist)) {
kVec diff = kVec.clone(pos);
diff.minus(other.pos);
diff.normalize();
diff.scale(1/dist);
sum.plus(diff);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
}
sumSep = kVec.clone(sum);
return sum;
}
// alignment
kVec align (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.vel);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
sum.limit(maxForce);
}
return sum;
}
// cohesion
kVec cohesion (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.pos);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
return steer(sum, ht);
}
return sum;
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale); // LINES
ln.setColor(255,0,0);
//space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(drawColor);
space.append(ln2);
}
void network(ArrayList pop, float threshold){
//loop through all the agents and check their distance
float closestDist = 1000000;
int closestAgent = 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 < threshold){
if(i == 0 && dist > 0){
closestDist = dist;
closestAgent = 0;
count++;
}else{
if(dist < closestDist && dist > 0){
closestDist = dist;
closestAgent = i;
count++;
}
}
}
}
if(count > 0){
kAgent other = (kAgent) pop.get(closestAgent);
kLine l = new kLine(pos, other.pos);
l.setColor(150);
space.append(l);
world1.addLine(l);
}
}
void borders(float envSize) {
if (pos.x < -envSize) pos.x = envSize;
if (pos.y < -envSize) pos.y = envSize;
if (pos.z < -envSize) pos.z = envSize;
if (pos.x > envSize) pos.x = -envSize;
if (pos.y > envSize) pos.y = -envSize;
if (pos.z > envSize) pos.z = -envSize;
}
}
// kAgentStructure
class kAgentSkin extends kAgent{
kAgentSkin(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentStructure";
}
void updatePop(kWorld world){
float sepVolScale = 2;
kVec seekVol = seekStructure(world.volume);
// call population functions
kVec sepVol = separate(world.volume, 1000); // 100
kVec sep = separate(world.skin, 2000); // 20
kVec coh = cohesion(world.skin);
// weight vector
seekVol.scale(1);
sepVol.scale(100); // 100
sep.scale(10); // 10
coh.scale(.065);
// add the vectors to acceleration
acc.plus(seekVol);
acc.plus(sepVol);
acc.plus(sep);
acc.plus(coh);
}
/* // seek closest agent
kAgent other = (kAgent) pop.get(closestAgent);
kVec target = kVec.clone(other.pos);
this.seek(target, 300);
}*/
// seek volume
kVec seekStructure(ArrayList vol){
// return a vector for seeking the volumes
// find closest agent
float closestDist = envSize*envSize;
int closestAgent = 0;
for(int i = 0; i<vol.size(); i++){
kAgent other = (kAgent) vol.get(i);
float dist = pos.distance(other.pos);
if(i > 0){
if(dist < closestDist && dist > 100){
closestDist = dist;
closestAgent = i;
}
}
else{
closestDist = dist;
closestAgent = 0;
}
}
// seek closest agent
kAgent other = (kAgent) vol.get(closestAgent);
kVec target = kVec.clone(other.pos);
return steer(target, 300); //300
}
void render() {
// draw vectors
float vecDisScale = 2;
/*kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
//space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(0);
space.append(ln2);*/
// skin color
float attDisScale = 2;
kLine ln0 = new kLine(pos.x,pos.y,pos.z - attDisScale,pos.x,pos.y,pos.z + attDisScale);
//kLine ln1a = new kLine(pos.x,pos.y - attDisScale,pos.z,pos.x,pos.y + attDisScale,pos.z);
//kLine ln2a = new kLine(pos.x - attDisScale,pos.y,pos.z,pos.x + attDisScale,pos.y,pos.z);
ln0.setColor(0,200,0);
//ln1a.setColor(0,200,0);
//ln2a.setColor(0,200,0);
space.append(ln0);
//space.append(ln1a);
//space.append(ln2a);
}
}
// kAgentSkin
class kAgentStructure extends kAgent{
kAgentStructure(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentStructure";
rangeOfVision = 100;
}
void updatePop(kWorld world){
float sepVolScale = 2;
kVec seekVol = seekStructure(world.volume);
// call population functions
kVec sepVol = separate(world.volume, 100); // 100
kVec sep = separate(world.skin, 20); // 20
kVec coh = cohesion(world.skin);
// weight vector
seekVol.scale(100);
sepVol.scale(1200);
sep.scale(1200);
coh.scale(.095);
// add the vectors to acceleration
acc.plus(seekVol);
acc.plus(sepVol);
acc.plus(sep);
acc.plus(coh);
}
/* // seek closest agent
kAgent other = (kAgent) pop.get(closestAgent);
kVec target = kVec.clone(other.pos);
this.seek(target, 300);
}*/
// seek volume
kVec seekStructure(ArrayList vol){
// return a vector for seeking the volumes
// find closest agent
float closestDist = envSize*envSize;
int closestAgent = 0;
for(int i = 0; i<vol.size(); i++){
kAgent other = (kAgent) vol.get(i);
float dist = pos.distance(other.pos);
if(i > 0){
if(dist < closestDist && dist > 100){
closestDist = dist;
closestAgent = i;
}
}
else{
closestDist = dist;
closestAgent = 0;
}
}
// seek closest agent
kAgent other = (kAgent) vol.get(closestAgent);
kVec target = kVec.clone(other.pos);
return steer(target, 300); //300
}
void render() {
// draw vectors
float vecDisScale = 5;
// structure connecting lines
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
//space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(0);
space.append(ln2);
// strucure color
float attDisScale = 1;
kLine ln0 = new kLine(pos.x,pos.y,pos.z - attDisScale,pos.x,pos.y,pos.z + attDisScale);
ln0.setColor(0,0,0);
space.append(ln0);
}
}
//kAgentVolume
class kAgentVolume extends kAgent{
kAgentVolume(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentVolume";
}
void updatePop(ArrayList pop){
// call population functions
kVec sep = separate(pop, 50);
kVec ali = align(pop);
kVec coh = cohesion(pop);
// weight vector
sep.scale(sepScale);
ali.scale(aliScale);
coh.scale(cohScale);
// add the vectors to acceleration
acc.plus(sep);
acc.plus(ali); //**
acc.plus(coh);
}
void render(){
float attDisScale = 5;
kLine ln0 = new kLine(pos.x,pos.y,pos.z - attDisScale,pos.x,pos.y,pos.z + attDisScale);
kLine ln1 = new kLine(pos.x,pos.y - attDisScale,pos.z,pos.x,pos.y + attDisScale,pos.z);
kLine ln2 = new kLine(pos.x - attDisScale,pos.y,pos.z,pos.x + attDisScale,pos.y,pos.z);
ln0.setColor(0,0,255);
ln1.setColor(0,0,255);
ln2.setColor(0,0,255);
space.append(ln0);
space.append(ln1);
space.append(ln2);
}
}
// kAgentWorld
// a class which controls the agent population arraylist
class kWorld {
ArrayList lines; // LINES
ArrayList volume;
ArrayList structure;
ArrayList skin;
kWorld() {
lines = new ArrayList(); // LINES
volume = new ArrayList();
structure = new ArrayList();
skin = new ArrayList();
}
// cycles through each agent passing the population to it
void run(){
for (int i = 0; i < volume.size(); i++) {
kAgent a = (kAgent) volume.get(i);
a.step(this);
}
for (int i = 0; i < structure.size(); i++) {
kAgent a = (kAgent) structure.get(i);
a.step(this);
}
for (int i = 0; i < skin.size(); i++) {
kAgent a = (kAgent) skin.get(i);
a.step(this);
}
lines = new ArrayList();
for (int i = 0; i < structure.size(); i++) {
kAgent a = (kAgent) structure.get(i);
//a.network(world.population, 50, 5);
a.network(structure, 100);
}
}
// adds an agent to the population
void addAgentVolume(kAgent a) {
volume.add(a);
}
void addAgentSkin(kAgent a) {
skin.add(a);
}
void addAgentStructure(kAgent a) {
structure.add(a);
}
// adds a line to lines // LINES
void addLine(kLine l) {
lines.add(l);
}
}
import kGeom.*;
import kRender.*;
PrintWriter output;
kSpace space;
kWorld world1;
float envSize = 300;
void setup(){
size(500,500,P3D);
frameRate(50);
space = new kSpace(this);
space.cam.jump(-600,-550,-500);
world1 = new kWorld();
// create agents
for (int i = 0; i < 300; i++) {
world1.addAgentSkin(new kAgentSkin(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 10, 0.5));
}
for (int i = 0; i < 5; i++) {
world1.addAgentVolume(new kAgentVolume(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 0.5, 0.06));
}
}
void draw(){
background(255);
int mx = mouseX;
int my = mouseY;
world1.run();
kRange rng = new kRange(300);
rng.setColor(100);
space.append(rng);
if (mousePressed) {
exportToTxt();
}
space.render();
space.init();
}
void mouseDragged(){
space.mouseDragged();
}
void exportToTxt() {
output = createWriter("networkExport.txt");
for (int i = 0; i < world1.lines.size(); i++) { // LINES
kLine l = (kLine) world1.lines.get(i);
kVec start = l.StartPoint();
kVec end = l.EndPoint();
output.println(start.x + "," + start.y + "," + start.z + " " + end.x + "," + end.y + "," + end.z);
}
output.flush();
output.close();
}
// kAGent
// simple 3D agent class - based on code from dan shiffman
// roland snooks | kokkugia.com | 2007
class kAgent{
kVec acc;
kVec vel;
kVec pos;
kVec vec;
float maxVel;
float maxForce;
float sepScale;
float aliScale;
float cohScale;
float rangeOfVision;
float wandertheta;
float attOffset = 200;
float ht = envSize*2;
int drawColor;
String agentType = "kAgent";
kVec sumSep = new kVec(0,0,0);
// constructor simple
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
acc = new kVec(0,0,0);
vel = new kVec(random(-1,1),random(-1,1),random(-1,1));
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = 7;
aliScale = 0.7;
cohScale = 1;
rangeOfVision = 70;
drawColor = 255;
}
// constructor complete
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce,
kVec _vel,
float _sepScale,
//float _aliScale, //**
float _cohScale,
float _rangeOfVision){
acc = new kVec(0,0,0);
vel = kVec.clone(_vel);
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = _sepScale;
//aliScale = _aliScale; //**
cohScale = _cohScale;
rangeOfVision = _rangeOfVision;
drawColor = 255;
}
// calculates new location
void step(kWorld world){
updatePop(world);
vel.plus(acc);
vel.limit(maxVel);
pos.plus(vel);
acc = new kVec(0,0,0); // reset acc to 0 each iteration
borders(envSize);
render();
}
void updatePop(kWorld world){
}
// steer
kVec steer(kVec target, float threshold) {
target.minus(pos);
float dist = target.length();
if (dist > 0 && dist < threshold) {
target.normalize();
target.scale(maxVel);
target.minus(vel);
target.limit(maxForce);
}
else {
target = new kVec(0,0,0);
}
return target;
}
// seek
void seek(kVec target, float threshold) {
acc.plus(steer(target, threshold));
}
// separation
kVec separate (ArrayList pop) {
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 < rangeOfVision/1.5)) {
kVec diff = kVec.clone(pos);
diff.minus(other.pos);
diff.normalize();
diff.scale(1/dist);
sum.plus(diff);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
}
sumSep = kVec.clone(sum);
return sum;
}
// alignment
kVec align (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.vel);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
sum.limit(maxForce);
}
return sum;
}
// cohesion
kVec cohesion (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.pos);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
return steer(sum, ht);
}
return sum;
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale); // LINES
ln.setColor(255,0,0);
space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(drawColor);
space.append(ln2);
}
void network(ArrayList pop, float threshold){
//loop through all the agents and check their distance
float closestDist = 1000000;
int closestAgent = 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 < threshold){
if(i == 0 && dist > 0){
closestDist = dist;
closestAgent = 0;
count++;
}else{
if(dist < closestDist && dist > 0){
closestDist = dist;
closestAgent = i;
count++;
}
}
}
}
if(count > 0){
kAgent other = (kAgent) pop.get(closestAgent);
kLine l = new kLine(pos, other.pos);
l.setColor(150);
space.append(l);
world1.addLine(l);
}
}
void borders(float envSize) {
if (pos.x < -envSize) pos.x = envSize;
if (pos.y < -envSize) pos.y = envSize;
if (pos.z < -envSize) pos.z = envSize;
if (pos.x > envSize) pos.x = -envSize;
if (pos.y > envSize) pos.y = -envSize;
if (pos.z > envSize) pos.z = -envSize;
}
}
// kAgentSkin
class kAgentSkin extends kAgent{
kAgentSkin(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentStructure";
}
void updatePop(kWorld world){
float sepVolScale = 2;
//kVec seekVol = seekVolume(world.volume);
// call population functions
kVec sepVol = separate(world.volume);
kVec sep = separate(world.skin);
kVec coh = cohesion(world.skin);
// weight vector
//seekVol.scale(seekVolScale);
sepVol.scale(sepVolScale);
sep.scale(sepScale);
coh.scale(cohScale);
// add the vectors to acceleration
//acc.plus(seekVol);
acc.plus(sepVol);
acc.plus(sep);
acc.plus(coh);
}
// seek volume
kVec seekVolume(){
// return a vector for seeking the volumes
return new kVec(0,0,0);
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(0);
space.append(ln2);
}
}
// kAgentStructure
class kAgentStructure extends kAgent{
kAgentStructure(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentStructure";
}
void updatePop(ArrayList pop){
// seek pray
// find closest agent
float closestDist = envSize*envSize;
int closestAgent = 0;
for(int i = 0; i<pop.size(); i++){
kAgent other = (kAgent) pop.get(i);
if(other.agentType == "kAgent"){
float dist = pos.distance(other.pos);
if(i > 0){
if(dist < closestDist){
closestDist = dist;
closestAgent = i;
}
}else{
closestDist = dist;
closestAgent = 0;
}
}
}
// seek closest agent
kAgent other = (kAgent) pop.get(closestAgent);
kVec target = kVec.clone(other.pos);
this.seek(target, 300);
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(0);
space.append(ln2);
}
}
//kAgentVolume
class kAgentVolume extends kAgent{
kAgentVolume(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentVolume";
}
void updatePop(ArrayList pop){
// call population functions
kVec sep = separate(pop);
kVec ali = align(pop);
kVec coh = cohesion(pop);
// weight vector
sep.scale(sepScale);
ali.scale(aliScale);
coh.scale(cohScale);
// add the vectors to acceleration
acc.plus(sep);
acc.plus(ali); //**
acc.plus(coh);
}
void render(){
float attDisScale = 5;
kLine ln0 = new kLine(pos.x,pos.y,pos.z - attDisScale,pos.x,pos.y,pos.z + attDisScale);
kLine ln1 = new kLine(pos.x,pos.y - attDisScale,pos.z,pos.x,pos.y + attDisScale,pos.z);
kLine ln2 = new kLine(pos.x - attDisScale,pos.y,pos.z,pos.x + attDisScale,pos.y,pos.z);
ln0.setColor(0,0,255);
ln1.setColor(0,0,255);
ln2.setColor(0,0,255);
space.append(ln0);
space.append(ln1);
space.append(ln2);
}
}
// kAgentWorld
// a class which controls the agent population arraylist
class kWorld {
ArrayList lines; // LINES
ArrayList volume;
ArrayList structure;
ArrayList skin;
kWorld() {
lines = new ArrayList(); // LINES
volume = new ArrayList();
structure = new ArrayList();
skin = new ArrayList();
}
// cycles through each agent passing the population to it
void run(){
for (int i = 0; i < volume.size(); i++) {
kAgent a = (kAgent) volume.get(i);
a.step(this);
}
for (int i = 0; i < structure.size(); i++) {
kAgent a = (kAgent) structure.get(i);
a.step(this);
}
for (int i = 0; i < skin.size(); i++) {
kAgent a = (kAgent) skin.get(i);
a.step(this);
}
lines = new ArrayList();
for (int i = 0; i < skin.size(); i++) {
kAgent a = (kAgent) skin.get(i);
//a.network(world.population, 50, 5);
a.network(skin, 100);
}
}
// adds an agent to the population
void addAgentVolume(kAgent a) {
volume.add(a);
}
void addAgentStructure(kAgent a) {
structure.add(a);
}
void addAgentSkin(kAgent a) {
skin.add(a);
}
// adds a line to lines // LINES
void addLine(kLine l) {
lines.add(l);
}
}
import kGeom.*;
import kRender.*;
kSpace space;
kWorld world1;
float envSize = 300;
void setup(){
size(500,500,P3D);
frameRate(50);
space = new kSpace(this);
space.cam.jump(-600,-550,-500);
world1 = new kWorld();
// create agents
for (int i = 0; i < 300; i++) {
world1.addAgent(new kAgentPrey(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 4, 0.2));
}
for (int i = 0; i < 10; i++) {
world1.addAgent(new kAgentPredator(new kVec(random(-250,250),random(-250,250),random(-250,250)), new kVec(random(-1,1),random(-1,1),random(-1,1)), 12, 0.06));
}
for (int i = 0; i < 100; i++) {
world1.addAgent(new kAgent(new kVec(random(500),random(500),random(500)), new kVec(random(-1,1),random(-1,1), random(-1,1)), 1, 0.2));
}
}
void draw(){
background(255);
int mx = mouseX;
int my = mouseY;
world1.run();
kRange rng = new kRange(300);
rng.setColor(100);
space.append(rng);
// if target distance < 20 then deleteAgent()
/*if() {
}*/
space.render();
space.init();
}
void mouseDragged(){
space.mouseDragged();
}
class kAgent{
kVec acc;
kVec vel;
kVec pos;
kVec vec;
float maxVel;
float maxForce;
float sepScale;
float aliScale;
float cohScale;
float rangeOfVision;
float wandertheta;
float attOffset = 200;
float ht = envSize*2;
int drawColor;
String agentType = "kAgent";
kVec sumSep = new kVec(0,0,0);
// constructor simple
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
acc = new kVec(0,0,0);
vel = new kVec(random(-1,1),random(-1,1),random(-1,1));
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = 7;
aliScale = 0.7;
cohScale = 1;
rangeOfVision = 70;
drawColor = 255;
}
// constructor complete
kAgent(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce,
kVec _vel,
float _sepScale,
float _aliScale,
float _cohScale,
float _rangeOfVision){
acc = new kVec(0,0,0);
vel = kVec.clone(_vel);
pos = kVec.clone(_pos);
vec = kVec.clone(_vec);
maxVel = _maxVel;
maxForce = _maxForce;
sepScale = _sepScale;
aliScale = _aliScale;
cohScale = _cohScale;
rangeOfVision = _rangeOfVision;
drawColor = 255;
}
// calculates new location
void step(kWorld world){
updatePop(world.population);
vel.plus(acc);
vel.limit(maxVel);
pos.plus(vel);
acc = new kVec(0,0,0); // reset acc to 0 each iteration
borders(envSize);
render();
}
int setMode(kVec maxForce) {
if (maxForce < 0){
return 1;
}
else if (maxForce > 1){
return 3;
}
else {
return 2;
}
}
void updatePop(ArrayList pop){
// call population functions
kVec sep = separate(pop);
kVec ali = align(pop);
kVec coh = cohesion(pop);
// weight vector
sep.scale(sepScale);
ali.scale(aliScale);
coh.scale(cohScale);
// add the vectors to acceleration
acc.plus(sep);
acc.plus(ali);
acc.plus(coh);
}
// steer
kVec steer(kVec target, float threshold) {
target.minus(pos);
float dist = target.length();
if (dist > 0 && dist < threshold) {
target.normalize();
target.scale(maxVel);
target.minus(vel);
target.limit(maxForce);
} else {
target = new kVec(0,0,0);
}
return target;
}
// seek
void seek(kVec target, float threshold) {
acc.plus(steer(target, threshold));
}
// flee
void flee(kVec target, float threshold){
acc.minus(steer(target, threshold));
}
// wander - currently only working in 2d
void wander() {
// make this 3D
float wanderR = 8;
float wanderD = 60;
float change = 0.1;
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, ht));
}
// separation
kVec separate (ArrayList pop) {
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 < rangeOfVision/1.5)) {
kVec diff = kVec.clone(pos);
diff.minus(other.pos);
diff.normalize();
diff.scale(1/dist);
sum.plus(diff);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
}
sumSep = kVec.clone(sum);
return sum;
}
// alignment
kVec align (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.vel);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
sum.limit(maxForce);
}
return sum;
}
// cohesion
kVec cohesion (ArrayList pop) {
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 < rangeOfVision)) {
sum.plus(other.pos);
count++;
}
}
if (count > 0) {
sum.scale(1/(float)count);
return steer(sum, ht);
}
return sum;
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(drawColor);
space.append(ln2);
}
void borders(float envSize) {
if (pos.x < -envSize) pos.x = envSize;
if (pos.y < -envSize) pos.y = envSize;
if (pos.z < -envSize) pos.z = envSize;
if (pos.x > envSize) pos.x = -envSize;
if (pos.y > envSize) pos.y = -envSize;
if (pos.z > envSize) pos.z = -envSize;
}
}
class kAgentPredator extends kAgent{
kAgentPredator(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 0;
agentType = "kAgentPredator";
}
void updatePop(ArrayList pop){
// seek pray
// find closest agent
float closestDist = envSize*envSize;
int closestAgent = 0;
for(int i = 0; i<pop.size(); i++){
kAgent other = (kAgent) pop.get(i);
if(other.agentType == "kAgentPrey"){
float dist = pos.distance(other.pos);
if(i > 0){
if(dist < closestDist){
closestDist = dist;
closestAgent = i;
}
} else {
closestDist = dist;
closestAgent = 0;
}
}
}
// seek closest agent
kAgent other = (kAgent) pop.get(closestAgent);
kVec target = kVec.clone(other.pos);
this.seek(target, 300);
}
void render() {
// draw vectors
float vecDisScale = 2;
kLine ln = new kLine(pos, vel, vel.length()*vecDisScale);
ln.setColor(255,0,0);
space.append(ln);
kLine ln1 = new kLine(pos, sumSep, sumSep.length()*vecDisScale);
ln1.setColor(0,0,255);
//space.append(ln1);
// draw agent
kLine ln2 = new kLine(pos, vel, 3);
ln2.setColor(0);
space.append(ln2);
}
}
class kAgentPrey extends kAgent{
kAgentPrey(
kVec _pos,
kVec _vec,
float _maxVel,
float _maxForce){
super(
_pos,
_vec,
_maxVel,
_maxForce);
drawColor = 255;
agentType = "kAgentPrey";
}
void updatePop(ArrayList pop){
kVec predFlee = this.preditorFlee(pop);
// call population functions
kVec sep = separate(pop);
kVec ali = align(pop);
kVec coh = cohesion(pop);
// weight vector
sep.scale(sepScale);
ali.scale(aliScale);
coh.scale(cohScale);
predFlee.scale(10);
// add the vectors to acceleration
acc.plus(sep);
acc.plus(ali);
acc.plus(coh);
acc.minus(predFlee);
}
kVec preditorFlee(ArrayList pop){
// find closest agent
float closestDist = envSize*envSize;
int closestAgent = 0;
for(int i = 0; i<pop.size(); i++){
kAgent other = (kAgent) pop.get(i);
if(other.agentType == "kAgentPredator"){
float dist = pos.distance(other.pos);
if(i > 0){
if(dist < closestDist){
closestDist = dist;
closestAgent = i;
}
}else{
closestDist = dist;
closestAgent = 0;
}
}
}
// seek closest agent
kAgent other = (kAgent) pop.get(closestAgent);
float killDist =10;
if(closestDist < killDist){
world1.deleteAgent(this);
return new kVec(0,0,0);
}else{
kVec target = kVec.clone(other.pos);
return this.steer(target, 100);
}
}
}
class kAttractor{
kVec pos;
float magnatude;
float attDisScale;
float range;
//constructor - basic
kAttractor(kVec _pos){
pos = kVec.clone(_pos);
magnatude = -2;
attDisScale = 10;
range = 100;
}
//constructor - complete
kAttractor(kVec _pos, float _magnatude, float _attDisScale, float _range){
pos = kVec.clone(_pos);
magnatude = _magnatude;
attDisScale = _attDisScale;
range = _range;
}
void render(){
kLine ln0 = new kLine(pos.x, pos.y, pos.z - attDisScale, pos.x, pos.y, pos.z + attDisScale);
kLine ln1 = new kLine(pos.x, pos.y - attDisScale, pos.z, pos.x, pos.y + attDisScale, pos.z);
kLine ln2 = new kLine(pos.x - attDisScale, pos.y, pos.z, pos.x + attDisScale, pos.y, pos.z);
ln0.setColor(0,0,255);
ln1.setColor(0,0,255);
ln2.setColor(0,0,255);
space.append(ln0);
space.append(ln1);
space.append(ln2);
}
}
// a class which controls the agent population arraylist
class kWorld {
ArrayList population;
ArrayList attractors;
kWorld() {
population = new ArrayList();
attractors = new 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.step(this);
}
// attractors render loop
for (int i = 0; i < attractors.size(); i++) {
kAttractor a = (kAttractor) attractors.get(i);
a.render();
}
}
// adds an agent to the population
void addAgent(kAgent a) {
population.add(a);
}
void addAttractor(kAttractor a) {
attractors.add(a);
}
//kill
void deleteAgent(kAgent a) {
population.remove(a);
}
}
Import Libraries
Declare variables
gravity, wind_speed, wind_direction, bat_array[], vector_array[]
Declare Bat Class
BEGIN Set-up parameters
Make parameters for world of bats For each bat in Bat Array Instantiate bat
END parameter setup
BEGIN Draw function
Call bat class functions
END Draw function
BEGIN bat class
Declare variables
Declare Constructor
kAgent constructor
Methods for class
Create update function which handles add and deletes
Create searching function
For each Frame execute
For Each Bat in Bat Array
Identify local swarm individuals and obstacles
Identify Center of mass by segment for swarm
Identify attractors such as prey
Calculate distances from individuals to obstacles and prey
if separation constraints are adequate, calculate vector opposite nearest neighbor
Calculate azimuth to obstacle
Calculate steering behaviors
Calculate composite behavior
Store composite behavior to Bat memory
Create behavior function
For Each Bat In Bat Array
Vector turns based on stored composite behavior
Move to next position
Create display function
END bat class











