• fullscreen
  • Boid.pde
  • Flock.pde
  • flockPaintingCamera.pde
  • // The Boid class
    
    class Boid {
    
      PVector location;
      PVector velocity;
      PVector acceleration;
      float r;
      float maxforce;    // Maximum steering force
      float maxspeed;    // Maximum speed
    
      Boid(float x, float y) {
        acceleration = new PVector(0,0);
        velocity = new PVector(random(-1,1),random(-1,1));
        location = new PVector(x,y);
        r = 2.0;
        maxspeed = 2;
        maxforce = 0.03;
      }
    
      void run(ArrayList<Boid> boids) {
        flock(boids);
        update();
        borders();
        render();
      }
    
      void applyForce(PVector force) {
        // We could add mass here if we want A = F / M
        acceleration.add(force);
      }
    
      // We accumulate a new acceleration each time based on three rules
      void flock(ArrayList<Boid> boids) {
        PVector sep = separate(boids);   // Separation
        PVector ali = align(boids);      // Alignment
        PVector coh = cohesion(boids);   // Cohesion
        // Arbitrarily weight these forces
        sep.mult(1.5);
        ali.mult(1.0);
        coh.mult(1.0);
        // Add the force vectors to acceleration
        applyForce(sep);
        applyForce(ali);
        applyForce(coh);
      }
    
      // Method to update location
      void update() {
        // Update velocity
        velocity.add(acceleration);
        // Limit speed
        velocity.limit(maxspeed);
        location.add(velocity);
        // Reset accelertion to 0 each cycle
        acceleration.mult(0);
      }
    
      // A method that calculates and applies a steering force towards a target
      // STEER = DESIRED MINUS VELOCITY
      PVector seek(PVector target) {
        PVector desired = PVector.sub(target,location);  // A vector pointing from the location to the target
        // Normalize desired and scale to maximum speed
        desired.normalize();
        desired.mult(maxspeed);
        // Steering = Desired minus Velocity
        PVector steer = PVector.sub(desired,velocity);
        steer.limit(maxforce);  // Limit to maximum steering force
        return steer;
      }
      
      void render() {
        // Draw a triangle rotated in the direction of velocity
       /* float theta = velocity.heading2D() + radians(90);
        fill(200,100);
        stroke(255);
        pushMatrix();
        translate(location.x,location.y);
        rotate(theta);
        beginShape(TRIANGLES);
        vertex(0, -r*2);
        vertex(-r, r*2);
        vertex(r, r*2);
        endShape();
        popMatrix();*/
      }
    
      // Wraparound
      void borders() {
        if (location.x < -r) location.x = width+r;
        if (location.y < -r) location.y = height+r;
        if (location.x > width+r) location.x = -r;
        if (location.y > height+r) location.y = -r;
      }
    
      // Separation
      // Method checks for nearby boids and steers away
      PVector separate (ArrayList<Boid> boids) {
        float desiredseparation = 25.0f;
        PVector steer = new PVector(0,0,0);
        int count = 0;
        // For every boid in the system, check if it's too close
        for (Boid other : boids) {
          float d = PVector.dist(location,other.location);
          // 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
            PVector diff = PVector.sub(location,other.location);
            diff.normalize();
            diff.div(d);        // Weight by distance
            steer.add(diff);
            count++;            // Keep track of how many
          }
        }
        // Average -- divide by how many
        if (count > 0) {
          steer.div((float)count);
        }
    
        // As long as the vector is greater than 0
        if (steer.mag() > 0) {
          // Implement Reynolds: Steering = Desired - Velocity
          steer.normalize();
          steer.mult(maxspeed);
          steer.sub(velocity);
          steer.limit(maxforce);
        }
        return steer;
      }
    
      // Alignment
      // For every nearby boid in the system, calculate the average velocity
      PVector align (ArrayList<Boid> boids) {
        float neighbordist = 50;
        PVector sum = new PVector(0,0);
        int count = 0;
        for (Boid other : boids) {
          float d = PVector.dist(location,other.location);
          if ((d > 0) && (d < neighbordist)) {
            sum.add(other.velocity);
            count++;
          }
        }
        if (count > 0) {
          sum.div((float)count);
          sum.normalize();
          sum.mult(maxspeed);
          PVector steer = PVector.sub(sum,velocity);
          steer.limit(maxforce);
          return steer;
        } else {
          return new PVector(0,0);
        }
      }
    
      // Cohesion
      // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
      PVector cohesion (ArrayList<Boid> boids) {
        float neighbordist = 50;
        PVector sum = new PVector(0,0);   // Start with empty vector to accumulate all locations
        int count = 0;
        for (Boid other : boids) {
          float d = PVector.dist(location,other.location);
          if ((d > 0) && (d < neighbordist)) {
            sum.add(other.location); // Add location
            count++;
          }
        }
        if (count > 0) {
          sum.div(count);
          return seek(sum);  // Steer towards the location
        } else {
          return new PVector(0,0);
        }
      }
    }
    
    
    
    // The Flock (a list of Boid objects)
    
    class Flock {
      ArrayList<Boid> boids; // An ArrayList for all the boids
    
      Flock() {
        boids = new ArrayList<Boid>(); // Initialize the ArrayList
      }
    
      void run() {
        for (Boid b : boids) {
          b.run(boids);  // Passing the entire list of boids to each boid individually
        }
      }
    
      void addBoid(Boid b) {
        boids.add(b);
      }
    
    }
    
    
    /**
     * FlockingCamera
     *
     * por Sandro Miccoli
     *
     * As partículas simulam o voo de pássaros e pintam dinamicamente a tela.
     * 
     * Para interagir:
     *
     * c - Alterna entre o modo de pintura e o modo de visualização do movimento dos pássaros
     * n - Cria um pássaro novo na tela
     * 
     * Clique na tela para gerar mais pássaros.
     */
     
     
    import processing.video.*;
    
    Flock flock;
    
    Capture video;
    int myWidth = 640;
    int myHeight = 480;
    
    boolean flag=false;
    
    void setup() {
      
      //img = loadImage("crows.jpg");
      
      video = new Capture(this, myWidth, myHeight);
      //video.start(); // For Linux, this will only work in newer versions of Processing (2.0+)
      noStroke();
      smooth(); 
      
      size(myWidth, myHeight);
      background(0);
      smooth();
      flock = new Flock();
      // Add an initial set of boids into the system
      for (int i = 0; i < 10; i++) {
        flock.addBoid(new Boid(480+random(120), 75+random(100)));
      }
    }
    
    void draw() {
      
      if (video.available()){
        video.read();
        video.loadPixels();
      }
      flock.run();
      if (flag){
        background(0); 
      }
      if (keyPressed) {    
        switch(key) {
        case 'c' :
          if (flag)
            flag=false;
          else
            flag=true;
          break;
        case 'n' :
          flock.addBoid(new Boid(random(width), random(height)));
          break;
        }
      }
    
      for (int i=0; i < flock.boids.size(); i++) {
        draw_line(int(flock.boids.get(i).location.x), int(flock.boids.get(i).location.y));
      }
    }
    
    // Add a new boids into the System
    void mousePressed() {
      for (int i=0; i<5; i++){
        flock.addBoid(new Boid(mouseX, mouseY));
      }
    }
    
    
    void draw_line(int x, int y) {
    
      int loc = x + y*myWidth;
    
      loadPixels();
      float r = 0;
      float g = 0;
      float b = 0;
      
      // Condição pra só pegar a cor do pixel quando tiver dentro da tela, ou seja, dentro do limite da imagem.
      if ((loc>0)&&(loc<video.pixels.length)) {
        r = red(video.pixels[loc]);
        g = green(video.pixels[loc]);
        b = blue(video.pixels[loc]);
      }
      pushStyle();
    
      strokeWeight(2);
      stroke(r, g, b, 225); // Necessário pra dar "fill" na linha
      line(x,y,x+random(-5,5),y+random(-5,5));
      
      popStyle();
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Sandro Miccoli

    flockCameraPainting

    Add to Faves Me Likey@! 2
    You must login/register to add this sketch to your favorites.

    This will not work on the browser.

    This sketch will only work on newer versions of Processing (2.0+), or in Windows and Macs.

    Only a little tweak for this sketch:
    http://www.openprocessing.org/sketch/67038

    Sandro Miccoli
    29 Mar 2013
    I've uploaded a video to show it working:
    http://www.youtube.com/watch?v=A4Bt7SQn37g
    You need to login/register to comment.