Created
December 6, 2019 16:16
-
-
Save ampersanda/2f3d51bbf2555123851227ae9f2a50fc to your computer and use it in GitHub Desktop.
Count digit of PI using block collisions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns my.core | |
(:require [quil.core :as q :include-macros true] | |
[quil.middleware :as m])) | |
;; x is horizontal position of the block | |
;; y is vertical position of the block | |
;; w is width of the block | |
;; m is mass/weight of the block | |
;; v is velocity of the block | |
(defn block [x w v m color] | |
{:x x | |
:y (- (q/height) w) | |
:w w | |
:m m | |
:v v | |
:color color}) | |
(def first-block-weight 20) | |
(def exponent 7) | |
(defn draw-block [{:keys [x y w v color]}] | |
(q/no-stroke) | |
(apply q/fill color) | |
(q/rect x y w w)) | |
(defn is-colliding? [block other-block] | |
(let [x1 (:x block) | |
w1 (:w block) | |
x2 (:x other-block) | |
w2 (:w other-block) | |
colliding? (not (or (< (+ x1 w1) x2) (> x1 (+ x2 w2))))] | |
colliding?)) | |
(defn is-hit-wall? [block] | |
(<= (:x block) 0)) | |
;; ellastic collision, https://en.wikipedia.org/wiki/Elastic_collision | |
(defn elastic-collision [block other-block] | |
(let [blocks [block other-block] | |
v1 (:v block) | |
v2 (:v other-block) | |
m2 (:m other-block) | |
total-mass (apply + (map :m blocks)) | |
diff-mass (apply - (map :m blocks))] | |
(+ (* (/ diff-mass total-mass) v1) (* (/ (* 2 m2) total-mass) v2)))) | |
(def states (atom nil)) | |
(defn update-block [{:keys [x y w v] :as block}] | |
(assoc block :x (+ x v))) | |
(defn setup [] | |
(q/frame-rate 60) | |
(q/color-mode :hsb) | |
(let [euler-hack (q/pow 10 (dec exponent))] | |
(reset! states {:blocks [(block 100 20 0 first-block-weight [255 100 160]) (block 200 100 (/ -5 euler-hack) (* first-block-weight (q/pow 100 (dec exponent))) [100 100 160])] | |
:counter 0}))) | |
(defn update-state [] | |
(let [{:keys [blocks counter]} @states | |
new-blocks (if (apply is-colliding? blocks) | |
(let [new-velocities [(apply elastic-collision blocks) (apply elastic-collision (reverse blocks))]] | |
(map #(assoc % :v %2) blocks new-velocities)) | |
blocks) | |
new-counter (if (apply is-colliding? blocks) | |
(inc counter) | |
counter) | |
collide-wall-blocks (map #(if (is-hit-wall? %) (update % :v -) %) new-blocks) | |
collide-wall-counter (apply + (map #(if (is-hit-wall? %) 1 0) new-blocks))] | |
(swap! states assoc :blocks (map #(update-block %) collide-wall-blocks)) | |
(swap! states assoc :counter (+ new-counter collide-wall-counter)))) | |
(defn draw-state [state] | |
(let [{:keys [blocks counter]} @states | |
euler-hack (q/pow 10 (dec exponent))] | |
(q/background 240) | |
(doseq [i (range euler-hack)] | |
(update-state)) | |
(doseq [block blocks] | |
(draw-block block)) | |
(q/fill 0) | |
(q/text-size 24) | |
(q/text counter 16 24))) | |
(q/defsketch my | |
:host "host" | |
:size [500 500] | |
:setup setup | |
:draw draw-state | |
:middleware [m/fun-mode]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment