class Meanderer {
Vec3D loc, vel;
Vec3D acc = new Vec3D();
float newMap, mapValue;
float wandertheta, wanderR, wanderD, change;
//----------------------------------------------------------------------
float Multiplier, MaxSpeed, MaxForce;
String tag = "A";
int switchTrigger= 0;
ArrayList<Vec3D> objectTrails = new ArrayList<Vec3D>();
//----------------------------------------------------------------------
boolean randomize = true;
Meanderer(Vec3D location, Vec3D velBase) {
this.loc = location;
this.vel = velBase;
}
//----------------------------------------------------------------------
//Run-------------------------------------------------------------------
//Run all the other methods for this dude-------------------------------
//----------------------------------------------------------------------
void run() {
wander();
bordersRespawn();
//bordersBounce();
if (simulate) {
move();
}
viz();
setType();
trail();
}
//----------------------------------------------------------------------
//SetType---------------------------------------------------------------
//Set the type based on its relationship to the image below-------------
//----------------------------------------------------------------------
void setType() {
if (setMap) {
if (this.loc.x <= img.width && this.loc.x >= 0 && this.loc.y >= 0 && this.loc.y <= img.height) {
color c = img.pixels[floor(this.loc.y)*img.width+floor(this.loc.x)];
int greyscale = round(red(c)*0.222+green(c)*0.707+blue(c)*0.071);
this.newMap = map(greyscale, 0, 255, 0, 1);
if (this.newMap > 0.35) {
if (this.tag == "A" && this.switchTrigger != 0) {
this.objectTrails = new ArrayList<Vec3D>();
}
this.tag = "B";
this.switchTrigger ++;
} else {
this.tag = "A";
}
} else {
this.newMap = 0;
}
}
}
//----------------------------------------------------------------------
//Move------------------------------------------------------------------
//Move and update the position------------------------------------------
//----------------------------------------------------------------------
void move() {
this.vel.addSelf(this.acc);
this.vel.normalize();
this.vel.scaleSelf(this.Multiplier);
this.vel.limit(this.MaxSpeed);
this.loc.addSelf(this.vel);
this.acc.clear();
}
//----------------------------------------------------------------------
//Viz-------------------------------------------------------------------
//Draw the head of the wanderer-----------------------------------------
//----------------------------------------------------------------------
void viz() {
if (this.tag == "A") {
stroke(255, 0, 0);
strokeWeight(2);
}
if (this.tag == "B") {
stroke(227, 255, 0);
strokeWeight(3);
}
point(this.loc.x, this.loc.y);
}
//----------------------------------------------------------------------
//Trail-----------------------------------------------------------------
//The trail is drawn from previous loc to new location------------------
//----------------------------------------------------------------------
void trail() {
this.objectTrails.add(new Vec3D(this.loc));
if (this.objectTrails.size() > 0) {
for (int j = 0; j < this.objectTrails.size()-1; j++) {
Vec3D pos = this.objectTrails.get(j);
Vec3D prevpos = this.objectTrails.get(j+1);
if (this.tag == "A") {
stroke(255, 0, 0, map(j, 0, this.objectTrails.size(), 0, 150));
strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1));
} else if (this.tag == "B") {
stroke(227, 255, 0, map(j, 0, this.objectTrails.size(), 0, 150));
strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 0.75));
}
line(pos.x, pos.y, prevpos.x, prevpos.y);
}
}
}
//-----------------------------------------------------------------------
//BorderRespawn----------------------------------------------------------
//If we hit the boundary spawn at x depending on your spawn settings-----
//-----------------------------------------------------------------------
void bordersRespawn() {
if (this.loc.x < 0 || this.loc.x > width || this.loc.y < 0 || this.loc.y > height) {
if (SpawnEdge) {
this.loc = new Vec3D(0, random(height), 0);
} else {
this.loc = new Vec3D(random(width), random(height), 0);
}
this.objectTrails = new ArrayList<Vec3D>();
}
}
//----------------------------------------------------------------------
//BorderBounce----------------------------------------------------------
//Reverse the direction if we hit the boundary--------------------------
//----------------------------------------------------------------------
void bordersBounce() {
if (this.loc.x > width) {
this.vel.x = this.vel.x * -1;
}
if (this.loc.x < 0) {
this.vel.x = this.vel.x * -1;
}
if (this.loc.y > height) {
this.vel.y = this.vel.y * -1;
}
if (this.loc.y < 0) {
this.vel.y = this.vel.y * -1;
}
}
//--------------------------------------------------------------------------
//Wanderer Behavior---------------------------------------------------------
//“Wandering is a type of random steering which has some long term order: -
//the steering direction on one frame is related to the steering direction
//on the next frame. This produces more interesting motion than, for example
//,simply generating a random steering direction each frame.” Reynolds-----
//--------------------------------------------------------------------------
void wander() {
// wanderR = Radius for circle
// wanderD = Distance for circle
if (setMap) {
if (this.loc.x <= img.width && this.loc.x >= 0 && this.loc.y >= 0 && this.loc.y <= img.height) {
getColorValue();
this.change *= this.newMap;
} else {
this.newMap = 0;
}
}
if (this.randomize) {
this.wandertheta += random(-this.change, this.change); // Randomly change wander theta
} else {
this.wandertheta += this.change;
}
Vec3D circleLoc = new Vec3D(this.vel.x, this.vel.y, 0);
circleLoc.normalize(); // Normalize to get heading
circleLoc.scaleSelf(this.wanderD);
circleLoc.addSelf(this.loc);
Vec3D circleOffSet = new Vec3D(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta), 0);
Vec3D target = circleLoc.addSelf(circleOffSet);
Vec3D steer = target.sub(this.loc);
steer.normalize();
steer.scaleSelf(1);
this.acc.addSelf(steer);
}
//----------------------------------------------------------------------
//Snatch the color value from the image---------------------------------
//----------------------------------------------------------------------
void getColorValue() {
color c = img.pixels[floor(this.loc.y)*img.width+floor(this.loc.x)];
int greyscale = round(red(c)*0.222+green(c)*0.707+blue(c)*0.071);
this.newMap = map(greyscale, 0, 255, 0, 1);
}
}
Update