Daily Creative Coding

元「30 min. Processing」。毎日、Creative Codingします。

吸収・爆発するパーティクル

/**
* Particles for Absorption and Explosion 
*
* @author aa_debdeb
* @date 2015/10/04
*/


float MAX_RADIOUS = 100;
float MAX_SPEED = 20;
float EXPLOSION_NUM = 10;

ArrayList<Particle> particles;

void setup(){
  size(500, 500);
  smooth();
  frameRate(24);
  noStroke();
  
  particles = new ArrayList<Particle>();
  particles.add(new Particle());
  particles.add(new Particle());
  particles.add(new Particle());

}

void draw(){
  background(255);
  for(Particle particle: particles){
    particle.draw();
  } 
  for(Particle particle: particles){
    particle.update();
  }
    
  ArrayList<Particle> deleteParticles = new ArrayList<Particle>();
  for(int i = 0; i < particles.size() - 1; i++){
    Particle p1 = particles.get(i);
    for(int j = i + 1; j < particles.size(); j++){
       Particle p2 = particles.get(j);
       if(!p1.absorbed && !p2.absorbed && p1.timeAfterExplosion >= 10 && p2.timeAfterExplosion >= 10 && p1.isContactWith(p2)){
         if(p1.radious >= p2.radious){
           p1.absorb(p2);
           deleteParticles.add(p2);
           p2.absorbed = true;
         } else{
           p2.absorb(p1);
           deleteParticles.add(p1);
           p1.absorbed = true;
         }
       }
    }
  }
  for(Particle p: deleteParticles){
    particles.remove(p);
  }
  
  ArrayList<Particle> appendParticles = new ArrayList<Particle>();
  deleteParticles = new ArrayList<Particle>();
  for(Particle p: particles){
    if(p.radious >= MAX_RADIOUS - 5.0){
      ArrayList<Particle> childrens = p.explode();
      for(Particle c: childrens){
        appendParticles.add(c); 
      }
      deleteParticles.add(p);
    }
  }
  for(Particle p: appendParticles){
    particles.add(p);
  }
  for(Particle p: deleteParticles){
    particles.remove(p);
  }
  
}

class Particle{

  PVector position;
  PVector velocity;
  float radious;
  boolean absorbed;
  int timeAfterExplosion;
  
  Particle(){
    position = new PVector(width / 2, height / 2);
    float radian = random(PI * 2);
    float speed = random(MAX_SPEED);
    velocity = new PVector(speed * cos(radian), speed * sin(radian));
    radious = MAX_RADIOUS;
    absorbed = false;
    timeAfterExplosion = 0;
  }
  
  Particle(Particle p){
    position = new PVector(p.position.x, p.position.y);
    float radian = random(PI * 2);
    float speed = random(MAX_SPEED);
    velocity = new PVector(speed * cos(radian), speed * sin(radian));
    radious = p.radious * sqrt(1.0 / EXPLOSION_NUM);
    absorbed = false;
    timeAfterExplosion = 0;
  }
  
  void draw(){
    fill(0);
    arc(position.x, position.y, radious * 2, radious * 2, 0, TWO_PI);
  }
  
  void update(){
    position.add(velocity);
    if(position.x < radious){
      position.x = radious;
      velocity.x *= -1;
    } else if(position.x >= width - radious){
      position.x = width - radious;
      velocity.x *= -1;
    }
    if(position.y < radious){
      position.y = radious;
      velocity.y *= -1;
    } else if(position.y >= height - radious){
      position.y = height - radious;
      velocity.y *= -1;
    }
    
    timeAfterExplosion += 1;
  }
  
  void absorb(Particle p){
    radious = sqrt(sq(radious) + sq(p.radious));
  }
  
  ArrayList<Particle> explode(){
    ArrayList<Particle> childrens = new ArrayList<Particle>();
    for(int i = 0; i < EXPLOSION_NUM; i++){
      childrens.add(new Particle(this));
    }
    return childrens;
  }
  
  boolean isContactWith(Particle p){
    if(position.dist(p.position) <= radious + p.radious){
      return true;
    } else {
      return false;
    }
  }
  
  
}
http://aa-debdeb.tumblr.com/post/130533069341/http30min-processinghatenablogcomentry20151