Chapter 15

ランダムを並べる

miku
miku
2021.11.21に更新

ランダム要素が入ったものを作った場合、ページを開くたびに新しい作品ができあがる。ただし、ランダムの引きによっては気に入らないものができる可能性があるだろう。その場合の対処方法として、例えばリロードを繰り返して気にいったものを幾つか拾い上げる、という方法が考えられるが、この章ではそれとは別の方法として、ランダムが使用されている作品を並べてみる、という方法について学ぶ。

基本

circle(x, y, random(30));

たとえば円の直径をランダムにする場合このように書くことができる。ただし、可能性は低いが直径が0になることがあるだろうし、他に色をランダムにした場合で、たまたま背景色と被って描画しても何も見えなくなる、なんてこともありえない話ではない。

function setup() {
  createCanvas(windowWidth, windowHeight);

  const n = 10;
  for (let y = 0; y < n; y++) {
    for (let x = 0; x < n; x++) {
      const tx = (width / (n - 1)) * x;
      const ty = (height / (n - 1)) * y;

      circle(tx, ty, random(30));
    }
  }
}

このような場合は結果を並べて描画するという方法がある。サイズが小さくて見えないというようなハズレのランダム値を引いた場合でも、他の円と比較されて、逆に映えて見えることもある。ここではこのような形で配置することを「ランダムを並べる」と表現したい。

ランダムを並べる

function setup() {
  createCanvas(windowWidth, windowHeight);

  const n = 10;
  for (let y = 0; y < n; y++) {
    for (let x = 0; x < n; x++) {
      drawCircle((width / n) * x, (height / n) * y, width / n, height / n);
    }
  }
}

function drawCircle(x, y, w, h) {
  translate(x, y);

  const d = w / 4;
  fill(random(255));
  circle(w / 2 - d / 4, h / 2, d);
  circle(w / 2 + d / 4, h / 2, d);

  resetMatrix();
}

色がランダムな2つの円を重ねて並べた作例。

ランダムを並べる その2

function setup() {
  createCanvas(windowWidth, windowHeight);

  const n = 10;
  for (let y = 0; y < n; y++) {
    for (let x = 0; x < n; x++) {
      drawCircle((width / n) * x, (height / n) * y, width / n, height / n);
    }
  }
}

function drawCircle(x, y, w, h) {
  translate(x, y);

  const d = w / 4;
  fill(random(255), random(255), random(255));
  circle(w / 2 - d / 4, h / 2, d);
  fill(random(255), random(255), random(255));
  circle(w / 2 + d / 4, h / 2, d);

  resetMatrix();
}

先程と同じ形だが、色のランダムの範囲がRGBになった作例。

このようにランダムを並べると複数のパターンをまとめて見ることができるので、このまま作品にしたり、制作中のデバッグに利用することができる。

ランダムのシード

function setup() {
  createCanvas(windowWidth, windowHeight);

  randomSeed(100);
  console.log(random()); // 0.2748232155572623
  console.log(random()); // 0.3489434248767793
  console.log(random()); // 0.29036099393852055

  randomSeed(100);
  console.log(random()); // 0.2748232155572623
  console.log(random()); // 0.3489434248767793
  console.log(random()); // 0.29036099393852055
}

randomSeed() にシードという番号を指定すると、以降に呼び出す random() はそのシードに応じた固定の値を返すようになる。

const d = 20;

function setup() {
  createCanvas(windowWidth, windowHeight);
  textAlign(CENTER, CENTER);

  const n = 3;
  for (let y = 0; y < n; y++) {
    for (let x = 0; x < n; x++) {
      drawCircle((width / n) * x, (height / n) * y, width / n, height / n);
    }
  }
}

function drawCircle(x, y, w, h) {
  translate(x + w / 2, y + h / 2);

  const seed = floor(random(1000000000));
  randomSeed(seed);

  fill(random(255), random(255), random(255));
  circle(-d / 4, 0, 20);
  fill(random(255), random(255), random(255));
  circle(d / 4, 0, 20);

  fill(240);
  text(seed, 0, 30);

  resetMatrix();
}

これを利用して、シードとセットで描画することで気に入った作品を後から再現することもできる。

テキストの描画機能に関しては下記の通り。

// デフォルトではテキストの原点は左上になるが、それを中央に変える
textAlign(CENTER, CENTER);
fill(col); // テキストの色は fill() に依存する
text(s, x, y); // 位置(x, y)に文字列sの内容を描画する

今回は画面にシード番号を描画したが、console.log() でコンソールに出力したり、document.title でタブに表示する、などのような方法もある。