• fullscreen
  • Statistical_Newton.pde
  • input.pde
  • particles.pde
  • Particles ParticleSystem;
    String s;
    int selected;
    void setup() {
      size(800, 200, P2D);
      int maxParticles = 19600;
      ParticleSystem = new Particles( maxParticles ); 
      /*
      ParticleSystem.spawnCircleFactor = 0.20;
       ParticleSystem.deathCircleFactor = 0.20;
       ParticleSystem.spawnAnnulusFactor = 0.44;
       ParticleSystem.deathAnnulusFactor = 0.20;
       */
      // inherited phi = bouncing swarm...
      ParticleSystem.spawnCircleFactor = 0.65;
      ParticleSystem.deathCircleFactor = 0.05;
      ParticleSystem.spawnAnnulusFactor = 0.0;
      ParticleSystem.deathAnnulusFactor = 0.75;
    
      for (int i = 0; i < maxParticles; ++i) {
        ParticleSystem.addParticle( random(width), random(height) );
      }
      textMode(SCREEN);
      loadPixels();
      selected = 0;
    }
    
    void draw() {
      ParticleSystem.updateParticles();
      ParticleSystem.moveParticles();
      s = "radius: " + (sqrt(ParticleSystem.rSq));
    
      Arrays.fill(pixels, 0);
    
      int xy, p;
      for (int i = 0; i < ParticleSystem.total(); ++i) {
    
        xy =  ParticleSystem.getX(i) + ParticleSystem.getY(i)*width;
        p = min((pixels[xy] & 0xFF) + 1, 0xFF);
        pixels[xy] = min(0xFF0000, (p<<21)) + min(0xFF00, (p<<11)) + p;
      }
    
      updatePixels();
      s = "Number of particles: " + ParticleSystem.total();
      text(s, 10, 18);
      s = "Radius: " + int(sqrt(ParticleSystem.rSq));
      text(s, 10, 36);
      s = "Circle spawn rate: " + ParticleSystem.spawnCircleFactor;
      text(s, 10, 54);
      s = "Circle death rate: " + ParticleSystem.deathCircleFactor;
      text(s, 10, 72);
      s = "Annulus spawn rate: " + ParticleSystem.spawnAnnulusFactor;
      text(s, 10, 90);
      s = "Annulus death rate: " + ParticleSystem.deathAnnulusFactor;
      text(s, 10, 108);
      text('>', 2, 36 + selected*18);
      if (ParticleSystem.total() == 0){
        text("Press SPACE to respawn", 10, 126);
      }
    
    }
    
    
    void keyPressed() {
      if (key == ' ') {
        for (int i = 0; i < 10; ++i) {
          ParticleSystem.addParticle( random(width), random(height), random(TWO_PI) );
        }
      }
    
      switch(keyCode) {
      case UP:
        selected = (selected + 4) % 5;
        break;
      case DOWN:
        selected = (selected + 1) % 5;
        break;
      }
    
      switch(selected) {
      case 0:
        switch(keyCode) {
        case LEFT:
          ParticleSystem.rSq = max((sqrt(ParticleSystem.rSq) - 1)*(sqrt(ParticleSystem.rSq) - 1), 0);
          break;
        case RIGHT:
          ParticleSystem.rSq = min((sqrt(ParticleSystem.rSq) + 1)*(sqrt(ParticleSystem.rSq) + 1), 60*60);
          break;
        }
        break;
      case 1:
        switch(keyCode) {
        case LEFT:
          ParticleSystem.spawnCircleFactor = max(0.0, ParticleSystem.spawnCircleFactor - 0.01);
          break;
        case RIGHT:
          ParticleSystem.spawnCircleFactor = min(1.0, ParticleSystem.spawnCircleFactor + 0.01);
          break;
        }
        break;
      case 2:
        switch(keyCode) {
        case LEFT:
          ParticleSystem.deathCircleFactor = max(0.0, ParticleSystem.deathCircleFactor - 0.01);
          break;
        case RIGHT:
          ParticleSystem.deathCircleFactor = min(1.0, ParticleSystem.deathCircleFactor + 0.01);
          break;
        }
        break;
      case 3:
        switch(keyCode) {
        case LEFT:
          ParticleSystem.spawnAnnulusFactor = max(0.0, ParticleSystem.spawnAnnulusFactor - 0.01);
          break;
        case RIGHT:
          ParticleSystem.spawnAnnulusFactor = min(1.0, ParticleSystem.spawnAnnulusFactor + 0.01);
          break;
        }
        break;
      case 4:
        switch(keyCode) {
        case LEFT:
          ParticleSystem.deathAnnulusFactor = max(0.0, ParticleSystem.deathAnnulusFactor - 0.01);
          break;
        case RIGHT:
          ParticleSystem.deathAnnulusFactor = min(1.0, ParticleSystem.deathAnnulusFactor + 0.01);
          break;
        }
        break;
      }
    }
    
    
    class Particles {
      float[] x, y, phi;
      int totalParticles;
      public float rSq, spawnCircleFactor, deathCircleFactor, spawnAnnulusFactor, deathAnnulusFactor;
    
      public Particles( int maxParticles ){
        totalParticles = 0;
    
        x = new float[maxParticles];
        y = new float[maxParticles];
        phi = new float[maxParticles];
    
        for (int i = 0; i < maxParticles; ++i){
          x[i] = y[i] = phi[i] = 0;
        }
    
        rSq = 30*30;  //radius squared
      }
    
      void addParticle( float _x, float _y ){
        if (totalParticles < x.length){
          x[totalParticles] = _x;
          y[totalParticles] = _y;
          phi[totalParticles] = random(TWO_PI);
          ++totalParticles;
        }
      }
      void addParticle( float _x, float _y, float _phi ){
        if (totalParticles < x.length){
          x[totalParticles] = _x;
          y[totalParticles] = _y;
          phi[totalParticles] = _phi;
          ++totalParticles;
        }
      }
    
      void addParticles( float _x, float _y, int newParticles ){
        while (totalParticles < x.length && newParticles > 0){
          addParticle( _x, _y );
          --newParticles;
        }
        if (newParticles > 0){
          println( " Particles discarded: " + newParticles );
        } 
      }
    
      void killParticle( int Particle ){
        if (Particle < totalParticles ){
          --totalParticles;
          x[Particle] = x[totalParticles];
          y[Particle] = y[totalParticles];
          phi[Particle] = phi[totalParticles];
        }
        else println( " trying to kill Particle out of bounds! " );
      }
    
      void moveParticles(){
        for (int i = 0; i < totalParticles; ++i){
          x[i] = (x[i]+sin(phi[i])/2+width)%width;
          y[i] = (y[i]+cos(phi[i])/2+height)%(height);
          phi[i] = (TWO_PI+phi[i]+random(-QUARTER_PI/2, QUARTER_PI/2))%TWO_PI;
        }
      }
    
      void updateParticles(){
        int Particle1, Particle2;
        float distance;
    
        // Death Circle
        for (int i = 0; i < int(totalParticles*deathCircleFactor); ++i){
          Particle1 = int(random(totalParticles));
          Particle2 = int(random(totalParticles));
    
          if ( (x[Particle1]-x[Particle2])*(x[Particle1]-x[Particle2]) + (y[Particle1]-y[Particle2])*(y[Particle1]-y[Particle2]) < rSq){
            if (random(1) < 0.5){
              killParticle( Particle1 );
            } 
            else {
              killParticle( Particle2 );
            }
          }
        }
    
        // Death Annulus
        for (int i = 0; i < int(totalParticles*deathAnnulusFactor); ++i){
    
          Particle1 = int(random(totalParticles));
          Particle2 = int(random(totalParticles));
    
          distance = (x[Particle1]-x[Particle2])*(x[Particle1]-x[Particle2]) + (y[Particle1]-y[Particle2])*(y[Particle1]-y[Particle2]);
    
          if ( distance > rSq && distance < 9*rSq ){
            if (random(1) < 0.5){
              killParticle( Particle1 );
            } 
            else {
              killParticle( Particle2 );
            }
          }
        }    
    
        // Spawn Annulus
        for (int i = 0; i < int(totalParticles*spawnAnnulusFactor) && totalParticles < x.length; ++i){
          Particle1 = int(random(totalParticles));
          Particle2 = int(random(totalParticles));
    
          distance = (x[Particle1]-x[Particle2])*(x[Particle1]-x[Particle2]) + (y[Particle1]-y[Particle2])*(y[Particle1]-y[Particle2]);
    
          if ( distance > rSq && distance < 9*rSq ){
            if (random(1) < 0.5){
              addParticle( x[Particle1], y[Particle1], phi[Particle1] );
            } else {
              addParticle( x[Particle2], y[Particle2], phi[Particle2] );
            }
          }
        }
    
        // Spawn Circle
        for (int i = 0; i < int(totalParticles*spawnCircleFactor) && totalParticles < x.length; ++i){
          Particle1 = int(random(totalParticles));
          Particle2 = int(random(totalParticles));
    
          if ( (x[Particle1]-x[Particle2])*(x[Particle1]-x[Particle2]) + (y[Particle1]-y[Particle2])*(y[Particle1]-y[Particle2]) < rSq){
            if (random(1) < 0.5){
              addParticle( x[Particle1], y[Particle1], phi[Particle1] );
            } else {
              addParticle( x[Particle2], y[Particle2], phi[Particle2] );
            }
          }
        }
    
      }
    
      int total(){
        return totalParticles;
      }
    
      int getX(int i){
        return int(x[i]);
      }
    
      int getY(int i){
        return int(y[i]);
      }
      
      boolean full(){
        return (totalParticles == x.length);
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    Job van der Zwan

    Bouncing Swarm

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

    I'm not quite sure why we get an emergent swarm that moves as a bouncing ball either..

    UP/DOWN - select variable
    LEFT/RIGHT - increase/decrease value of selected variable

    Matt Greenslade
    30 Dec 2011
    Really good
    You need to login/register to comment.