Arantium Maestum

プログラミング、囲碁、読書の話題

ClojureとQuilでいろいろ降らせてみた

前回の元記事の作者の方がこのような記事をQiitaに挙げていた:

qiita.com

前回のコードは基本的に形を座標リストとして表してしまえばあとは同じ関数でデータ作成・描画・アップデートができるので、とりあえずいろいろ降らせてみた。

Quil -L7gXIMMKuYC2kSR6goi

とりあえず円、正多角形、星、ハート、楓を作ってみた。

円は簡単:

(defn circle-fn [t]
  (let [radt (q/radians t)
        x    (/ (q/cos radt) 3)
        y    (/ (q/sin radt) 3)]
    [x y]))

(def circle-shape
  (map circle-fn (range 360)))

(cos n, sin n)だからね・・・

多角形は高階関数になっている:

(defn polygon-fn [v]
  (fn [t]
    (let [z (-> t (/ v) (* 360) q/radians)
          x (/ (q/cos z) 3)
          y (/ (q/sin z) 3)]
      [x y])))

(def triangle-shape
  (map (polygon-fn 3) (range 3)))

(def hexagon-shape
  (map (polygon-fn 6) (range 6)))

上の円と同じ理屈で、描く点の数を減らしているのがポイント。ただ、私の実装だと同じ数をpolygon-fnrangeの二つに一回ずつ渡しているのがダサい・・・

星も同じ理屈:

(defn star-fn [v]
  (fn [t]
    (let [r (inc (mod t 2))
          z (-> t (/ v) (* 360) q/radians)
          x (-> z q/cos (* r) (/ 3))
          y (-> z q/sin (* r) (/ 3))]
      [x y])))

(def five-star-shape
  (map (star-fn 10) (range 10)))

五芒星の場合、10点の頂点があり、そのうちの5つが外側の円、5つが内側の円の上に乗っている。

ハート:

(defn heart-fn [t]
  (let [radt (q/radians t)
        R    1/50
        x    (* R 13 (q/sin radt) (q/sin radt) (q/sin radt))
        y    (* -1 R (- (-> t q/radians q/cos (* 13))
                        (-> t (* 2) q/radians q/cos (* 5))
                        (-> t (* 3) q/radians q/cos (* 2))
                        (-> t (* 4) q/radians q/cos)))]
    [x y]))

(def heart-shape
  (map heart-fn (range 360)))

楓:

(defn leaf-fn [t]
  (let [R    1/8
        r    (* -1
                (-> t (* 8) q/radians q/cos (* 9) (/ 10) inc)
                (-> t (* 24) q/radians q/cos (/ 10) inc)
                (-> t (* 200) q/radians q/cos (/ 10) (+ 0.9))
                (-> t q/radians q/sin inc))
        x    (-> t q/radians q/cos (* r R))
        y    (-> t q/radians q/sin (* r R))]
    [x y]))

(def leaf-shape
  (map leaf-fn (range 360)))

ここらへんは正直理屈はわからぬ・・・

あとはshapesという名のvectorに集めて、make-sakura(今になって思えば関数名を変えるべきだった)の中でランダムにshapesの中から座標リストを取ってくるようにしてある:

(def shapes
  [sakura-shape
   circle-shape
   triangle-shape
   hexagon-shape
   five-star-shape
   heart-shape
   leaf-shape])

(defn make-sakura []
  (let [...]
    {:shape (nth shapes (q/floor (q/random (count shapes))))
...}))

このように簡単に表示・動く形を増やすことができる。