第13章 配列が一つを群れに変える
円が一つなら、@x と @y で位置を覚えられます。100 個になると、@x1 から @x100 を作る方法は変更しにくくなります。配列は、同じ役割を持つ複数の値を順序付きでまとめます。
13.1 位置を一つの配列へ集める
def setup
createCanvas(500, 300)
@x_positions = [80, 160, 260, 390]
end
def draw
background(245)
fill(235, 90, 120)
@x_positions.each do |x|
ellipse(x, height / 2, 50, 50)
end
end
each は配列の要素を一つずつブロックへ渡します。円を増やすには配列へ値を足します。描画コードを増やす必要はありません。
13.2 x と y を組にするハッシュ
各要素が位置と速度を持つなら、値の意味を名前で表せるハッシュを使えます。
def setup
createCanvas(500, 300)
@dots = [
{ :x => 80, :y => 90, :speed => 1.2 },
{ :x => 160, :y => 170, :speed => 2.0 },
{ :x => 300, :y => 130, :speed => 0.8 }
]
end
各ハッシュには :x、:y、:speed というキーがあります。=>は、左側のキーと右側の値を結び付ける記号です。rbCanvas/p5 0.5.1で確実に読めるこの形を使います。更新と描画を同じ反復で行います。次の draw は変更部分で、直前の setup の end より後ろへ足します。
def draw
background(25, 30, 48)
noStroke
@dots.each do |dot|
dot[:x] += dot[:speed]
dot[:x] = -20 if dot[:x] > width + 20
fill(255, 210, 100, 180)
ellipse(dot[:x], dot[:y], 24, 24)
end
end
3 つの点は同じ更新規則を持ちますが、初期位置と速度が違います。
13.3 push で実行中に増やす
クリックした場所へ点を追加します。次のイベントメソッドは変更部分で、draw の end より後ろへ足します。
def mousePressed
@dots.push({ :x => mouseX, :y => mouseY, :speed => random(0.5, 2.5) })
end
push は配列の末尾へ要素を加えます。クリックのたび、現在位置と乱数の速度を持つ新しい点が生まれます。
rbCanvas/p5 0.5.1では、push(の直後で改行すると、内容が正しくてもunexpected token tSEMIという構文エラーになる場合があります。この例では、pushへ渡すハッシュを同じ行に書いて避けています。
要素が増え続けると、描画処理も増え続けます。作品の意図が「記録を蓄積する」なら増え続けてもよい場合があります。長く遊ぶ作品なら、上限や削除が必要です。
13.4 select で残すものを選ぶ
画面の右端を越えた点を取り除きます。13.2では、右端を越えた点を左端へ戻す次の行があります。次のコードが、まず削除する変更部分です。
dot[:x] = -20 if dot[:x] > width + 20
折り返しを残したままでは、右端を越えた点がすぐ-20へ戻り、取り除く対象がなくなります。削除したあと、次の変更部分をdrawにある@dots.eachの反復が終わった直後、draw最後のendより前へ足します。
@dots = @dots.select do |dot|
dot[:x] <= width + 20
end
select は、ブロックの条件が成り立つ要素だけを集めた新しい配列を返します。消す対象を直接探す代わりに、「残す条件」を書いています。
描画中の配列から同時に要素を削除すると、反復の順番が分かりにくくなることがあります。更新が終わったあとで select し直すと、処理の段階が分かれます。
確認するときは、13.2の三つの点をそのまま動かします。点が右端から完全に出ると配列から取り除かれ、左端からは戻りません。クリックで追加した点も同じ条件で取り除かれます。
13.5 色の候補から一つ選ぶ
配列には、位置だけでなく、作品で使う色の組み合わせも入れられます。
def setup
createCanvas(480, 320)
background(245)
noStroke
palette = [
[190, 45, 70],
[240, 150, 60],
[45, 105, 145],
[90, 55, 120]
]
6.times do |row|
9.times do |column|
color = palette.sample
fill(color[0], color[1], color[2])
ellipse(30 + column * 53, 28 + row * 53, 38, 38)
end
end
end
palette(パレット)は、絵に使う色をまとめた配列です。その中の各色も、赤、緑、青の3要素を持つ配列です。sample(サンプル)は、配列から要素を一つ選んで返すRubyのメソッドです。color[0]は最初の赤、color[1]は次の緑、color[2]は最後の青を取り出します。角括弧の番号は0から始まります。
すべてを自由な乱数色にせず、先に選んだ4色からだけ使うことで、偶然が起きても作品全体の関係を保てます。色を一つ入れ替える、特定の行だけ候補を減らす、円を別の形へ変える、の順で敷き詰め模様を育てられます。
13.6 配列のハッシュからクラスへ移る境目
ハッシュは、少数の性質を持つ要素に向いています。点が「更新する」「描く」「端に出たか調べる」という複数の処理を持ち始めると、毎回ハッシュを渡すコードが散らばります。
その時点でクラスが役立ちます。クラスは配列より上等な方法ではありません。データと、そのデータに関わる処理を一緒に置きたいときの選択です。次章では、今の点をクラスへ移し、違いを比べます。
13.7 小作品「記憶の一色」
13.5のpaletteにある四色から一色だけを、自分が覚えている場所や物の色へ置き換えます。正確なRGBを探す必要はありません。「夕方の帰り道」「古いかばん」のように、その色へ短い名前を付け、数字を少しずつ変えます。
実行するたび並びは変わりますが、選んだ色の関係は残ります。気に入った偶然が出たら保存します。配列は、使える色を制限するためだけでなく、自分が選んだ材料をひとまとめにする道具です。
この章の小さな区切り
- 配列から複数の点または色を取り出して描けた
- クリックで要素が一つ増えることを確認できた
- パレットの一色を変え、前後の印象を一言で比べた
クリック追加まで進まなくても、13.1の四つの円が表示できれば次章へ進めます。今日残したい画面を一つ保存します。