魚の群れ(スイミー)

子供のころに「スイミー」を読んだ人も多いと思います。そんな風景をイメージしてスケッチを作ってみました。

魚の群れを動かしていますが、一見すると複雑そうにみえるかもしれませんが、

  1. ある魚を配置して適藤な速度(1フレームに移動する距離)を設定
  2. その周囲に複数の魚を配置して、同じ速度を設定

というこれだけの処理です。

魚は画像をつかってもよいでしょう。今回は〇と△を組み合わせて描画してみました。
座標の計算が面倒だったのでtranslate関数を使いました。また、左右の向きを変えるためにscale関数を使っています。

java

class Fish {
  PVector pos, speed;
  color col;
  int count = (int)random(100);

  Fish(float x, float y, float sx, float sy, color c) {
    pos = new PVector(x, y);
    speed = new PVector(sx, sy);
    col = c;
  }

  void paint() {
    pos.add(speed);
    if (pos.x < 0 || pos.x > 600) {
      speed.x *= -1;
    }
    if (pos.y < 0 || pos.y > 400) {
      speed.y *= -1;
    }

    pushMatrix();
    translate(pos.x, pos.y);
    fill(col);
    ellipse(0, 0, 50, 20);
    if (speed.x > 0) {
      scale(1, 1);
    }else {
      scale(-1, 1);
    }
    if ((count++ / 4) % 2 == 0) {
      triangle(-35, -10, -35, 10, -20, 0);
    }
    fill(0);
    ellipse(10, 0, 5, 5);
    popMatrix();
  }
}

ArrayList<Fish> fish = new ArrayList<Fish>();
PImage sea;
void setup() {
  size(600, 400);
  noStroke();
  sea = loadImage("sea.jpg");
  createFishSchool(width/4, height/4);
  createFishSchool(width*3/4, height*3/4);
}

void draw() {
  background(255);
  image(sea, 0, 0);
  for (Fish f : fish) {
    f.paint();
  }
}

void createFishSchool(float x, float y){
  float sx = random(-5, 5), sy = random(-2, 2);
  for (int i = 0; i < 10; i++) {
    float nx = x + random(-80, 80);
    float ny = y + random(-80, 80);
    fish.add(new Fish(nx, ny, sx, sy, #ff5555));
  }
  fish.add(new Fish(x, y, sx, sy, #000000));
}