ClojureとQuilでいろいろ降らせてみた
前回の元記事の作者の方がこのような記事をQiitaに挙げていた:
前回のコードは基本的に形を座標リストとして表してしまえばあとは同じ関数でデータ作成・描画・アップデートができるので、とりあえずいろいろ降らせてみた。
とりあえず円、正多角形、星、ハート、楓を作ってみた。
円は簡単:
(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-fn
とrange
の二つに一回ずつ渡しているのがダサい・・・
星も同じ理屈:
(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)))) ...}))
このように簡単に表示・動く形を増やすことができる。