Fixing bugs - vibrating units.

A few days ago I asked a question on removing objects on mouse click (http://forum.processing.org/two/discussion/981/remove-object-on-mouse-click#Item_5) that was kindly answered.

I have started to get my sketch to where I wish -- but I still need to iron out some of the bugs. I have included a hand drawn sketch that I hope illustrates what I am trying to achieve.

My objects keep vibrating - I believe as the flock forces are fighting against each other. I have tried to decelerate them as they approach neighbours but I'm still having trouble.

My code is below:

import toxi.geom.*;

ArrayList mypenguinCollection;
float numberofpenguins = 15;
float distanceformouse = 1;

void setup() {
  size(600, 600);
  smooth();
  mypenguinCollection = new ArrayList();

  for (int i = 0; i <numberofpenguins; i++) {
    float posx=200*sin(TWO_PI/10*i);
    float posy=200*cos(TWO_PI/10*i);
    Vec3D original = new Vec3D(random(100, 500), random(100, 500), 0);
    penguin mypenguin = new penguin(original);
    mypenguinCollection.add(mypenguin);
  }
}

void draw() {
  background(255);

  line(300, 0, 300, 600);
  line(0, 300, 600, 300);

  for (int i = 0; i <mypenguinCollection.size(); i++) {
    penguin mypenguin_2 = (penguin) mypenguinCollection.get(i);
    mypenguin_2.run();
  }
}


class penguin {

  Vec3D loc = new Vec3D (0, 0, 0); 
  Vec3D speed = new Vec3D (10000, 0, 0);
  Vec3D gravity = new Vec3D (0, 0.2, 0);
  Vec3D acc= new Vec3D(0, 0, 0);
  Vec3D vel = new Vec3D(0, 0, 0);
  Vec3D target = new Vec3D( 300, 300, 0);
  float radius = 10;
  int countCentrality =0;
  float velMax= .8;
  int countNeighbours=0;
  int temperature= 40;
  float cohMag=.000001;
  float sepMag=2;

  penguin(Vec3D _loc) {
    loc = _loc;
  }

  void run() {
    display();
    flock();
    movetoorigin();
    update();
  }

  void update() {

    println(countNeighbours);
    if (countNeighbours==3) {
      vel.clear();
      acc.clear();
      cohMag*=0.8;
      sepMag*=1.0;
    }
    vel.addSelf(acc);
    vel.limit(velMax);
    loc.addSelf(vel);
    acc = new Vec3D();
  }

  void movetoorigin() {

    Vec3D diff = target.sub(loc);

    float distance = diff.magnitude();
    diff.normalize();

    diff.scaleSelf(distance/5);
    if (countNeighbours<5) {
      acc.addSelf(diff);
    }
  }

  void display() {

    float dist = target.distanceTo(loc);
    float red = map(dist, 0, 100, 255, 0);

    fill(red+5, 0, 255-red);
    ellipse(loc.x, loc.y, radius*1.2, radius*1.1);
    //ellipse(loc.x, loc.y, 10, 10);
  }

  void move() {
    speed.addSelf(acc);
    speed.limit(1);
    loc.addSelf(speed);
    acc.clear();
  }

  void flock() {

    separate(sepMag);
    cohesion(cohMag);
    //align(0.00001);
  }

  void align(float magnitude) {

    Vec3D steer = new Vec3D();

    int count = 0;

    for (int i=0; i < mypenguinCollection.size();i++) {
      penguin other = (penguin) mypenguinCollection.get(i);

      float distance = loc.distanceTo(other.loc);

      if (distance > 0 && distance < 50) {

        steer.addSelf(other.speed);
        count++;
      }
    }

    if (count > 0) {

      steer.scaleSelf(1.0/count);
    }

    steer.scaleSelf(magnitude);
    acc.addSelf(steer);
  }

  void cohesion(float magnitude) {
    countNeighbours=0;
    Vec3D sum = new Vec3D();

    int count = 0;

    for (int i=0; i < mypenguinCollection.size();i++) {
      penguin other = (penguin) mypenguinCollection.get(i);

      float distance = loc.distanceTo(other.loc);

      if (distance > radius*2.5 && distance < 40) {

        sum.addSelf(other.loc);
        count++;
      }

      if (distance > radius*2.5 && distance < 40) {

        sum.addSelf(other.loc);
        count++;
      }

      if (distance > radius*2.5 && distance < 40) {

        sum.addSelf(other.loc);
        count++;
      }

      if (distance>0&&distance<(radius*2+8)) {

        countNeighbours++;
      }
    }

    if (count > 0) {
      sum.scaleSelf(1.0/count);
    }

    Vec3D steer = sum.sub(loc);
    steer.scaleSelf(magnitude);

    acc.addSelf(steer);
  }

  void separate(float magnitude) {

    Vec3D steer = new Vec3D();

    int count = 0;


    for (int i=0; i < mypenguinCollection.size();i++) {
      penguin other = (penguin) mypenguinCollection.get(i);

      float distance = loc.distanceTo(other.loc);

      if (distance>0 && distance<radius*2) {

        Vec3D diff = loc.sub(other.loc);
        diff.normalizeTo(distance);

        steer.addSelf(diff);
        count++;
      }
    }

    if (count > 0) {

      steer.scaleSelf(1.0/count);
    }
    steer.scaleSelf(magnitude);
    acc.addSelf(steer);
  }
}

//boolean seperate = 
Vec3D loc = new Vec3D (0, 0, 0); 
Vec3D speed = new Vec3D (10000, 0, 0);
Vec3D gravity = new Vec3D (0, 0.2, 0);
Vec3D acc= new Vec3D(0, 0, 0);
Vec3D vel = new Vec3D(0, 0, 0);
Vec3D target = new Vec3D( 300, 300, 0);
float radius = 10;
int countCentrality =0;
float velMax= .8;
int countNeighbours=0;
int temperature= 40;
float cohMag=.000001;
float sepMag=2;

void mousePressed() {
  if (mouseButton == LEFT) {

    for (int i=mypenguinCollection.size()-1; i>=0; i--) {
      penguin other = (penguin) mypenguinCollection.get(i);
      if (dist(mouseX, mouseY, other.loc.x, other.loc.y) < 7.5) {
        //      mypenguinCollection.remove(i);
        other.target= new Vec3D(random(75, 115), random(75, 115), 0);
        float distance= other.loc.distanceTo(other.target);
        other.velMax=map(distance, 0, width, 0, 5);

        other.cohMag=other.cohMag*-1;
        other.sepMag=0;
      }
    }
  }
  else if (mouseButton == RIGHT) {
    for (int i=mypenguinCollection.size()-1; i>=0; i--) {
      penguin other = (penguin) mypenguinCollection.get(i);
      if (dist(mouseX, mouseY, other.loc.x, other.loc.y) < 7.5) {
        //      mypenguinCollection.remove(i);
        other.target= new Vec3D(300, 300, 0);
        float distance= other.loc.distanceTo(other.target);
        other.velMax=map(distance, 0, width, 0, 5);

        //vel.clear();
        //acc.clear();
        other.cohMag=other.cohMag*0.1;
        other.sepMag=1;
      }
    }
  }
}

20131107_140628

Sign In or Register to comment.