日常の進捗

主に自分のための,行為とその習慣化の記録

Mod: Coding Challenge #27: Fireworks!(2D+3D)

Processingの花火のシミュレータは夏に作ったけど、こちらのほうが爆発時や爆発後の処理が洗練されている。動画視聴しながら2D版を作って、3Dに移植している。

f:id:takawo:20170928193125g:plain

コード(3D)

PVector gravity = new PVector(0, 0.1);
ArrayList<ParticleSystem> particleSystem;

// setup関数 : 初回1度だけ実行される
void setup() {
  size(960, 540, P3D); // ウィンドウサイズを960px,540pxに
  colorMode(HSB, 360, 100, 100, 100); // HSBでの色指定にする
  smooth(); // 描画を滑らかに
  particleSystem = new ArrayList<ParticleSystem>();
}

// draw関数 : setup関数実行後繰り返し実行される
void draw() {
  translate(width/2, height/2, map(sin(frameCount*0.01), -1, 1, 0, -1000));
  rotateX(-PI/4);
  rotateY(frameCount*0.01);
  background(220, 80, 20);
  fill(0, 0, 100, 20);
  noStroke();
  beginShape();
  vertex(-width/2, height, -500);  
  vertex(-width/2, height, 500);  
  vertex(width/2, height, 500);  
  vertex(width/2, height, -500);  
  endShape(CLOSE);

  if (random(1) < 0.05) {
    particleSystem.add(new ParticleSystem());
  }
  for (int i = particleSystem.size()-1; i >= 0; i--) {
    ParticleSystem ps = particleSystem.get(i);
    ps.run();
    if (ps.done()) {
      particleSystem.remove(ps);
    }
  }
}

class Particle {
  PVector pos;
  PVector vel;
  PVector acc;
  float life = 100;
  float lifeSpan = random(life/50, life/30);
  boolean seed = false;
  color c;
  Particle() {
    pos = new PVector(random(-width/2, width/2), height, random(-500, 500));
    vel = new PVector(0, random(-12, -6));
    acc = new PVector(0, 0.1);
    c = color(random(360), 80, 100);
  }
  Particle(float x, float y, float hue) {
    pos = new PVector(x, y, random(-500, 500));
    vel = new PVector(0, random(-12, -6));
    acc = new PVector(0, 0.1);
    c = color(hue, 80, 100);
    seed = true;
  }
  Particle(PVector _pos, float hue) {
    pos = new PVector(_pos.x, _pos.y, _pos.z);
    vel = PVector.random3D();
    vel.mult(random(4, 6));
    acc = new PVector(0, 0.1);
    c = color(hue, 80, 100);
  }

  void update() {
    pos.add(vel);
    vel.add(acc);
    if (!seed) {
      life -= lifeSpan;
      vel.mult(0.98);
    }
    acc.mult(0);

    if (pos.y > height) {
      pos= new PVector(random(-width/2, width/2), height, random(-500, 500));
      vel = new PVector(0, random(-12, -8));
    }
  }

  void draw() {
    stroke(c, life);
    strokeWeight(4);
    pushMatrix();
    translate(pos.x, pos.y, pos.z);
    point(0, 0);
    popMatrix();
  }

  void applyForce(PVector force) {
    acc.add(force);
  }

  void run() {
    update();
    draw();
  }
  boolean isDead() {
    if (life < 0) {
      return true;
    }
    return false;
  }

  boolean explode() {
    if (seed && vel.y > 0) {
      lifeSpan = 0;
      return true;
    }
    return false;
  }
}

class ParticleSystem {
  ArrayList<Particle> particles;
  Particle p;
  float hue;
  ParticleSystem() {
    hue = random(360);
    p = new Particle(random(-width/2, width/2), height, hue);
    particles = new ArrayList<Particle>();
  }
  boolean done() {
    if (p == null && particles.isEmpty()) {
      return true;
    } else {
      return false;
    }
  }
  void run() {
    if (p != null) {
      p.applyForce(gravity);
      p.update();
      p.draw();
      if (p.explode()) {
        for (int i = 0; i < 100; i++) {
          particles.add(new Particle(p.pos, hue));
        }
        p = null;
      }
    }
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle child = particles.get(i);
      child.applyForce(gravity);
      child.run();
      if (child.isDead()) {
        particles.remove(child);
      }
    }
  }
}

f:id:takawo:20170928193131g:plain

コード(2D)

PVector gravity = new PVector(0, 0.1);
ArrayList<ParticleSystem> particleSystem;

// setup関数 : 初回1度だけ実行される
void setup() {
  size(960, 540); // ウィンドウサイズを960px,540pxに
  colorMode(HSB, 360, 100, 100, 100); // HSBでの色指定にする
  smooth(); // 描画を滑らかに
  particleSystem = new ArrayList<ParticleSystem>();
}

// draw関数 : setup関数実行後繰り返し実行される
void draw() {
  background(220, 80, 20);
  if (random(1) < 0.05) {
    particleSystem.add(new ParticleSystem());
  }
  for (int i = particleSystem.size()-1; i >= 0; i--) {
    ParticleSystem ps = particleSystem.get(i);
    ps.run();
    if (ps.done()) {
      particleSystem.remove(ps);
    }
  }
}

class Particle {
  PVector pos;
  PVector vel;
  PVector acc;
  float life = 100;
  float lifeSpan = random(life/50, life/30);
  boolean seed = false;
  color c;
  Particle() {
    pos = new PVector(random(width), height);
    vel = new PVector(0, random(-12, -6));
    acc = new PVector(0, 0.1);
    c = color(random(360), 80, 100);
  }
  Particle(float x, float y, float hue) {
    pos = new PVector(x, y);
    vel = new PVector(0, random(-12, -6));
    acc = new PVector(0, 0.1);
    c = color(hue, 80, 100);
    seed = true;
  }
  Particle(PVector _pos, float hue) {
    pos = new PVector(_pos.x, _pos.y);
    vel = PVector.random2D();
    vel.mult(random(4, 6));
    acc = new PVector(0, 0.1);
    c = color(hue, 80, 100);
  }

  void update() {
    pos.add(vel);
    vel.add(acc);
    if (!seed) {
      life -= lifeSpan;
      vel.mult(0.98);
    }
    acc.mult(0);

    if (pos.y > height) {
      pos= new PVector(random(width), height);
      vel = new PVector(0, random(-12, -8));
    }
  }

  void draw() {
    stroke(c, life);
    strokeWeight(10);
    point(pos.x, pos.y);
  }

  void applyForce(PVector force) {
    acc.add(force);
  }

  void run() {
    update();
    draw();
  }
  boolean isDead() {
    if (life < 0) {
      return true;
    }
    return false;
  }

  boolean explode() {
    if (seed && vel.y > 0) {
      lifeSpan = 0;
      return true;
    }
    return false;
  }
}

class ParticleSystem {
  ArrayList<Particle> particles;
  Particle p;
  float hue;
  ParticleSystem() {
    hue = random(360);
    p = new Particle(random(width), height, hue);
    particles = new ArrayList<Particle>();
  }
  boolean done() {
    if (p == null && particles.isEmpty()) {
      return true;
    } else {
      return false;
    }
  }
  void run() {
    if (p != null) {
      p.applyForce(gravity);
      p.update();
      p.draw();
      if (p.explode()) {
        for (int i = 0; i < 100; i++) {
          particles.add(new Particle(p.pos, hue));
        }
        p = null;
      }
    }
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle child = particles.get(i);
      child.applyForce(gravity);
      child.run();
      if (child.isDead()) {
        particles.remove(child);
      }
    }
  }
}

リファレンス