日常の進捗

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

花火

花火を観に行けてないので打ち上げた。いつもそうだけど、今回は特に勢いで書いた感じになった。 マウスをクリックした位置で花火が爆発する。

ArrayList<Mover> movers = new ArrayList<Mover>();

void setup() {
  fullScreen();
  colorMode(HSB, 360, 100, 100);
  background(0, 0, 0);
}

void draw() {
  fill(0, 0, 0, 20);
  rect(0, 0, width, height);
  for (Mover m : movers) {
    m.update();
    m.draw();
  }
  // delete burned movers
  ArrayList<Mover> deleteMovers = new ArrayList<Mover>();
  for (Mover m : movers) {
    if (m.pos.y > height) {
      deleteMovers.add(m);
    }
  }

  for (Mover rm : deleteMovers) {
    movers.remove(rm);
  }
}

void mousePressed() {
  float rMax = random(10, 50);
  float rMin = rMax/5;
  float rSeparation = random(5, 10);
  for (float r = rMin; r < rMax; r += rMax/rSeparation) {
    int separation = (int)random(10, 20);
    color c = color(random(360), 80, 100);
    float startAngle = random(360);
    for (float angle = startAngle; angle < startAngle+360; angle += 360/separation) {
      float theta = radians(angle);
      float x = cos(theta) * r;
      float y = sin(theta) * r;
      PVector pos = new PVector(x + mouseX, y + mouseY);
      PVector center = new PVector(mouseX, mouseY);
      Mover m = new Mover(pos, center, c, rMax/5/2);
      movers.add(m);
    }
  }
}

class Mover {
  PVector current;
  PVector pos;
  PVector vel;
  PVector acc;
  PVector center;
  color c;
  float d;
  float g = 0.001;
  boolean isBurn = false;
  Mover(PVector _pos, PVector _center, color _c, float _d) {
    pos = _pos;
    current = new PVector(pos.x, height);
    center = _center;
    c = _c;
    d = _d;
    float theta = atan2(center.y-pos.y, center.x-pos.x);
    float dist = PVector.dist(pos, center);
    float len = map(dist, 0, 200, 0, 10);
    vel = new PVector(cos(theta+PI)*len, sin(theta+PI)*len);
    acc = new PVector(0, 0);
  }

  void update() {
    if (isBurn) {
      PVector gravity = new PVector(0, g);
      acc.add(gravity);
      vel.add(acc);
      vel.mult(0.99);
      pos.add(vel);
    } else {
      current.add(new PVector(0, -2));
      if (PVector.dist(new PVector(center.x, current.y), center) < 2) {
        isBurn = true;
      }
    }
  }

  void draw() {
    if (isBurn) {
      fill(c);
      noStroke();
      ellipse(pos.x, pos.y, d, d);
    } else {
      fill(0, 0, 100);
      noStroke();
      ellipse(center.x, current.y, d, d);
    }
  }
}