KAgent example 3d subFlock
From KokkugiaWiki
a simple flocking agent example with predator and prey agent sub-classes
applet - kAgent 3d subFlock
predator
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);
}
}
prey
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);
kVec target = kVec.clone(other.pos);
return this.steer(target, 100);
}
}
sketch
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));
}
}
void draw(){
background(255);
int mx = mouseX;
int my = mouseY;
world1.run();
kRange rng = new kRange(300);
rng.setColor(100);
space.append(rng);
space.render();
space.init();
}
void mouseDragged(){
space.mouseDragged();
}
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.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();
}
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;
}
}
