Alphaam_RobotaPsyche/February22/vehicle.pde
// The vehicle class, more or less straight from the book
class Vehicle {

  PVector location;
  PVector velocity;
  PVector acceleration;
  // Additional variable for size
  float r;
  float maxforce;
  float maxspeed;
  float bsize;
  float bsize1=2;
  float bcolor;
  DNA brush;

  Vehicle(float x, float y) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    location = new PVector(x, y);
    r = 3.0;
    brush = new DNA();
    //Arbitrary values for maxspeed and
    // force; try varying these!
    maxspeed = 4;
    maxforce = 0.10;
  }

  // Update the velocity and location, based on the acceleration generated by the steering force
  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    location.add(velocity);
    acceleration.mult(0); // clear the acceleration for the next frame
  }

  // Newton’s second law; we could divide by mass if we wanted.
  // If there are multiple forces (e.g. gravity, wind) we use
  // this function for each one, and it is added to the acceleration
  void applyForce(PVector force) {
    acceleration.add(force);
  }

  /*
  What follows are different steering algorithms. A vehicle
   could use any one, and you could create addiotional ones.
   Each algorithm calculates the steering force and then
   applies it
   */
  void applyBehaviors(ArrayList<Vehicle> vehicles) {
    // seek() and separate() do not apply the force
    PVector separate = separate(vehicles);
    PVector seek = seek(new PVector(mouseX, mouseY));

    separate.mult(100); 
    seek.mult(0.5);

    applyForce(separate);
    applyForce(seek);
  }
  void flock(ArrayList<Vehicle> boids) {
    // The three flocking rules
    PVector sep = separate(boids);
    PVector ali = align(boids);
    PVector coh = cohesion(boids);

    // Arbitrary weights for these forces
    // (Try different ones!)
    sep.mult(1.5);
    ali.mult(1.0);
    coh.mult(1.0);

    // Applying all the forces
    applyForce(sep);
    applyForce(ali);
    applyForce(coh);
  }

  PVector align (ArrayList<Vehicle> boids) {
    // This is an arbitrary value and could
    // vary from boid to boid.
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);
    int count = 0;
    for (Vehicle other : boids) {
      float d = PVector.dist(location, other.location);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.velocity);
        // For an average, we need to keep track of
        // how many boids are within the distance.
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);
      sum.normalize();
      sum.mult(maxspeed);
      PVector steer = PVector.sub(sum, velocity);
      steer.limit(maxforce);
      return steer;
      // If we don’t find any close boids,
      // the steering force is zero.
    } else {
      return new PVector(0, 0);
    }
  }

  PVector cohesion (ArrayList<Vehicle> boids) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);
    int count = 0;
    for (Vehicle other : boids) {
      float d = PVector.dist(location, other.location);
      if ((d > 0) && (d < neighbordist)) {
        // Adding up all the others’ locations
        sum.add(other.location);
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);
      // Here we make use of the seek() function we
      // wrote in Example 6.8.  The target
      // we seek is the average location of
      // our neighbors.
      return seek(sum);
    } else {
      return new PVector(0, 0);
    }
  }

  PVector seek(PVector target) {
    PVector desired = PVector.sub(target, location);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);

    // Instead of applying the force we return the PVector.
    // applyForce(steer); // No longer done here
    return steer;
  }

  // Calculate the steering force to follow a flow field
  void follow(FlowField flow) {
    // Look up the vector at that spot in the flow field
    PVector desired = flow.lookup(location);
    desired.mult(maxspeed);

    // Steering is desired minus velocity
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  void display() {
    // Vehicle is a triangle pointing in
    // the direction of velocity; since it is drawn
    // pointing up, we rotate it an additional 90 degrees.
    float theta = velocity.heading() + PI/2;
    getDNA();
    fill(bcolor, bsize1, bcolor);

    noStroke();
    pushMatrix();
    translate(location.x, location.y);
    rotate(theta);
    //beginShape();
    //vertex(0, -r*2);
    //vertex(-r, r*2);
    ellipse(r, r*2, bsize, bsize);
    endShape(CLOSE);
    popMatrix();
  }

  void checkPosition(ArrayList<Vehicle> vehicles) {
    for (Vehicle other : vehicles) {
      if (PVector.dist(location, other.location)<=50) {
        //vehicles.remove(10);
        bsize1=200;
      }
      if (PVector.dist(location, other.location)<=100 && PVector.dist(location, other.location)>=51) {
        //vehicles.remove(10);
        bsize1=255;
      }
      if (PVector.dist(location, other.location)>=101 && PVector.dist(location, other.location)>=150) {
        //vehicles.remove(10);
        bsize1=100;
      }
    
    if (PVector.dist(location, other.location)>151) {
      //vehicles.remove(10);
      bsize1=50;
    }
  }
}

PVector separate (ArrayList<Vehicle> vehicles) {
  PVector steer = new PVector(0, 0);
  float desiredseparation = 20; // how close is too close.
  int count = 0;
  PVector sum = new PVector(0, 0);

  for (Vehicle other : vehicles) {

    // What is the distance between me and another Vehicle?
    float d = PVector.dist(location, other.location);

    // If the distance is zero we are looking at ourselves; exclude that
    if ((d > 0) && (d < desiredseparation)) {

      // calculate the location of this vehicle
      PVector diff = PVector.sub(location, other.location); 
      diff.normalize();

      // We'll need the average, so add this location to the sum 
      // of all locations and increment the count.
      sum.add(diff); 
      count++;
    }
  } // end of loop over all vehicles

  // now calculate the average, 
  // figure out the force
  // and apply the force:
  if (count > 0) { // If zero then no one is too close
    sum.div(count); // sum is now our desired velocity

    // Scale average to maxspeed
    sum.setMag(maxspeed);

    // Apply Reynolds’s steering formula:
    // error is our current velocty minus our desired velocity
    steer = PVector.sub(sum, velocity);
    steer.limit(maxforce);

    // Apply the force to the Vehicle’s
    // acceleration.
    //applyForce(steer);
  }
  return steer;
}
void getDNA() {
  bsize = brush.brushSize();
  bcolor = brush.brushColor();
}
}
