見出し画像

虹のアーチの作り方-Rubyでクリエイティブコーデイング-

Rails Girls Tokyo 16th のコーチLTの中で、イベントロゴをコードで描く&コードの中にそのイベントの班名の由来になったRubyのクラスを盛り込むという余興のようなことをやりました。

完成したコードを見るとなんだか難しそうに思えるかもしれませんが、最初はべた書きで試行錯誤から始まるんですよ。どうやって手を加えていくかみてもらったら、Rubyでのクリエイティブコーディングが少しでも伝わるといいなとメイキングを作ってみることにしました。

使っている技術

(技術的な理解は後回しでも大丈夫です)

  • p5.js / ruby.wasm/  p5.rbを使っています

    • p5.jsは、Processingというビジュアルアートを作成するためのプログラム言語・環境をWebブラウザで実行できるよう、JavaScriptライブラリにしたものです。

    • ruby.wasmは、ブラウザ上でのRubyの実行を可能にしています。

    • p5.rbは、ruby.wasmのJS::Object経由でp5.js のメソッドやプロパティをブリッジしてくれます。

つまり、これらを使ってRubyの構文の中からp5.jsの機能にアクセスできるようにしています。(作ってくださった皆様に感謝)

使うもの

Webエディタ https://p5rb.ongaeshi.me/editor

p5.rbエディタ

ローカルでも作れますが、webエディタがあるのでそれを使うと簡単に今すぐ作れます。
ここから先は実際にこのWebエディタで書きながら進んでみてください(表示された画像は右クリックで保存できます)。

エディタにデフォルトで書かれている部分(サンプル)は削除して、実行するときは青いRunボタンを押してください。

コードの中に見慣れないメソッドが出てきたら大抵p5.jsです。コメントも書いてますが、詳しく知りたい場合はリファレンスを参照してみてください。

作り方

0. 描きたいものの構成要素を考える

Rails Girls Tokyo 16Th ロゴ
  • まずは虹の部分を描こう(時間が余ったらRubyも ※余りませんでした)

  • 虹部分は大きな半円に小さい半円を重ねていったらできそう

    • ピンク→緑→紫→ピンク→緑→白 の順に重ねたらできそう

1. 円を描いてみる

枠線が黒の白い半円を書いてみます。

1
def setup
  createCanvas(500, 500) # 描画領域の大きさ
  angleMode(DEGREES)     # 角度を度数で扱うための指定
  background(255)        # 背景を白(255)に指定
  noLoop                 # 繰り返さない(これを書かないとsetup1回実行後drawを繰り返します
end

def draw
  stroke(0)              # 図形の線の色を黒(0)に指定
  fill(255)              # 図形の塗りつぶし色を白(255)に指定
  arc(width/2, height/2, 100, 100, 180, 360) # width は描画領域の幅、height は縦
end

arcは円弧を描くメソッドです。
arc(x座標, y座標, 幅, 縦, 開始角度, 終了角度) を指定します。
今回の場合だと、幅の半分、縦の半分つまり画面中心に、縦横100の半円を描いています(この100はなんとなくです。基準とする長さとして設けました)。

※ 開始90度、終了180度だと扇形になります。自由に角度や長さを変えてどうなるかためしてみてください。

2. 円を重ねる

虹にしたいので、先ほどつくった半円よりも幅と高さの大きな円arcメソッドで作り、大きい円の上に小さい円を重ねていきます。5本のアーチを作りたいので円を6個重ねます。
※ 線が表示されない場合は小さい順に並べてないか確認してください。

2
def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  stroke(0)              
  fill(255)             
  arc(width/2, height/2, 180, 180, 180, 360)  # 一番大きい半円
  arc(width/2, height/2, 155, 155, 180, 360) 
  arc(width/2, height/2, 135, 135, 180, 360)
  arc(width/2, height/2, 120, 120, 180, 360)
  arc(width/2, height/2, 110, 110, 180, 360)
  arc(width/2, height/2, 100, 100, 180, 360)  # 1で描いた半円
end

虹の幅は外に行くほど幅が太く、内側ほど幅が細いので描画しながらちょうどいい幅を探ります。

3. 色をつける

虹に色をつけます。ここではカラーコードで色を指定します。 fillは色を指定できます。指定したらその後に書かれた図形は指定した色で塗り潰されます。

3
def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  stroke(0)              
  fill('#eeb3b2')  # ピンク
  arc(width/2, height/2, 180, 180, 180, 360)

  fill('#d5e8c5')  # 緑
  arc(width/2, height/2, 155, 155, 180, 360)

  fill('#bca7c7')  # 紫
  arc(width/2, height/2, 135, 135, 180, 360)

  fill('#eeb3b2')  # ピンク
  arc(width/2, height/2, 120, 120, 180, 360)

  fill('#d5e8c5')  # 緑
  arc(width/2, height/2, 110, 110, 180, 360)

  fill('#ffffff')  # 白
  arc(width/2, height/2, 100, 100, 180, 360)
end

なんということでしょう。もうこれで虹は完成です!
ここで終わってもいいのですが、ちょっと同じようなコードが繰り返されて冗長なので整理してみます。

4. メソッドに切り出してみる

各半円は色と大きさが違うだけなので半円を描くメソッドdraw_bridgeを作ります。

