はじめに
この記事はRuby Advent Calendar 201715日目の記事です。
<< DXRubyのススメ](https://qiita.com/S_H_/items/85111f9ef9d8d513d010) || [ブロック引数の使いどころになる時のパターン >>
遅くなってすみません💦
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
フラクタル
せっかくなんでよくある円の入れ子になったフラクタルも書きます。
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
パーリンノイズ
パーリンノイズを生成する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
まとめ
こんな感じでRubyでもクリエィティブコーディングしてみました。
今回は静止画 + 円縛りになっちゃいました。
これはこれでスケッチ感覚で楽しいですが、
インタラクションのあるものとかもやってみたいです。