波紋

「クラスを使ってオブジェクトを作成し、ArrayListで管理する」そんなサンプルを充実させようと作ってみました。
雨が降った水面のようなイメージです。
waterripplebasic

class Ripple {
  float radius;
  PVector pos;

  Ripple() {
    pos = new PVector(random(600), random(400));
  }

  void paint() {
    noFill();
    radius += 0.5;
    stroke(255, 255 - radius*10);
    ellipse(pos.x, pos.y, radius*5, radius*5/2);
  }

  boolean done() {
    return radius > 25;
  }
}


ArrayList<Ripple> ripples = new ArrayList<Ripple>();
PImage water;

void setup() {
  size(600, 400);
  strokeWeight(2);
  ripples.add(new Ripple());
  water = loadImage("water.jpg");
}

void draw() {
  background(100, 200, 255);
  image(water, 0, 0);
  for (Ripple w : ripples) {
    w.paint();
  }

  if (frameCount % 10 == 0) {
    ripples.add(new Ripple());
  }

  for (int i = ripples.size() - 1; i >= 0; i--) {
    Ripple w = ripples.get(i);
    if (w.done()) {
      ripples.remove(i);
    }
  }
}

1つの波紋は

  • pos 場所
  • radius 半径

といった2つの情報を保持しています。paintメソッドで描画する度にradiusを増やして円を大きくしています。
radiusが25より大きくなるとInvlalidメソッドがtrueを返すようにしています。

このRippleクラスを以下のように書き換えると波紋が同心円状に広がり、もう少しリアルな感じになります。

class Ripple {
  int count;
  int alpha = 255;
  PVector pos;
  Ripple() {
    pos = new PVector(random(600), random(400));
  }

  void paint() {
    noFill();
    if (frameCount % 5 == 0) {
      count++;
      alpha*=0.9;
    }
    int offset = count % 10;
    for (int i = 0; i < 50; i++) {
      if ((i - offset) % 10 == 0) {
        stroke(255, lerp(alpha, 0, i/50.0));
        ellipse(pos.x, pos.y, i*5, i*5/2);
      }
    }
  }

  boolean done() {
    return count > 25;
  }
}

waterripple