logo

prolebra_2DBabyMakingTrackers_Object

class Tracker {
  List<Vec3D> objectTrails;
  
  Vec3D speed;
  Vec3D acc = new Vec3D(0, 0, 0);
  Vec3D loc;
  
  String type, babyType;
  
  float maxforce = 0.01;
  float max = 4.0f;
  float vel = 1.0;
  float amp,r;
  float maxDist = 100;

  boolean sepActive = false;
  boolean wonderTrigger = false;
  boolean instanceable;

  int maxChildren,instanceTriggerCount;

  float wandertheta;
  float wanderTVal; //value to swap rotation after x position changes
  float wanderD; // Distance for our "wander circle"
  float wanderR; //Radius for our "wander circle"
  float wanderT; // Randomly change wander theta
  //-------------------------------------------------------------------------------------
  Tracker(Vec3D location, Vec3D Speed, boolean instance, String Type, String BabyType) {
    this.loc = location;
    this.objectTrails = new ArrayList<Vec3D>();
    this.r = 12;
    this.instanceTriggerCount = 0;
    this.instanceable = instance;
    this.type = Type;
    this.wandertheta = 0;
    this.babyType = BabyType;
    this.speed = Speed;
  }
  //----------------------------------------------------------------------
  //Run-------------------------------------------------------------------
  //Run all the other methods for this dude-------------------------------
  //----------------------------------------------------------------------
  void run() {
    pathFollow();
    if (this.sepActive && this.instanceable) {
     separate();
     }
     if(this.wonderTrigger){
     wander();
     } 
     /*
    if (this.wonderTrigger) {
      wander();
    }
    */
    if (simulate) {
      move();
    }
    viz();
    trail();
  }
  //--------------------------------------------------------------------------
  //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() {   
    if (stepCount < this.wanderTVal) {
      if (type == "parent") {
        this.wandertheta = this.wanderT;
      } else {
        if (babyType == "w_a") {
          this.wandertheta = this.wanderT;
        } else {
          this.wandertheta = -this.wanderT;
        }
      }
    } else if (stepCount >= this.wanderTVal && stepCount <this.wanderTVal*2) {
      if (type == "parent") {
        this.wandertheta = -this.wanderT;
      } else {
        if (babyType == "w_a") {
          this.wandertheta = -this.wanderT;
        } else {
          this.wandertheta = this.wanderT;
        }
      }
    } else {
      stepCount = 0;
    }
    // Now we have to calculate the new location to steer towards on the wander circle
    Vec3D circleloc = speed.copy();    // Start with velocity
    circleloc.normalize();            // Normalize to get heading
    circleloc.scaleSelf(this.wanderD);          // Multiply by distance
    circleloc.addSelf(this.loc);               // Make it relative to boid's location
    float h = speed.headingXY();        // We need to know the heading to offset wandertheta
    Vec3D circleOffSet = new Vec3D(this.wanderR*cos(this.wandertheta+h), this.wanderR*sin(this.wandertheta+h), 0);
    Vec3D target = circleloc.add(circleOffSet);
    seek(target);
    
