logo

TrackStar_Object

class Agent {

  float vel = 1.0;
  float r, amp;
  float maxforce = 0.01;
  float max = 4.0f;

  List<Vec3D> objectTrails;

  Vec3D speed = new Vec3D(vel, 0, 0);
  Vec3D acc = new Vec3D(0, 0, 0);
  Vec3D loc;
  //-------------------------------------------------------------------------------------------
  Agent(Vec3D location) {
    loc = location;
    this.objectTrails = new ArrayList<Vec3D>();
    r = 12;
  }
  //-------------------------------------------------------------------------------------------
  //---------------------------------------Runs all other methods------------------------------
  //-------------------------------------------------------------------------------------------
  void run() {
    pathFollow();
    separate();
    if (simulate) {
      move();
    }
    viz();
    trail();
  }
  //-------------------------------------------------------------------------------------------
  //---------------------------------------Path Follow Method----------------------------------
  //-------------------------------------------------------------------------------------------
  void pathFollow() {
    
    Vec3D predict = this.speed.copy();
    predict.normalize();
    predict.scaleSelf(this.amp);
    Vec3D nextPosPrev = this.loc.add(predict);

    Vec3D target = null;
    Vec3D normal = null;
    float worldRecord = 1000000;

    for (int i = 0; i < tempPath.points.size()-1; i++) { 
      Vec3D a = tempPath.points.get(i);
      Vec3D b = tempPath.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);
      }
    }
    if (worldRecord > tempPath.radius ) {
      seek(target);
    } else {
      Vec3D zero = new Vec3D(0, 0, 0);
      zero.scaleSelf(3);
      this.acc.addSelf(zero);
    }
    // Draw the debugging stuff
    if (debug) {
      // 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(loc);
    desired.normalize();
    desired.scaleSelf(max);
    Vec3D steer = desired.sub(speed);
    steer.limit(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 Method-------------------------------------
  //-------------------------------------------------------------------------------------------
  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--------------------------------------
  //-------------------------------------------------------------------------------------------
  void viz() {
    stroke(255, 0, 0);
    strokeWeight(6);
    point(this.loc.x, this.loc.y);
  }
  //-------------------------------------------------------------------------------------------
  //---------------------------------------Separation Method----------------------------------
  //-------------------------------------------------------------------------------------------
  void separate () {
    float desiredseparation = r*2;
    Vec3D steer = new Vec3D(0, 0, 0);
    int count = 0;

    for (int i = 0; i < agentList.size(); i++) { // For every agent in the system, check if it's too close
      Agent other = (Agent) agentList.get(i);
      float d = this.loc.distanceTo(other.loc);
      if ((d > 0) && (d < desiredseparation)) { // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
        Vec3D diff = loc.sub(other.loc); // Calculate vector pointing away from neighbor
        diff.normalize();
        diff.normalizeTo(1/d); // Weight by distance
        steer.addSelf(diff);
        count++;// Keep track of how many
      }
    }
    if (count > 0) {
      steer.scaleSelf(1.0/(float)count); // Average
    }
    if (steer.magnitude() > 0) { // As long as the vector is greater than 0
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.scaleSelf(this.max);
      steer.subSelf(this.speed);
      steer.limit(this.maxforce);
    }
    steer.scaleSelf(1);
    applyForce(steer);
  }
  //-------------------------------------------------------------------------------------------
  //---------------------------------------Trail Method----------------------------------------
  //-------------------------------------------------------------------------------------------
  void trail() {
    if (objectTrails.size() > 0) {
      for (int j = 0; j < objectTrails.size(); j++) {
        if (j != 0) {
          Vec3D pos = objectTrails.get(j);
          Vec3D prevpos = objectTrails.get(j - 1);
          stroke(255, 0, 0, map(j, 0, objectTrails.size(), 0, 200));
          strokeWeight(map(j, 0, objectTrails.size(), 0.45, 1.0));
          line(pos.x, pos.y, prevpos.x, prevpos.y);
        }
      }
    }
  }
}
Update
  • Share