quil / quil-site

Source code of quil.info
http://quil.info
Eclipse Public License 1.0
7 stars 13 forks source link

Fire Example #24

Closed rollacaster closed 5 years ago

rollacaster commented 5 years ago
(ns fire.core
  (:require [quil.core :as q :include-macros true]
            [quil.middleware :as m]))

(defn add [v1 v2]
  (vector (+ (first v1) (first v2))
          (+ (second v1) (second v2))))

(defn div [[x y] n] (if (or (= n 0) (= n 0.0))
                      (vector x y)
                      (vector (/ x n) (/ y n))))

(defn create-particle [location]
  {:location location
   :velocity [(* (q/random-gaussian) 0.3) (- (* (q/random-gaussian) 0.4) 1.0)]
   :acceleration [0 0]
   :lifespan 255
   :mass 10})

(defn add-particle [ps]
  (update ps :particles #(conj % (create-particle (:origin ps)))))

(defn display-particle [{:keys [lifespan] [x y] :location :as particle}]
  (q/color-mode :rgb)
  (q/fill (q/color 255 24 0 lifespan))
  (q/ellipse x y (q/map-range lifespan 0 255 0 (/ (q/width) 10)) 
                 (q/map-range lifespan 0 255 0 (/ (q/width) 10))))

(defn is-dead [{:keys [lifespan]}] (< lifespan 0.0))

(defn apply-force [{:keys [mass acceleration] :as particle} force]
  (assoc particle :acceleration (add acceleration (div force mass))))

(defn update-particle [{:keys [acceleration velocity location lifespan] :as particle}]
  (let [velocity (add velocity acceleration)
        location (add velocity location)
        lifespan (- lifespan 2.0)]
    (-> particle
        (assoc :velocity velocity)
        (assoc :location location)
        (assoc :lifespan lifespan)
        (assoc :acceleration [0 0]))))

(defn run-particle-system [{:keys [particles confetti] :as ps}]
  (doseq [particle particles]
    (display-particle particle))
  (let [wind [(q/map-range (q/mouse-x) 0.0 (q/width) -0.3 0.3)
              (q/map-range (q/mouse-y) 0.0 (q/height) -0.3 0.3)]]
    (-> ps
        (update :particles #(map (fn [particle] (apply-force particle wind)) %))
        (update :particles #(map update-particle %))
        (update :particles #(remove is-dead %)))))

(defn setup []
  (def particle-system (atom {:particles () :origin [(/ (q/width) 2)
                                                    (* 2 (/ (q/height) 3))]}))
  (set! (.-globalCompositeOperation (.getContext (.getElementById js/document "host") "2d")) "lighter"))

(defn draw []
  (.clearRect (.getContext (.getElementById js/document "host") "2d") 0 0 (q/width) (q/height))
  (q/background 0)
  (swap! particle-system (comp add-particle add-particle add-particle run-particle-system)))

(q/defsketch fire
  :host "host"
  :size [500 500]
  :setup setup
  :draw draw)

Here's my fire example 🔥 Thank's for creating quil!

nbeloglazov commented 5 years ago

Thanks Thomas! Quick question, are those calls to context object of the canvas necessary? Ideally sketch should use only quil API so that it can be run both on clj and cljs.

rollacaster commented 5 years ago

Initially I made the sketch with Clojure. I used clear and blend-mode, both are not implemented in the cljs API. I assumed that I had to use canvas methods to have the same behaviour.

I used these methods to create the fire illusion. It is lighter in the middle and appears in a darker red on the outside. If you know a way to achieve the same behaviour, I will change it.

nbeloglazov commented 5 years ago

I see. We are currently migrating Quil to use p5js which adds blend-mode to cljs version. Maybe you could try it out for your sketch? This is the version: https://clojars.org/quil/versions/3.0.0-SNAPSHOT

As for clear - it's still not supported in cljs. For your case setting background to some color doesn't work for some reason?

rollacaster commented 5 years ago

I tried Quil 3.0.0. in my project but it breaks all sketches: https://github.com/rollacaster/sketches/tree/quil-3.0.0

In my case changing the background is not enough because all particles need to be redrawn for each frame otherwise it does not look like fire (http://quil.info/sketches/show/3d633eb85c4ec1b23d4e0d815c4b76e408f748c4f2814ec6694bc77f43baf1b9)

nbeloglazov commented 5 years ago

I see, make sense. I'll add clear function to cljs as well then based on your sketch.

As for breaking all sketches - in 3.0.0 insted of using as hosts for sketches we now need to use

. If beside that sketches still keep failing - please share as it might indicate bugs in 3.0.0. Also there was some API changes and some functions were removed. This sheet can help to see what changed.

I'm planning to add your example once we release 3.0.0.

rollacaster commented 5 years ago

All my sketches work with 3.0.0 thanks for this sheet. I am happy my example is added after the release :)

My only issue is that I don't know how to apply custom styles the canvas element which was created, it has some inline styles. But I probably can find a workaround which removes them after the canvas was created.

anthonygalea commented 5 years ago

Very nice Thomas. Is this how your sketch looks like with clj?

screenshot

Made minor modifications to get it running with cljs:

(ns fire.core
  (:require [quil.core :as q :include-macros true]
            [quil.middleware :as m]))

(defn add [v1 v2]
  (vector (+ (first v1) (first v2))
          (+ (second v1) (second v2))))

(defn div [[x y] n] (if (or (= n 0) (= n 0.0))
                      (vector x y)
                      (vector (/ x n) (/ y n))))

(defn create-particle [location]
  {:location location
   :velocity [(* (q/random-gaussian) 0.3) (- (* (q/random-gaussian) 0.4) 1.0)]
   :acceleration [0 0]
   :lifespan 255
   :mass 10})

(defn add-particle [ps]
  (update ps :particles #(conj % (create-particle (:origin ps)))))

(defn display-particle [{:keys [lifespan] [x y] :location :as particle}]
  (q/color-mode :rgb)
  (q/fill (q/color 255 24 0 lifespan))
  (q/ellipse x y (q/map-range lifespan 0 255 0 (/ (q/width) 10)) 
                 (q/map-range lifespan 0 255 0 (/ (q/width) 10))))

(defn is-dead [{:keys [lifespan]}] (< lifespan 0.0))

(defn apply-force [{:keys [mass acceleration] :as particle} force]
  (assoc particle :acceleration (add acceleration (div force mass))))

(defn update-particle [{:keys [acceleration velocity location lifespan] :as particle}]
  (let [velocity (add velocity acceleration)
        location (add velocity location)
        lifespan (- lifespan 2.0)]
    (-> particle
        (assoc :velocity velocity)
        (assoc :location location)
        (assoc :lifespan lifespan)
        (assoc :acceleration [0 0]))))

(defn update-state [state]
  (let [wind [(q/map-range (q/mouse-x) 0.0 (q/width) -0.3 0.3
                (q/map-range (q/mouse-y) 0.0 (q/height) -0.3 0.3))]]
      (-> state
          (update :particles #(map (fn [particle] (apply-force particle wind)) %))
          (update :particles #(map update-particle %))
          (update :particles #(remove is-dead %))
          add-particle
          add-particle
          add-particle)))  

(defn setup []
 {:particles ()
  :origin [(/ (q/width) 2)
           (* 2 (/ (q/height) 3))]})

(defn draw-state [{:keys [particles] :as state}]
  (q/clear)
  (q/background 0)
  (doseq [particle particles]
    (display-particle particle))) 

(q/defsketch fire
  :host "host"
  :size [500 500]
  :setup setup
  :update update-state
  :draw draw-state
  :middleware [m/fun-mode])
nbeloglazov commented 5 years ago

Fixed link (we need to do something with sharing as often people share url as as it is without clicking "share"). Probably need just to enable sharing by default.

nbeloglazov commented 5 years ago

Here is how it looked on the original sketch: https://ibb.co/cgyPWCf Looks like 3.0.0 doesn't handle color well? Looking at original sketch code I don't actually see how it produces yellow color.

rollacaster commented 5 years ago

The yellow color is produced by using (q/blend-mode :add), which is the only thing missing in @anthonygalea version to make it work. (http://quil.info/sketches/show/c5d0eb21889f6a0217269c4d14776e6a3e1bc6e60c394e565ae95e5e451aa5b6)

nbeloglazov commented 5 years ago

Adding this example right now. Btw, commenting (q/clear) makes cool effect: http://quil.info/sketches/show/50b3d79c0e0fe66d9a63929fb1f3b60a8856f54e05028104d581db28b337a902

nbeloglazov commented 5 years ago

Added and redeployed: http://quil.info/?example=fire Thanks for the great sketch!