def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  stroke(0)              
  draw_bridge('#eeb3b2', 180)
  draw_bridge('#d5e8c5', 155)
  draw_bridge('#bca7c7', 135)
  draw_bridge('#eeb3b2', 120)
  draw_bridge('#d5e8c5', 110)
  draw_bridge('#ffffff', 100)
end

def draw_bridge(color, size)
  fill(color)
  arc(width/2, height/2, size, size, 180, 360)
end

上記のように修正して実行してみてください。3と同じものが表示されます。
通常のクリエイティブコーディングであればここで完了でいいのではないでしょうか。
※ 終わりをどこにするか決めるのも自分自身です。自由です。

以降は"今回の班名の由来になったクラスを使う"という遊びのための改変を加えます。若干力技のコードになっていくので興味のある方のみどうぞ。

5. 繰り返し処理で書けないか

今の状態でIntegerとStringは使えています。
虹の色がピンク→緑→紫の順に繰り返されてる点に注目します。これを配列にするとArrayクラスがクリアできそうです。
配列で順に色を指定するということは、繰り返し処理になっていると順に色を設定できてよさそうです。

  draw_bridge('#eeb3b2', 180)
  draw_bridge('#d5e8c5', 155)
  draw_bridge('#bca7c7', 135)
  draw_bridge('#eeb3b2', 120)
  draw_bridge('#d5e8c5', 110)
  draw_bridge('#ffffff', 100)

↑上記の部分が↓下記のように書けないか法則を考えてみます。

colors = ['#eeb3b2', '#d5e8c5', '#bca7c7']
radius = 一番外側の円のサイズ
5.times do |i|
  color = colors[i % colors.length]  # iを配列の数で割った余り番目の配列を取るようにすると ピンク→緑→紫→ピンク→緑…と取れる
  draw_bridge(color, radius)
  radius = radius - xxx # だんだん小さくしていく
end

幅はそれぞれ差が5の倍数です。それを足がかりに足したり引いたりして1つの式で表せるように考えます。最大を210、最小を110に変更したところ思ったような数列ができる繰り返しが作れました。

def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  stroke(0) 
  colors = ['#eeb3b2', '#d5e8c5', '#bca7c7']   
  radius = 210
  5.times do |i|
    color = colors[i % colors.length]
    draw_bridge(color, radius)
    radius = radius - (- 5*i + 30) # なんとか捻り出した法則
  end
  draw_bridge('#ffffff', 110)
end

def draw_bridge(color, size)
  fill(color)
  arc(width/2, height/2, size, size, 180, 360)
end

これを実行してみると先ほどよりほんの少しだけ大きな虹になります

6

Procに挑む

さて、これで3つのクラスが組み込めました。残りはHashとProc。Hashはどうとでもなる気がするので、先にProcをどうにかできないか考えてみます。

何にも浮かばなくてリファレンスを読み直してみたりしました。

苦肉の策としてメソッドに切り出したbridge部分をProcオブジェクトにして遅延評価ならなんとか…

def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  stroke(0) 
  bridge = Proc.new do |color, size|
    fill(color)
    arc(width/2, height/2, size, size, 180, 360)
  end

  colors = ['#eeb3b2', '#d5e8c5', '#bca7c7']   
  radius = 210
  5.times do |i|
    color = colors[i % colors.length]
    bridge.call(color, radius)
    radius = radius - (- 5*i + 30)
  end
  bridge.call('#ffffff', 110)
end

これも実行してもらうと6と同じものが表示されます。

7. Hashを組み込む

Procが組み込めたのでもう安心です。あとはHashだけ。引数部分にHashを使ってみることにしました。

options = { color: color, size: radius }
bridge.call(options)

こういいった引数の渡し方にするとなんとかHashも入ります。

def setup
  createCanvas(500, 500) 
  angleMode(DEGREES)     
  background(255)        
  noLoop                 
end

def draw
  bridge = Proc.new do |options|
    stroke(0)
    fill(options[:color])
    arc(width/2, height/2, options[:size], options[:size], 180, 360)
  end

  colors = ['#eeb3b2', '#d5e8c5', '#bca7c7']
  radius = 210

  5.times do |i|
    color = colors[i % colors.length]
    options = { color: color, size: radius }
    bridge.call(options)
    radius = radius - (- 5*i + 30)
  end
  
  options = { color: '#ffffff', size: 110 }
  bridge.call(options) 
end

これでArray, Hash, Integer, String, Proc全部組み込めました!完成!!

感謝

今回紹介した虹は、Rails Girls Tokyo 16thのオーガナイザーのお二人えんじぇるさんとまいむさんがイベントの開催を決め、「プログラミングへの入り口」をテーマにしようとコンセプトを決め、moegiさんがそれを「虹のアーチ」という形で表現し、班名がRubyのクラスになって…という素敵な企画に触発されてできたファンアートです。出会わなければ作れなかったものです。ありがとうございます。

まいむさんの開催への思い

moegiさんのロゴデザインの背景

まとめ

今回紹介したコードはRubyのお作法的に適切かというとそうでもないかもしれません。でも、こんな風にコードで描くだけでなく、書き方に何かコンセプトを持たせるのも1つの楽しみ方であり、表現方法です。楽しみ方に正解も間違いもないので、自分なりのコードの楽しみ方を探してみてください。
そして、この記事がクリエイティブコーディングの虹のアーチをくぐるきっかけになれば幸いです。

この記事が気に入ったらサポートをしてみませんか?