    if (diagram) drawWanderStuff(loc, circleloc, target, wanderR);  // Render wandering circle, etc. 
  }  
  //-------------------------------------------------------------------------------------------
  //Diagram------------------------------------------------------------------------------------
  //A method just to draw the circle associated with wandering---------------------------------
  //-------------------------------------------------------------------------------------------
  void drawWanderStuff(Vec3D location, Vec3D circle, Vec3D target, float rad) {
    stroke(255); 
    noFill();
    ellipseMode(CENTER);
    ellipse(circle.x, circle.y, rad*2, rad*2);
    ellipse(target.x, target.y, 4, 4);
    line(location.x, location.y, circle.x, circle.y);
    line(circle.x, circle.y, target.x, target.y);
  }
  //-------------------------------------------------------------------------------------------
  //Path Follow Method-------------------------------------------------------------------------
  //Follows the path if inside the radius------------------------------------------------------
  //-------------------------------------------------------------------------------------------
  void pathFollow() {
    Vec3D predict = this.speed.copy();
    predict.normalize();
    predict.scaleSelf(this.amp);
    Vec3D nextPosPrev = loc.add(predict);
    Vec3D target = null;
    Vec3D normal = null;
    float worldRecord = 1000000;
    for (int z = 0; z < pathList.size(); z++) {
      for (int i = 0; i <  pathList.get(z).points.size()-1; i++) { 
        Vec3D a = pathList.get(z).points.get(i);
        Vec3D b = pathList.get(z).points.get(i+1);
        Vec3D normalPoint = getNormalPoint(nextPosPrev, a, b); //Finding the normals for each line segment
        if (normalPoint.x < min(a.x, b.x) || normalPoint.x > max(a.x, b.x)) {
          normalPoint = b.copy();
        }
        float distance = nextPosPrev.distanceTo(normalPoint);
        if (distance < worldRecord) {
          worldRecord = distance;
          normal = normalPoint;
          Vec3D dir = b.sub(a); //Look at the direction of the line segment so we can seek a little bit ahead of the normal
          dir.normalize();
          dir.scaleSelf(10);
          target = normalPoint.copy();
          target.add(dir);
        }
      }
    }
    //remove if you want to just go to the line
    //maxDist = 10000000000000f;
    if (worldRecord < this.maxDist) {
      this.sepActive = true;
      this.wonderTrigger = true;
      if (worldRecord > tempPath.radius) {
        seek(target);
      } else {
        //IF TYPE IS PARENT AND HAS CREATED LESS THAN THE ALLOWED CHILDREN THEN CREATE MORE
        if (this.instanceable && instanceTriggerCount < maxChildren) { 
          addNew = true;
          triggerLoc = nextPosPrev.copy();
          childSpawners.add(new Vec3D(this.loc));
          childSpawnType.add(instanceTriggerCount);
          triggerCount++;        
          instanceTriggerCount ++;
        } else {
          addNew = false;
        }
        Vec3D zero = new Vec3D(0, 0, 0);
        zero.scaleSelf(3);
        acc.addSelf(zero);
      }
    } else {
      wonderTrigger = false;
    }
    // Draw the debugging stuff
    if (drawFutureLoc) {
      // Draw predicted future location
      stroke(255);
      fill(0);
      line(this.loc.x, this.loc.y, this.loc.x, this.loc.y);
      ellipse(nextPosPrev.x, nextPosPrev.y, 4, 4);
      // Draw normal location
      stroke(255);
      fill(0);
      ellipse(normal.x, normal.y, 4, 4);
      // Draw actual target (red if steering towards it)
      line(nextPosPrev.x, nextPosPrev.y, normal.x, normal.y);
      if (worldRecord > tempPath.radius) fill(255, 0, 0);
      noStroke();
      ellipse(target.x, target.y, 8, 8);
    }
  }
  //-------------------------------------------------------------------------------------------
  //-------------------Get the Normal Point on the Path Method---------------------------------
  //-------------------------------------------------------------------------------------------
  Vec3D getNormalPoint(Vec3D p, Vec3D a, Vec3D b) {
    Vec3D ap = p.sub(a);
    Vec3D ab = b.sub(a);
    ab.normalize();
    ab.scaleSelf(ap.dot(ab)); //Using the dot product for scalar projection
    Vec3D normalPoint = a.add(ab); // Finding the normal point along the line segment
    return normalPoint;
  }
  //-------------------------------------------------------------------------------------------
  //---------------------------------------Seek Target Method----------------------------------
  //-------------------------------------------------------------------------------------------
  void seek(Vec3D target) {
    Vec3D desired = target.sub(this.loc);
    desired.normalize();
    desired.scaleSelf(this.max);
    Vec3D steer = desired.sub(this.speed);
    steer.limit(this.maxforce); // Limit the magnitude of the steering force.
    steer.scaleSelf(3);
    applyForce(steer);
  }
  //-------------------------------------------------------------------------------------------
  //Apply Force Method-------------------------------------------------------------------------
  //-------------------------------------------------------------------------------------------
  void applyForce(Vec3D force) {
    this.acc.addSelf(force);
  }
  //----------------------------------------------------------------------
  //Move------------------------------------------------------------------
  //Move and update the position------------------------------------------
  //----------------------------------------------------------------------
  void move() {
    this.speed.addSelf(this.acc);
    this.speed.limit(this.max);
    this.loc.addSelf(this.speed);
    this.objectTrails.add(new Vec3D(this.loc));
    this.acc.clear();
  }
  //-------------------------------------------------------------------------------------------
  //Viz Method---------------------------------------------------------------------------------
  //Draw heads---------------------------------------------------------------------------------
  void viz() {
    if (type == "parent") {
      stroke(255, 0, 0);
      strokeWeight(6);
      point(this.loc.x, this.loc.y);
    } else {
      if (babyType == "w_a") {
        stroke(0, 0, 255);
        strokeWeight(6);
        point(this.loc.x, this.loc.y);
      } else {
        stroke(0, 255, 255);
        strokeWeight(6);
        point(this.loc.x, this.loc.y);
      }
    }
  }
  //-------------------------------------------------------------------------------------------
  //Separation Method--------------------------------------------------------------------------
  //Method checks for nearby boids and steers away---------------------------------------------
  //-------------------------------------------------------------------------------------------
  void separate () {
    float desiredseparation = this.r*2;
    Vec3D steer = new Vec3D(0, 0, 0);
    int count = 0;
    // For every boid in the system, check if it's too close
    for (int i = 0; i < agentList.size(); i++) {
      Tracker other = (Tracker) agentList.get(i);
      float d = this.loc.distanceTo(other.loc);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        Vec3D diff = loc.sub(other.loc);
        diff.normalize();
        diff.normalizeTo(1/d);        // Weight by distance
        steer.addSelf(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      steer.scaleSelf(1.0/(float)count);
    }
    // As long as the vector is greater than 0
    if (steer.magnitude() > 0) {
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.scaleSelf(this.max);
      steer.subSelf(this.speed);
      steer.limit(this.maxforce);
    }
    steer.scaleSelf(3);
    applyForce(steer);
  }
  //-------------------------------------------------------------------------------------------
  //Trail Method-------------------------------------------------------------------------------
  //The trail is drawn from previous loc to new location---------------------------------------
  //-------------------------------------------------------------------------------------------
  void trail() {

    if (this.objectTrails.size() > 0) {
      for (int j = 0; j < this.objectTrails.size(); j++) {
        if (j != 0) {
          Vec3D pos = this.objectTrails.get(j);
          Vec3D prevpos = this.objectTrails.get(j - 1);
          if(this.type == "parent"){
            stroke(255, 0, 0, map(j, 0, this.objectTrails.size(), 0, 200));
            strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.5));
          }else if(this.babyType == "w_a"){
            stroke(0, 0, 255, map(j, 0, this.objectTrails.size(), 0, 200));
            strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.0));
          }else{
            stroke(0,255, 255, map(j, 0, this.objectTrails.size(), 0, 200));
            strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.0));
          }       
          line(pos.x, pos.y, prevpos.x, prevpos.y);
        }
      }
    }
  }
}
Update
  • Share