第6章 反復は同じ形を別の景色に変える
円を 10 個描くために ellipse を 10 行書くこともできます。位置が少しずつ変わるなら、その違いを規則として書けます。反復は手間を減らすだけでなく、数、間隔、規則の崩し方を作品の材料にします。
6.1 5 回描く times
まず、同じ場所へ円を 5 回描きます。
def setup
createCanvas(500, 220)
background(245)
5.times do
ellipse(100, 110, 60, 60)
end
end
見える円は一つです。同じ場所へ完全に重ねたからです。反復回数は増えましたが、位置が変わっていません。
times は、何回目の反復かをブロック変数へ渡せます。直前の長いコードにある 5.times do から対応する end までを、次の変更部分と置き換えます。
5.times do |i|
x = 70 + i * 90
ellipse(x, 110, 60, 60)
end
初めて見る記号がいくつかあります。左から順に読みます。
5.timesは、その後の処理を 5 回繰り返しますdoは、繰り返す処理の始まりです|i|は、今が何回目かを受け取るための書き方です。縦線 2 本の間に変数名を書きます- 最後の
endは、繰り返す範囲の終わりです
i は 0、1、2、3、4 と変わります。プログラムでは番号を 0 から数える場面が多くあります。5 回繰り返しても最後が 4 なのは、最初が 0 だからです。
最初の x は 70 + 0 * 90 なので 70、次は 70 + 1 * 90 なので 160 です。* は掛け算を表します。反復回数を 8 へ変えるだけで、同じ間隔の円が増えます。
6.2 行と列を重ねる
横方向の反復を、縦方向の反復の内側へ置きます。
def setup
createCanvas(480, 360)
background(28, 32, 50)
noStroke
4.times do |row|
6.times do |column|
x = 50 + column * 75
y = 55 + row * 85
fill(240, 180, 70)
ellipse(x, y, 44, 44)
end
end
end
外側の row が 1 回進む間に、内側の column が 0 から 5 まで進みます。4 行 × 6 列なので、円は 24 個です。
反復を重ねるとコードは短くなりますが、最初は動きを追いにくくなります。行数を 2、列数を 3 へ減らすと、どの順で描かれるか想像しやすくなります。
6.3 規則の中の一つだけを変える
すべて同じだと、画面は安定します。直前の長いコードの二重反復部分を、次の変更部分と置き換え、条件分岐で一つだけ色を変えます。
4.times do |row|
6.times do |column|
x = 50 + column * 75
y = 55 + row * 85
if row == 1 && column == 3
fill(235, 80, 120)
else
fill(240, 180, 70)
end
ellipse(x, y, 44, 44)
end
end
== は値が等しいかを比べ、&& は「かつ」です。2 行目であり、かつ 4 列目の円だけが別の色になります。ブロック変数は 0 から始まるため、row == 1 が 2 行目です。
6.4 同じ間隔からずれを作る
列ごとに y 座標を少し変えると、格子が波打って見えます。二重反復の中にある y = 55 + row * 85 の1行だけを、次の1行と置き換えます。
y = 55 + row * 85 + (column % 2) * 20
% は余りを求める演算子です。column % 2 は、偶数列で 0、奇数列で 1 になります。奇数列だけ 20 下がるため、互い違いの配置になります。
さらに ellipse の大きさへ row や column を使えば、左から右、上から下への変化を作れます。二重反復の中にある ellipse(x, y, 44, 44) の1行を、次の変更部分と置き換えます。
size = 24 + column * 6
ellipse(x, y, size, size)
反復は同じものを量産する命令ではなく、番号を位置、色、大きさへ変換する仕組みです。次章では、番号ではなく角度や乱数から変化を作ります。
6.5 同じ反復から三つの作品を選ぶ
今の行と列のコードは、形を変えるだけで別の風景になります。
ellipseのまま、緑の大きさを行ごとに変えると植物園rectへ変え、黄色を一部だけ灯すと夜の窓triangleへ変え、列ごとに傾きを想像して配置すると旗の列
全部を作る必要はありません。一つ選び、まず図形と背景色だけを変えます。そのあと、一個だけ異なる要素を「間違い」ではなく「物語の主役」として置きます。なぜその一個だけ違うのかは、言葉で説明できなくてもかまいません。
6.6 発展:形の中へ同じ形を描く
大きな円の中へ半分の円を描き、その円の中へさらに半分の円を描くと、同じ規則が小さくなりながら続く模様ができます。このように、全体と似た形が一部分にも現れる構造をフラクタルと呼びます。
def setup
createCanvas(500, 320)
background(20, 25, 45)
noStroke
draw_circles(width / 2, height / 2, 240)
end
def draw_circles(x, y, size)
return if size < 12
fill(120 + size / 3, 100, 210, 150)
ellipse(x, y, size, size)
next_size = size / 2
draw_circles(x - size / 4, y, next_size)
draw_circles(x + size / 4, y, next_size)
end
draw_circlesの中から、もう一度draw_circlesを呼んでいます。自分自身を呼び出す方法を再帰と呼びます。return if size < 12は、円が12より小さくなったら、その呼び出しをそこで終える条件です。この条件がないと、いつまでも小さくしようとして処理を終えられません。
ここは発展なので、仕組みを一度で理解する必要はありません。まずそのまま実行し、240を180へ、12を24へ変えてください。その次に、円を四角形へ変える、左右ではなく上下へ分ける、色を大きさから決める、といった改造へ進めます。
この章の小さな区切り
timesで同じ形を繰り返せた- 行か列の数を一つ変えた
- 余裕があれば、フラクタルの大きさか分かれ方を変えた
格子模様を表示できれば、再帰を理解しきらなくても保存して次章へ進めます。