Help us understand the problem. What is going on with this article?

Rubyでクリエィティブコーディング

More than 1 year has passed since last update.

はじめに

この記事はRuby Advent Calendar 201715日目の記事です。

<< DXRubyのススメ || ブロック引数の使いどころになる時のパターン >>

遅くなってすみません💦
GTKについても調べながら書いているので、
間違いなどあったらご指摘お願いします。

今回はRubyでGTKを使ったクリエィティブコーディングについて書きたいと思います。
GTKと言ってもOpenGLを使った描画など、
色々あるそうなので今回はCairo(Gtk::DrawingArea)を使ったものを紹介します。

まずruby-gnome2をインストールします。
インストール方法は以前こちらに書いたので参考にしてください。

使い方

まずシンプルに円を表示します。
context.scale 0.5, 0.5しているのは、
なぜか2倍で表示されてしまうからなんですけどなんでなんでしょう……

追記
@noanoa07 さんからのコメントで以下の報告をいただきました。
Retina Displayじゃない方はscaleはいらないみたいです。

2倍に表示されてしまう件は、HiDPi(高解像度)ディスプレイ(MacのRetina Displayなど)にCairoが対応してないからのようです。
なので、通常ディスプレイのMacだと普通に、Retina DisplayのMacだと2倍に表示されているのだと思います。
参考)
http://blog.livedoor.jp/noanoa07/archives/2154505.html

@ktou さんからのコメントで動的にscaleを変更するように編集しました。

@ktou さんからのコメントを頂いて、以下の点を変更しました。

  • HiDPIに対応したのでgtk3(3.3.0)を使用
  • scale 関連のコードを削除
  • Cairo::Context を生成せずに、 :draw のブロックに渡される Cairo::Context を使用
require 'gtk3'

width = 300
height = 300

window = Gtk::Window.new
window.set_size_request(width, height)

drawing_area = Gtk::DrawingArea.new
drawing_area.set_size_request(width, height)

drawing_area.signal_connect(:draw) do |_, context|
  # background color
  context.set_source_rgb(0.0, 0.0, 0.0)
  context.paint 1.0

  # fill color
  context.set_source_rgb(1.0, 1.0, 1.0)
  # arc(x, y, r, start, end)
  context.arc(width / 2, height / 2, 150, 0, 2 * Math::PI)
  context.fill
end

fixed = Gtk::Fixed.new
fixed.put(drawing_area, 0, 0)
window.add(fixed)

window.show_all
window.signal_connect(:destroy) { Gtk.main_quit }

Gtk.main

スクリーンショット 2017-12-15 3.25.09.png

フラクタル

せっかくなんでよくある円の入れ子になったフラクタルも書きます。

require 'gtk3'

width = 300
height = 300

window = Gtk::Window.new
window.set_size_request(width, height)

drawing_area = Gtk::DrawingArea.new
drawing_area.set_size_request(width, height)

def draw_circle(context, x, y, r, c = [1.0, 1.0, 1.0, 1.0])
  context.set_source_rgba(c)
  context.arc(x, y, r, 0, 2 * Math::PI)
  context.stroke
end

def draw_fractal_circle(context, x, y, r, c = [1.0, 1.0, 1.0, 1.0], n)
  return nil if n < 0
  draw_circle context, x, y, r, c
  next_r = r / 2
  x1 = x - next_r
  draw_fractal_circle context, x1, y, next_r, c, n - 1
  x2 = x + next_r
  draw_fractal_circle context, x2, y, next_r, c, n - 1
end

drawing_area.signal_connect(:draw) do |_, context|
  context.set_source_rgb(0.0, 0.0, 0.0)
  context.paint 1.0

  x = width / 2
  y = height / 2
  r = 150
  red = 0.1
  green = 0.7
  blue = 1.0
  alpha = 0.5
  draw_fractal_circle context, x, y, r, [red, green, blue, alpha], 5
end

fixed = Gtk::Fixed.new
fixed.put(drawing_area, 0, 0)
window.add(fixed)

window.show_all
window.signal_connect(:destroy) { Gtk.main_quit }

Gtk.main

スクリーンショット 2017-12-15 3.47.27.png

パーリンノイズ

パーリンノイズを生成するGemがあったのでこれを使えば、
ノイズを使った表現もできます。
perlin_noise

require 'gtk3'
require 'perlin_noise'

width = 300
height = 300

window = Gtk::Window.new
window.set_size_request(width, height)

drawing_area = Gtk::DrawingArea.new
drawing_area.set_size_request(width, height)

def draw_circle(context, x, y, r, c = [1.0, 1.0, 1.0, 1.0])
  context.set_source_rgba(c)
  context.arc(x, y, r, 0, 2 * Math::PI)
  context.fill
end

n2d = Perlin::Noise.new 2, interval: 5
contrast = Perlin::Curve.contrast(Perlin::Curve::CUBIC, 2)

drawing_area.signal_connect(:draw) do |_, context|
  context.set_source_rgb(0.0, 0.0, 0.0)
  context.paint 1.0
  0.step(width, width / 10) do |x|
    0.step(height, height / 10) do |y|
      n = n2d[x * 0.01, y * 0.01]
      n = contrast.call n
      r = (width / 10 / 2) * n
      red = 1.0
      green = 1.0
      blue = 1.0
      alpha = n
      draw_circle context, x, y, r, [red, green, blue, alpha]
    end
  end
end

fixed = Gtk::Fixed.new
fixed.put(drawing_area, 0, 0)
window.add(fixed)

window.show_all
window.signal_connect(:destroy) { Gtk.main_quit }

Gtk.main

スクリーンショット 2017-12-15 4.54.19.png

まとめ

こんな感じでRubyでもクリエィティブコーディングしてみました。
今回は静止画 + 円縛りになっちゃいました。
これはこれでスケッチ感覚で楽しいですが、
インタラクションのあるものとかもやってみたいです。

enkatsu
Processing, oF, Cinder, Python, Ruby, JS
https://enkatsu.org
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away