Simple follow behaviour

edited March 2018 in Questions about Code

I'm trying to implement a simple follow behaviour where each object in the ArrayList follows the next object in the ArrayList. At the moment it seems like all the objects are following each other though? I'm assuming it's a problem with the loop but can't figure it out..

ArrayList<Mover> movers;

void setup() {
  size(640, 360);
  movers = new ArrayList<Mover>();
  for (int i = 0; i < 4; i++) {
    movers.add(new Mover());
  }
}

void draw() {
  background(255);

  for (int i = 0; i < movers.size(); i++) {
    Mover m = movers.get(i);
    float alpha = i*85;

    m.follow(movers);
    m.update();
    m.display(alpha);
    m.boundary();
  }
}

class Mover {
  PVector location;
  PVector velocity;
  PVector acceleration;
  float mass;
  float radius;
  float maxspeed;
  float maxforce;
  float damping;

  Mover() {
    location = new PVector(random(width), random(height));
    velocity = new PVector();
    acceleration = new PVector();
    radius = 20;
    maxspeed = 2;
    maxforce = 0.3;
    damping = 0.98;
  }

  void follow(ArrayList<Mover> movers) {
    for (int i = 0; i < movers.size()-1; i++) {
      Mover other = movers.get(i+1);
      PVector neighbour = PVector.sub(other.location, location);
      neighbour.setMag(maxspeed);
      PVector steer = PVector.sub(neighbour, velocity);
      steer.limit(maxforce);
      applyForce(steer);
    }
  }
  void applyForce(PVector force) {
    force.copy();
    acceleration.add(force);
  }

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    velocity.mult(damping);
    location.add(velocity);
    acceleration.mult(0);
  }

  void display(float alpha) {
    fill(alpha);
    stroke(0);
    strokeWeight(1);
    ellipse(location.x, location.y, radius, radius);
  }

  void boundary() {
    if (location.x < 0) { 
      location.x = width;
    }
    if (location.x > width) { 
      location.x = 0;
    }  
    if (location.y < 0) { 
      location.y = height;
    }
    if (location.y > height) { 
      location.y = 0;
    }
  }
}
Tagged:

Answers

  • Add some debug statements. Don't just try and guess what it's doing, get it to tell you.

    Add some comments whilst you're there.

  • edited March 2018

    your method follow in the class is wrong

    I would pass each ball an id named ID.

    instead of having a for loop you just want that each ball follows the other ball with the ID id-1.

    That means that ball 0 doesn't have a ball to follow, so 0 should be treated special. He is the leader and needs an own movement pattern.

    I just wrote it here, looks nice. Tell me if you want to see it

  • If I could see it that would be great. I'm just starting out so i'm not sure how I would go about passing each ball an ID that could be used in the function.

  • edited March 2018

    There is a tutorial about classes called objects, see constructor there in the tutorial

    https://www.processing.org/tutorials/objects/

  • ArrayList<Mover> movers;
    
    void setup() {
    
      size(1540, 360);
    
      movers = new ArrayList<Mover>();
      for (int i = 0; i < 4; i++) {
        movers.add(new Mover(i));
      }
    }
    
    void draw() {
      background(255);
    
      for (int i = 0; i < movers.size(); i++) {
    
        Mover m = movers.get(i);
        float alpha = i*85;
    
        m.follow(movers);
        m.update();
        m.display(alpha);
        m.boundary();
      }
    }
    
    // ==========================================================
    
    class Mover {
    
      PVector location;
      PVector velocity;
      PVector acceleration;
      float mass;
      float radius;
      float maxspeed;
      float maxforce;
      float damping;
    
      int id; 
    
      Mover(int id_) {
        location = new PVector(random(width), random(height));
        velocity = new PVector();
        acceleration = new PVector();
        radius = 20;
        maxspeed = 2;
        maxforce = 0.3;
        damping = 0.78; // damping = map(id, 0, 3, .6, .98) ;
    
        id=id_;
        println(id);
    
        if (id==0) {
          // Leader
          velocity = new PVector(random(2, 3), random(2, 3));
          if (random(100)>50) velocity.x*=-1; 
          if (random(100)>50) velocity.y*=-1;
        }
      }
    
      void follow(ArrayList<Mover> movers) {
    
        int i=id-1;
    
        if (i>=0) {
          Mover other = movers.get(i);
          PVector neighbour = PVector.sub(other.location, location);
          neighbour.setMag(maxspeed);
          PVector steer = PVector.sub(neighbour, velocity);
          steer.limit(maxforce);
          applyForce(steer);
          return;
        }
    
        // This is the leader 
        // println(id);
      }//method
    
      void applyForce(PVector force) {
        force.copy();
        acceleration.add(force);
      }
    
      void update() {
        if (id==0) {
          // Leader
          velocity.add(acceleration);
          //  velocity.limit(maxspeed);
          // velocity.mult(damping);
          location.add(velocity);
        } else {
          velocity.add(acceleration);
          velocity.limit(maxspeed);
          velocity.mult(damping);
          location.add(velocity);
          acceleration.mult(0);
        }
      }
    
      void display(float alpha) {
        fill(alpha);
        stroke(0);
        strokeWeight(1);
        ellipse(location.x, location.y, radius, radius);
      }
    
      void boundary() {
        // go to other side of screen 
        if (location.x < 0) { 
          location.x = width;
        }
        if (location.x > width) { 
          location.x = 0;
        }  
        if (location.y < 0) { 
          location.y = height;
        }
        if (location.y > height) { 
          location.y = 0;
        }
      }
    }
    //
    
Sign In or Register to comment.