Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第7章 周期と偶然のあいだ

機械的に同じ速さで動く円は、動きの仕組みを知るには分かりやすい例です。しかし呼吸、波、風のような動きは、行って戻る変化や、完全には予測できない揺れを含みます。周期と乱数は、その 2 種類の変化を作ります。

規則正しいsinの波と、滑らかに揺らぐnoiseの線を並べた図
図解 7-A `sin` は繰り返す波、`noise` は滑らかで不規則な変化を作る。

7.1 sin が往復運動を返す

sin(サイン)は、三角関数と呼ばれる計算の一つです。この本では、公式も計算方法も覚えません。数字を少しずつ増やして sin へ渡すと、答えが -1 から 1 の間をなめらかに行き来することだけを、画面の動きに使います。-1 は「マイナス 1」と読み、0 より小さい数です。

def setup
  createCanvas(500, 240)
end

def draw
  background(245)

  wave = sin(frameCount * 0.04)
  x = width / 2 + wave * 180

  fill(235, 90, 120)
  ellipse(x, height / 2, 60, 60)
end

frameCount(フレーム・カウント)は、draw が何回呼ばれたかを表す値です。1、2、3 と増えていく番号へ 0.04 を掛け、sin へ渡します。戻ってくる wave は -1 から 1 の間なので、180 を掛けると -180 から 180 の範囲になります。

この計算を自分で解く必要はありません。まず 0.040.02 へ変えて実行してください。動きが遅くなれば、数字と速さの関係を確認できています。次に元へ戻し、18080 へ変えると、左右へ動く幅が小さくなります。

0.04 を小さくするとゆっくり、大きくすると速く往復します。180 は移動幅です。速度と振れ幅を別の数字で調整できる点が重要です。

7.2 同じ周期を大きさへ使う

同じ wave を位置ではなく大きさへ使います。次の変更部分を、7.1の長いコードにある draw の中身と置き換えます。

wave = sin(frameCount * 0.04)
size = 100 + wave * 40
ellipse(width / 2, height / 2, size, size)

大きさは 60 から 140 の間を往復します。wave をそのまま大きさにすると負の値になる時間があります。中心となる 100 を足すことで、扱いやすい範囲へ移しています。

周期の式は、横移動、透明度、色、回転にも使えます。同じ波を複数の性質へ使うと、画面全体が同じ呼吸を持ちます。別の速さを使うと、少しずつずれる関係が生まれます。

7.3 random は毎回別の値を選ぶ

random(400) は、0 以上 400 未満の範囲から値を返します。draw のたびに位置を選ぶと、円が激しく飛びます。

def setup
  createCanvas(500, 300)
  background(20)
  noStroke
end

def draw
  x = random(width)
  y = random(height)
  size = random(4, 28)

  fill(255, 220, 120, 120)
  ellipse(x, y, size, size)
end

背景を setup に置いたため、点が消えずに積もります。実行するたび別の星空になります。

乱数は「自然らしさ」を自動で作る命令ではありません。位置も色も大きさもすべて乱数にすると、どこを見る画面なのか分かりにくくなることがあります。何を規則で揃え、どこだけ偶然に任せるかが制作上の選択です。

7.4 noise は隣り合う値がつながる

random は呼ぶたび大きく飛べます。noise は、近い入力へ近い値を返すため、連続した揺れを作りやすい機能です。

def setup
  createCanvas(500, 240)
end

def draw
  background(245)

  value = noise(frameCount * 0.01)
  x = value * width

  fill(60, 130, 220)
  ellipse(x, height / 2, 60, 60)
end

noise(ノイズ)の戻り値は通常 0 から 1 の範囲です。width(ウィズ、キャンバスの幅)を掛けると、キャンバスの左端から右端の範囲へ変換できます。

二つの変化を横へ並べる代わりに、上段と下段へ点として記録すると形を比べられます。次はそれだけで実行できる完成コードです。

def setup
  createCanvas(600, 300)
  background(245)
  noStroke

  120.times do |i|
    x = 30 + i * 4.5

    wave_y = 80 + sin(i * 0.18) * 35
    fill(235, 90, 120)
    ellipse(x, wave_y, 6, 6)

    noise_y = 220 + (noise(i * 0.08) - 0.5) * 90
    fill(50, 130, 230)
    ellipse(x, noise_y, 6, 6)
  end
end

上段の赤い点は、同じ波の形を繰り返します。下段の青い点は滑らかにつながっていますが、次の山や谷の大きさは一定ではありません。

薄い灰色の600×300のキャンバスで、上段に規則正しく繰り返す赤い波、下段になめらかで不規則な青い波が小さな点で描かれている実行結果
図 7-2 上段のsinは同じ周期を繰り返し、下段のnoiseは滑らかに揺らぐ。

7.5 偶然を保存する

乱数を使った作品で気に入った結果が出たら、その画面を保存する方法があります。再現できることも重要なら、randomSeed で乱数の並びを固定できます。

def setup
  createCanvas(500, 300)
  randomSeed(42)
  background(20)

  100.times do
    fill(255, 220, 120, 140)
    ellipse(random(width), random(height), random(4, 24), random(4, 24))
  end
end

同じシード値 42 なら、同じ乱数列を得られます。偶然に見える構図を選び、あとから同じ版を作れるようになります。

黒に近い500×300のキャンバス全体へ、大小の黄色い点が星空のように散らばっている実行結果
図 7-1 シードを固定して再現できる100個の点。

第2部では、値が時間で変わる仕組みを見ました。第3部では、変化のきっかけをマウスとキーボードから受け取ります。

7.6 波と偶然を同じ海へ置く

sinで規則的に上下する線を作り、noiseで少しだけ位置を揺らすと、完全な規則でも完全な乱数でもない水面を作れます。さらにrandomで小さな光を散らすと、波、風、反射という別々の役割を同じ画面へ置けます。

ここでは完成コードを一つに決めません。星空のコードを青い背景へ変えて水面にする、往復する円を船に見立てて三角形を足す、noiseの動きを雲へ使う、のどれかから始めます。同じ数の変化が、何に見立てるかで別作品になることを試す節です。

7.7 模様をもっと探すなら

第6章の行数と列数、第7章のsinnoiserandomを組み合わせると、同じコードから規則的な模様と崩れた模様を作り分けられます。まず一つだけ選びます。

  • 行と列の数を増やし、遠くから見た印象を比べる
  • sinを位置や大きさへ使い、並びを波打たせる
  • noiseを色へ使い、少しずつ変わる帯を作る
  • 第6章のフラクタルで、円を四角や枝へ変える

さらに探したくなったら、「セル・オートマトン」「フラクタル」「ジェネラティブアート」「Genuary」という言葉を、画像や作品例から調べられます。見つけた作品を全部まねるのではなく、気になった規則を一つだけ今のスケッチへ持ち帰ります。

この章の小さな区切り

  • randomsinnoiseのどれか一つを画面で確認した
  • 数字を一つ変え、変化の速さか散らばり方を比べた
  • 余裕があれば、星空、水面、雲のどれかに見立てた

三つを全部使わなくても、一つの変化を観察できれば保存して次章へ進めます。

参考資料