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