はいども@nobkzです。Creative CodingとClojureについて
はじめに
すいません。最近いろいろ個人的に体調やらいろいろありまして、advent Calendarの投稿を遅れてしまいました。すいません....
Creative Codingとは?
簡単にざっくり言えば、「コンピュータでアートやろう!」ってことなんですが、つまり、コンピュータグラフィックスやサウンド、インターフェースの設計などで、より芸術として昇華させるようなものです。
そして、それを支援するような、環境やフレームワークが沢山あり、代表的なのが、グラフィック系で言えば、
- Processing
- openframeworks
- cinder
であり、音系で言えば、
- Max/MSP/Jitter
- PureData
- SuperCollider
- Overtone
- impromptu
などがあります。そして、ハードウェアと組み合わせることがあって、たとえば、
- Aruduino
- Rasberry PI
- BeagleBone
などがありまぁ、大体はどれかを使ってやる感じだと思います。
なぜClojureなのか?
さて、クリエイティブコーディングとして、Clojureに可能性を最近感じています。
一年前にはhttp://qiita.com/nobkz/items/aea2c70a5fb03003f375
なんて記事を書きましたが、これはソフトウェアでの音楽的表現として、overtoneの紹介や、clojureの構文の拡張性が、より音楽的な記述の可能性を言っているわけです。そして、似たようなことがCreative Codingなどにも言えるのでは?と思います。
さらに、Light Table等http://lighttable.com/ なども寄りCreative Codingを促進させるようなものがあると思います。(これはClojureだけの話しでは無いですが。)
また、Clojureには最近OmなどFRPの技法があり、最近これをCreative Codingに応用できるのでは?と思っています。むしろ、Elmなどを見ている限り、こちらの方が、より文化的なクリエイティビティを支援するような技法があるんじゃないかと思っています。
最後のReplを利用したライブコーディングの可能性もあり、なかなか面白いことができると思います。
どうでしょうか?何か面白いと思いませんか?
ClojureでCreative Codingの実践
Creative Codingは基本的に前提として次の知識や技術が必要になると思います。
- 物理
- 数学
- もちろんプログラミング
- アート
物理や数学と良いましたが、最近流行の圏論とかじゃなくて、これはある意味手段として、物理や数学をアートの表現に応用すると言ったことになります。
つまり、なにか科学的なモデルをシミュレートすることで、おもしろいアートを産み出して行こうというわけです。
Quilで始める
さて、今回使用するのは、ProcessingをClojureでラップした、Quilというものを使います。
最初のサンプル
さて、基本的なことは、他のチュートリアルに任せるとして、まず簡単なサンプルを作ります。
lein new quil firstlive
さて、以下のコードが最初です。
(ns firstlive.core
(:require [quil.core :as q]
[quil.middleware :as m]
[firstlive.dynamic :as dynamic]))
(q/defsketch firstlive
:title "my first live"
:size [500 700]
:setup dynamic/setup
:update dynamic/update
:draw dynamic/draw
:mouse-clicked dynamic/mouse-clicked
:middleware [m/fun-mode])
(ns firstlive.dynamic
(:require [quil.core :as q]))
(defn setup []
(q/frame-rate 30)
(q/color-mode :hsb)
(q/background 240)
{})
(defn update [state]
state)
(defn draw [state]
(q/no-stroke)
(q/fill (q/random 0 200) 230 230)
(q/ellipse (q/random 0 700) (q/random 0 700) 10 10))
(defn mouse-clicked [event state]
state)
dynamic.cljは、今後動的に変更していくところです。どうです?わくわくしてきませんか?
さて、replを起動して、以下のコードで、最初のサンプルの結果を見てみましょう。
user> (use 'firstlive.core)
結果はこうなるはずです。(長時間放置したので、最初はもっと点は少ないと思います。)
動的な更新を試す
さて、 ライブコーディングをしていくのであれば、動的に更新しながら、楽しみたいですよね。
さて、やってみましょう。
見た通り、点が沢山表示されていると思いますので、クリックしたら消すようにしましょう。
さきのdynamic.cljのmouse-clickedの関数を変更しましょう。
(defn mouse-clicked [event state]
(q/background 240) ;; 追加
state)
単純に背景を塗り潰すだけです。さて、この画面を開いたまま動的に変更しましょう。replから、以下のコードを実行するだけです。
user> (use :reload 'firstlive.dynamic)
さて、スケッチをクリックしてみましょう。点は消えましたか?
雨を降らす
さて、何かをアート的なものを作るには、行きあたりばったりやっても良いのですが、テーマを何か設定しましょう。
今回は、雨で行こうと思います。
玉を落すだけ
玉を落す -> たくさん玉を落すという戦略で雨を降らせようと思います。
さて、新しいファイルを追加して、ball.cljを作りましょう。
(ns firstlive.ball
(:require [quil.core :as q]))
(defn make-ball [x y]
{:x x
:y y})
(defn update-ball [ball]
(if (< (:y ball) 700)
(assoc ball :y (+ (:y ball) 5))
(assoc ball :y 0)))
(defn draw-ball [ball]
(q/ellipse (:x ball) (:y ball) 10 10))
そして、dynamic.cljを変更しましょう。
(ns firstlive.dynamic
(:require [quil.core :as q])
(:require [firstlive.ball :as ball]))
(defn setup []
(q/frame-rate 30)
(q/color-mode :hsb)
(q/background 240)
(ball/make-ball 250 0)) ;; 変更
(defn update [ball]
(ball/update-ball ball)) ;; 変更
(defn draw [ball]
(q/background 240) ;; 追加
(q/no-stroke)
(q/fill (q/random 0 200) 230 230)
(ball/draw-ball ball)) ;; 変更
(defn mouse-clicked [state event]
(q/background 240)
state)
まず、updateとdraw関数を変更しています。
setup関数は最初のprocessingの初期化時に一回だけ呼ばれるので、変更の必要は無いのですが、再度、Processingを立ち上げたことを考え、変更しています。
さて、動的にロードしていきましょう。
user> (use :reload 'firstlive.dynamic)
オブジェクトを実行中に更新する
あ、ボールがきらきらしてて、嫌ですね。ちょっと変更しましょうか。ballに色の状態を持たせましょう。
ballの古いオブジェクトに対してcolorを動的にアップデートする関数を先ず書いておきましょう。
(defn change-new-version [ball]
(if (= (:version ball) 1)
ball
(assoc (assoc ball :version 1) :color (q/random 1 255))))
これはまず、versionをkeyとして、最新のバージョンを判断し、古いバージョンあったら、アップデートします。
そして、update関数と、make-ball関数も変更しておきましょう。
(defn make-ball [x y]
{:x x
:y y
:version 1
:color (q/random 1 255)})
(defn update-ball [ball]
(let [new-ball
(if (< (:y ball) 700)
(assoc ball :y (+ (:y ball) 5))
(assoc ball :y 0))]
(change-new-version new-ball)))
一旦、コードをロードしておきましょう。
user> (use :reload 'firstlive.ball)
さて、これで、現在実行中で、生成されているオブジェクトに色の状態を追加したので、今度はそれをdrawしていきましょう、
(defn draw-ball [ball]
(q/fill (:color ball) 233 233) ;; 追加
(q/ellipse (:x ball) (:y ball) 10 10))
そして、dynamic.cljを若干修正を入れてます。
;; q/fill呼出を削除
(defn draw [ball]
(q/background 240)
(q/no-stroke)
(ball/draw-ball ball))
そして、再度
user> (use :reload 'firstlive.ball)
しておくと、ballがチラチラしないと思います。
たくさんボールを降らせる
さて、ボールを沢山降らせましょう。
ボールをたくさん降らせる = 雨なので! rain.cljのファイルを作ってそこに書いて行きましょう!
(ns firstlive.rain
(:require [quil.core :as q]
[firstlive.ball :as ball]))
(defn make-rain []
{:balls (map #(ball/make-ball (* % 50) 1)
(range 0 10))})
(defn update-rain [rain]
(if (nil? (:balls rain))
(make-rain)
{:balls (map ball/update-ball (:balls rain))}))
(defn draw-rain [rain]
(if (nil? (:balls rain))
nil
(doseq [ball (:balls rain)] (ball/draw-ball ball))))
そして、dynamic.cljを変更しましょう
(ns firstlive.dynamic
(:require [quil.core :as q])
(:require [firstlive.rain :as rain]))
(defn setup []
(q/frame-rate 30)
(q/color-mode :hsb)
(q/background 240)
(rain/make-rain))
(defn update [state]
(rain/update-rain state))
(defn draw [state]
(q/background 240)
(q/no-stroke)
(rain/draw-rain state))
(defn mouse-clicked [state event]
(q/background 240)
state)
さて、ロードしましょう。
user> (use :reload 'firstlive.ball)
そして、沢山ボールが降ってきました。
まだまだ、雨らしく無いですが、それは今後の課題としています。
まとめ
さて、今回は、
- Creative Codingの紹介
- ClojureがCreative Codingの言語としては、なかなか良い選択であること
- Clojureで、実行中に動的にコードを置き変えながら、Creative Codingの実践をする
ということをやりました。
まだまだ、書くべきことが多いのですが今日はここまで。