Clojure + Processing(5) - Processing wrapper for clojure

自分で書く前に clojuregoogle group で見つけた。

Roland Sadowski さんによる。素晴らしい。こっちで気付いたことが既にカバーされているようだ。うーん、2ヶ月ほど遅れたか。これから試してみよう。

  • clojure では static クラスメソッド(以下の例では cos, sin など)と、インスタンスメソッドの呼び出し方は使い分けないとエラーになる。これは嫌すぎる。 => ラッパーで何でも defn で定義された単なる関数に。
  • Java のメソッドをよびだすとき、明示的に (float x) などと指定しなければならない場合がある => ラッパーで対処。fill だけでなく fill-int, fill-float などを追加。
  • またグローバルに *applet* (PApplet を参照)を定義。

ひとつバグ発見。stroke-weight が strokeJoin を呼んでいる。google group にポストしたつもりだけど反映されてない?google group のマナーが良くわかっていない。

以下しつこいがおなじプログラムを rosado.processing を使って書き直したもの。ラッパーのおかげでだいぶすっきり。

(clojure/ns p5-example
	    (:use rosado.processing)
	    (:import (javax.swing JFrame JLabel JTextField JButton))
	    (:import (processing.core PApplet)))

(let [angle1 (ref (float 0.0))
      x (ref (float 100))
      y (ref (float 100))
      segLength (float 50)]

  (defn segment [x y a]
    (push-matrix)
    (translate x y)
    (rotate a)
    (line 0 0 segLength 0)
    (pop-matrix))

  (defn follow-draw 
    [dst]
    (background-int 226)
    (dosync
     (let [mx (mouse-x)
	   my (mouse-y)
	   dx (- mx @x)
	   dy (- my @y)]
       (ref-set angle1 (atan2 dy dx))
       (ref-set x (float (- mx (* (cos @angle1) segLength))))
       (ref-set y (float (- my (* (sin @angle1) segLength))))
       (segment @x @y @angle1)
       (ellipse @x @y 20 20)))))

(def p5-applet
     (proxy [PApplet] []
	    (setup []
		   (binding [*applet* this]
		     (size 200 200)
		     (smooth)
		     (stroke-weight 20.0)
		     (stroke-float 0 100)))
	    (draw []
		  (binding [*applet* this]
		    (follow-draw this)))))

(.init p5-applet)

(def swing-frame (JFrame. "Processing with Clojure"))

(doto swing-frame
  ;;  (setDefaultCloseOperation (. JFrame EXIT_ON_CLOSE))
  (setSize 200 200)
  (add p5-applet)
  (pack)
  (show))