• fullscreen
  • emergence_exp2.pde
  • int NUM_OF_AGENTS = 1000;
    int HORIZON = 45;
    Agent[] agents = new Agent[NUM_OF_AGENTS];
    
    void setup() {
      size(900, 500);
      ellipseMode(CENTER);
      for(int i = 0; i < NUM_OF_AGENTS; i++) {
        agents[i] = new Agent();
      }
    }
    
    void draw() {
      float sumR = 0.0;
      float sumG = 0.0;
      float sumB = 0.0;
      int numNeightbours = 1;
      background(#CCEEFF);
      for(int i = 0; i < NUM_OF_AGENTS; i++) {
        color cs = agents[i].getColor();
        sumR = red(cs)+0.0;
        sumG = green(cs)+0.0;
        sumB = blue(cs)+0.0;
        numNeightbours = 1;
        for(int j = 0; j < NUM_OF_AGENTS; j++) {
          if(j != i) {
            boolean b = agents[i].attractionLaw(agents[j]);
            if (b == true) {
              color c = agents[j].getColor();
              sumR += red(c);
              sumG += green(c);
              sumB += blue(c);
              numNeightbours += 1;
            }
          }
        }
        if(numNeightbours > 1) {
          agents[i].colorConvergenceLaw(color(round(sumR/numNeightbours), round(sumG/numNeightbours), round(sumB/numNeightbours)));
          agents[i].updateColor();
        }
        // border collision avoiding
        if(agents[i].position.x < 0.0) {
          agents[i].speed.x += 5;
        }
        else if(agents[i].position.x > width) {
          agents[i].speed.x -= 5;
        }
        if(agents[i].position.y < 0.0) {
          agents[i].speed.y += 5;
        }
        else if(agents[i].position.y > height) {
          agents[i].speed.y -= 5;
        }
        // end border collision avoiding
        // drag force
        agents[i].speed.x -= agents[i].speed.x*0.21;
        agents[i].speed.y -= agents[i].speed.y*0.21;
        // end drag force
        agents[i].updatePosition();
        fill(agents[i].getColor());
        ellipse(agents[i].position.x, agents[i].position.y, 9, 9);
      }
    }
    
    void mouseClicked() {
      for(int i = 0; i < NUM_OF_AGENTS; i++) {
        agents[i].c = color(floor(random(255)), floor(random(255)), floor(random(255)));
      }
    }
    
    class Agent {
      public color c;
      protected color nextC;
      public Vector position;
      public Vector speed;
      
      
      Agent() {
        this.position = new Vector(random(width), random(height));
        this.speed = new Vector(random(-10, 10), random(-10, 10));
        this.c = color(floor(random(255)), floor(random(255)), floor(random(255)));
      }
      
      float colorDistance(color c2) {
        float distR = red(this.c) - red(c2);
        float distG = green(this.c) - green(c2);
        float distB = blue(this.c) - blue(c2);
        return(sqrt(pow(distR, 2) + pow(distG, 2) + pow(distB, 2)));
      }
      
      boolean attractionLaw(Agent other) {
        float COEFF = 0.09;
        float d = dist(this.position.x, this.position.y, other.position.x, other.position.y);
        if(d > HORIZON) {
          // return false if other is over the horizon
          return false;
        }
        
        float f = (10 - 0.1*colorDistance(other.c))*COEFF;
        if(f < (-10.0)*COEFF) {
          f = (-10.0)*COEFF;
        }
        if(colorDistance(other.c) < 20) {
          f = (-5.0)*COEFF;
        }
        
        // collision avoiding
        if(d < 20) {
          f -= (100/(d+1)-(100/21))*COEFF;
        }
        Vector attractionForce = new Vector(f*((other.position.x-this.position.x)/d), f*((other.position.y-this.position.y)/d));
        this.speed.x += attractionForce.x;
        this.speed.y += attractionForce.y;
        if(d < 40) {
          return true;
        }
        return false;
      }
      
      void colorConvergenceLaw(color averageColor) {
        float COEFF = 0.05;
        float distR = red(averageColor) - red(this.c);
        float distG = green(averageColor) - green(this.c);
        float distB = blue(averageColor) - blue(this.c);
        int r = round(red(this.c) + COEFF*distR);
        int g = round(green(this.c) + COEFF*distG);
        int b = round(blue(this.c) + COEFF*distB);
        this.nextC = color(r, g, b);
      }
      
      color getColor() {
        return this.c;
      }
      
      void updateColor() {
        this.c = this.nextC;
      }
      
      void updatePosition() {
        this.position.x += this.speed.x;
        this.position.y += this.speed.y;
      }
    }
    
    class Vector {
      public float x;
      public float y;
      
      Vector(float x, float y) {
        this.x = x;
        this.y = y;
      }
    }
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    Nonegiven

    Emergence Experiment 2.01 rev 6

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

    Full credit to Luca Ongaro for the coding.
    This is just a tweak. I found that the potential for this code was really laid bare when i got agent counts up in the thousands. Kinda blew my mind really. I am looking into openCL and possibly being able to get the counts into the hundreds of thousands.

    Original Text:
    Simple rules cause dumb agents to display a complex social behavior, organizing in "multi-cellular" structures capable of moving. The basic rules are:
    - Every agent is attracted by agents with quite similar colours, but repelled by agents with different or very similar colours

    Jotham Read
    3 May 2010
    Wow that's fucking sick
    Luca Ongaro
    30 Oct 2010
    This is so damn cool. Thanks for crediting!
    is the code an all versus all comparison?
    And how to the nodes change color, what is the rule for that?

    Cheers Arend
    Replica3363
    18 Nov 2012
    Kind of 'speciation' mechanism. Gives fascinating patterns and dynamics : love it !
    You need to login/register to comment.