├── doc └── intro.md ├── src └── natureofclojure │ ├── core.clj │ ├── ch1_2_pvector_class │ ├── bouncingball_pvector_ball.clj │ ├── bouncingball_clojure_vector_ball.clj │ ├── ball │ │ ├── pvector_ball.clj │ │ └── clojure_vector_ball.clj │ └── bouncingball_pvectors.clj │ ├── i_5 │ ├── perlin_noise.clj │ ├── noise_walk.clj │ ├── exercise_i_10_noise_landscape.clj │ ├── walker │ │ └── noise.clj │ └── landscape.clj │ ├── ch2_1_what_is_a_force │ ├── motion101_mouse_acceleration.clj │ └── mover │ │ └── mouse_acceleration.clj │ ├── i_2 │ ├── random_walk_trail.clj │ ├── random_walk_tends_to_right.clj │ ├── simple_probability.clj │ ├── walker │ │ ├── tends_to_right.clj │ │ └── trail.clj │ └── multiple_probability.clj │ ├── i_3 │ ├── gaussian_throb.clj │ ├── gaussian.clj │ ├── random_distribution.clj │ └── gaussian2.clj │ ├── i_1 │ ├── random_walk_traditional.clj │ └── walker │ │ └── traditional.clj │ ├── math │ ├── vector.clj │ └── fast_vector.clj │ ├── ch3_1_angles_and_angular_motion │ ├── angles.clj │ ├── angular_motion.clj │ ├── attractor.clj │ ├── forces_angular_motion.clj │ └── mover.clj │ ├── ch1_5_vectors_acceleration │ ├── motion101.clj │ ├── motion101_acceleration.clj │ ├── motion101_random_acceleration.clj │ └── mover │ │ ├── random_acceleration.clj │ │ └── acceleration.clj │ ├── slider │ ├── demo.clj │ └── h_slider.clj │ ├── ch1_6_vectors_acceleration_towards_mouse │ ├── motion101_mouse_acceleration.clj │ └── mover │ │ └── mouse_acceleration.clj │ ├── ch1_3_vector_math │ ├── vector_subtraction.clj │ └── vector_multiplication.clj │ ├── ch1_4_vector_math_ii │ ├── vector_normalize.clj │ └── vector_magnitude.clj │ ├── ch3_3_simple_harmonic_motion │ ├── simple_harmonic_motion.clj │ ├── simpler_harmonic_motion.clj │ └── oscillating_objects.clj │ ├── ch2_2_applying_a_force │ ├── forces.clj │ ├── forces_many.clj │ └── mover_forces.clj │ ├── ch6_5_dot_product │ ├── behavior.clj │ ├── simple_scalar_projection.clj │ ├── angle_between.clj │ └── mover_projection.clj │ ├── ch1_1_vectors │ └── bouncingball_novectors.clj │ ├── ch2_6_gravitational_attraction │ ├── attractor.clj │ ├── attraction.clj │ ├── attraction_many.clj │ ├── mutual_attraction.clj │ ├── mutual_mover.clj │ └── mover.clj │ ├── ch3_2_trigonometry_and_polar_coordinates │ └── polar_to_cartesian.clj │ ├── ch2_3_simulating_mass │ ├── forces_many_realgravity.clj │ └── mover_forces.clj │ ├── ch2_4_friction_force │ ├── forces_friction.clj │ └── mover.clj │ ├── ch2_5_drag_force │ ├── liquid.clj │ ├── mouse_drag.clj │ ├── fluid_resistance.clj │ └── mover.clj │ ├── i_4 │ └── monte_carlo_distribution.clj │ ├── ch6_4_flow_field_following │ └── core.clj │ ├── ch6_7_grouping │ ├── separation.clj │ ├── alignment.clj │ ├── cohesion.clj │ └── behavior.clj │ ├── ch3_4_pendulum_simulation │ └── core.clj │ ├── ch6_6_steering_behaviors │ ├── behavior.clj │ ├── path_following_simple.clj │ └── complex_path.clj │ ├── ch6_2_steering_behaviors_seek │ └── core.clj │ ├── ch6_8_flocking │ ├── separation_seek.clj │ ├── boids.clj │ ├── behavior.clj │ └── boid_slider.clj │ └── ch6_3_steering_behaviors_arrive │ └── core.clj ├── dev └── user.clj ├── test └── natureofclojure │ └── core_test.clj ├── .gitignore ├── project.clj └── README.md /doc/intro.md: -------------------------------------------------------------------------------- 1 | # Introduction to natureofclojure 2 | 3 | TODO: write [great documentation](http://jacobian.org/writing/great-documentation/what-to-write/) 4 | -------------------------------------------------------------------------------- /src/natureofclojure/core.clj: -------------------------------------------------------------------------------- 1 | (ns natureofclojure.core) 2 | 3 | (defn foo 4 | "I don't do a whole lot." 5 | [x] 6 | (println x "Hello, World!")) 7 | -------------------------------------------------------------------------------- /dev/user.clj: -------------------------------------------------------------------------------- 1 | (ns user 2 | (:require 3 | [clojure.repl :refer (source apropos dir pst doc find-doc)] 4 | [clojure.java.javadoc :refer (javadoc)] 5 | [clojure.pprint :refer (pp pprint)])) 6 | -------------------------------------------------------------------------------- /test/natureofclojure/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns natureofclojure.core-test 2 | (:use clojure.test 3 | natureofclojure.core)) 4 | 5 | (deftest a-test 6 | (testing "FIXME, I fail." 7 | (is (= 0 1)))) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /lib 3 | /classes 4 | /checkouts 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | .lein-deps-sum 10 | .lein-failures 11 | .lein-plugins 12 | .lein-repl-history 13 | .nrepl-port 14 | 15 | # Emacs 16 | *~ 17 | \#*\# 18 | /.emacs.desktop 19 | /.emacs.desktop.lock 20 | *.elc 21 | auto-save-list 22 | tramp 23 | .\#* 24 | 25 | # Org-mode 26 | .org-id-locations 27 | *_archive 28 | 29 | # flymake-mode 30 | *_flymake.* 31 | 32 | # eshell files 33 | /eshell/history 34 | /eshell/lastdir 35 | 36 | # elpa packages 37 | /elpa/ 38 | 39 | # reftex files 40 | *.rel 41 | 42 | # AUCTeX auto folder 43 | /auto/ -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject natureofclojure "0.1.0-SNAPSHOT" 2 | :description "A bunch of Clojure Quil examples based on Daniel Shiffman's Nature of Code video channel on Vimeo." 3 | :url "http://github.com/mudphone/natureofclojure" 4 | :license {:name "Create Commons Attribution-ShareAlike 2.0 Generic License" 5 | :url "http://creativecommons.org/licenses/by-sa/2.0/"} 6 | :dependencies [[org.clojure/clojure "1.6.0"] 7 | [quil "2.2.1"] 8 | [org.clojure/math.numeric-tower "0.0.2"] 9 | [net.mikera/vectorz-clj "0.25.0"]] 10 | :profiles {:dev {:source-paths ["dev"]}} 11 | ) 12 | -------------------------------------------------------------------------------- /src/natureofclojure/ch1_2_pvector_class/bouncingball_pvector_ball.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch1-2-pvector-class.bouncingball-pvector-ball 6 | (:require [quil.core :as qc] 7 | [natureofclojure.ch1-2-pvector-class.ball.pvector-ball :as pb])) 8 | 9 | (defn setup []) 10 | 11 | (defn draw [] 12 | (qc/background 255) 13 | (pb/move @pb/ball) 14 | (pb/bounce @pb/ball) 15 | (pb/display @pb/ball)) 16 | 17 | (defn run [] 18 | (qc/defsketch bouncingball-pvector-ball 19 | :title "Bouncing Ball - PVector Ball" 20 | :setup setup 21 | :draw draw 22 | :size [pb/WIDTH pb/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_5/perlin_noise.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.i-5.perlin-noise 6 | (:require [quil.core :as qc])) 7 | 8 | (def WIDTH 600.0) 9 | (def HEIGHT 400.0) 10 | (def t (atom 0)) 11 | 12 | (defn setup [] 13 | (qc/frame-rate 60)) 14 | 15 | (defn draw [] 16 | (qc/background 0) 17 | (qc/fill 255) 18 | (swap! t #(+ % 0.01)) 19 | 20 | (let [n (qc/noise @t) 21 | x (qc/map-range n 0 1 0 WIDTH)] 22 | (qc/ellipse x (/ HEIGHT 2.0) 40 40))) 23 | 24 | (defn run [] 25 | (qc/defsketch perlin-noise 26 | :title "Perlin Noise" 27 | :setup setup 28 | :draw draw 29 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_2_pvector_class/bouncingball_clojure_vector_ball.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch1-2-pvector-class.bouncingball-clojure-vector-ball 6 | (:require [quil.core :as qc] 7 | [natureofclojure.ch1-2-pvector-class.ball.clojure-vector-ball :as cb])) 8 | 9 | (defn setup []) 10 | 11 | (defn draw [] 12 | (qc/background 255) 13 | (cb/move cb/ball) 14 | (cb/bounce cb/ball) 15 | (cb/display @cb/ball)) 16 | 17 | (defn run [] 18 | (qc/defsketch bouncingball-clojure-vector-ball 19 | :title "Bouncing Ball - Clojure Vector Ball" 20 | :setup setup 21 | :draw draw 22 | :size [cb/WIDTH cb/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_5/noise_walk.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/NOC_I_5_NoiseWalk/NOC_I_5_NoiseWalk.pde 7 | ;; 8 | (ns natureofclojure.i-5.noise-walk 9 | (:require [quil.core :as qc] 10 | [natureofclojure.i-5.walker.noise :as wn])) 11 | 12 | (defn setup [] 13 | (qc/frame-rate 30)) 14 | 15 | (defn draw [] 16 | (qc/background 255) 17 | (wn/walk-walker wn/walker) 18 | (wn/display-walker @wn/walker)) 19 | 20 | (defn run [] 21 | (qc/defsketch noise-walk 22 | :title "Noise Walk" 23 | :setup setup 24 | :draw draw 25 | :size [wn/WIDTH wn/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_1_what_is_a_force/motion101_mouse_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch2-1-what-is-a-force.motion101-mouse-acceleration 6 | (:require [quil.core :as qc]) 7 | (:use [natureofclojure.ch2-1-what-is-a-force.mover.mouse-acceleration :as mover])) 8 | 9 | (def WIDTH 800.0) 10 | (def HEIGHT 200.0) 11 | 12 | (defn setup [] 13 | (mover/initialize mover/mover WIDTH HEIGHT)) 14 | 15 | (defn draw [] 16 | (qc/background 255) 17 | 18 | (mover/update mover/mover) 19 | (mover/display @mover/mover)) 20 | 21 | (defn run [] 22 | (qc/defsketch what-is-a-force 23 | :title "What is a force?" 24 | :setup setup 25 | :draw draw 26 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/random_walk_trail.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/RandomWalkTrail/RandomWalkTrail.pde 7 | ;; 8 | (ns natureofclojure.i-2.random-walk-trail 9 | (:require [quil.core :as qc] 10 | [natureofclojure.i-2.walker.trail :as tr])) 11 | 12 | (defn setup [] 13 | (qc/frame-rate 30)) 14 | 15 | (defn draw [] 16 | (qc/background 255) 17 | (tr/step-walker tr/walker) 18 | (tr/render-walker @tr/walker)) 19 | 20 | (defn run [] 21 | (qc/defsketch random-walk-trail 22 | :title "Random Walk Trail" 23 | :setup setup 24 | :draw draw 25 | :size [tr/WIDTH tr/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_3/gaussian_throb.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.i-3.gaussian-throb 6 | (:import [java.util Random]) 7 | (:require [quil.core :as qc])) 8 | 9 | (def WIDTH 400) 10 | (def HEIGHT 300) 11 | 12 | ;; Create a Java random number generating object 13 | ;; (This is a mutable thing.) 14 | (def generator (new Random)) 15 | 16 | (defn setup []) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | (let [h (+ 100 (* 10 (. generator nextGaussian)))] 21 | (qc/fill 0) 22 | (qc/ellipse (/ WIDTH 2.0) (/ HEIGHT 2.0) h h))) 23 | 24 | (defn run [] 25 | (qc/defsketch gaussian-throb 26 | :title "Gaussian Throb" 27 | :setup setup 28 | :draw draw 29 | :size [WIDTH HEIGHT])) 30 | -------------------------------------------------------------------------------- /src/natureofclojure/i_1/random_walk_traditional.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/introduction/NOC_I_1_RandomWalkTraditional 7 | ;; 8 | (ns natureofclojure.i-1.random-walk-traditional 9 | (:require [quil.core :as qc] 10 | [natureofclojure.i-1.walker.traditional :as wt])) 11 | 12 | (defn setup [] 13 | (qc/frame-rate 60) 14 | (qc/background 255) 15 | (qc/smooth)) 16 | 17 | (defn draw [] 18 | (wt/step-walker wt/walker) 19 | (wt/render-walker @wt/walker)) 20 | 21 | (defn run [] 22 | (qc/defsketch random-walk-traditional 23 | :title "Random Walk Traditional" 24 | :setup setup 25 | :draw draw 26 | :size [wt/WIDTH wt/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/random_walk_tends_to_right.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/introduction/NOC_I_3_RandomWalkTendsToRight 7 | ;; 8 | (ns natureofclojure.i-2.random-walk-tends-to-right 9 | (:require [quil.core :as qc] 10 | [natureofclojure.i-2.walker.tends-to-right :as ttr])) 11 | 12 | (defn setup [] 13 | (qc/frame-rate 60) 14 | (qc/background 255) 15 | (qc/smooth)) 16 | 17 | (defn draw [] 18 | (ttr/pull-walker ttr/walker) 19 | (ttr/render-walker @ttr/walker)) 20 | 21 | (defn run [] 22 | (qc/defsketch random-walk-tends-to-right 23 | :title "Random Walk Tends to Right" 24 | :setup setup 25 | :draw draw 26 | :size [ttr/WIDTH ttr/HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_5/exercise_i_10_noise_landscape.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.i-5.exercise-i-10-noise-landscape 6 | (:require [quil.core :as qc] 7 | [natureofclojure.i-5.landscape :as ls])) 8 | 9 | (def theta (atom 0.0)) 10 | 11 | (defn setup []) 12 | 13 | (defn draw [] 14 | (qc/background 255) 15 | (qc/push-matrix) 16 | (qc/translate (/ ls/WIDTH 2.0) 17 | (/ ls/HEIGHT 2.0) 18 | -160) 19 | (qc/rotate-x (/ Math/PI 3.0)) 20 | (qc/rotate-z @theta) 21 | (ls/render @ls/landscape) 22 | (qc/pop-matrix) 23 | 24 | (ls/calculate! ls/landscape) 25 | (swap! theta #(+ % 0.0025))) 26 | 27 | (defn run [] 28 | (qc/defsketch noise-landscape 29 | :title "Noise Landscape" 30 | :setup setup 31 | :draw draw 32 | :size [ls/WIDTH ls/HEIGHT] 33 | :renderer :p3d)) -------------------------------------------------------------------------------- /src/natureofclojure/math/vector.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.math.vector 6 | (:require [clojure.math.numeric-tower :as math])) 7 | 8 | (defn add [& vs] 9 | (vec (apply map + vs))) 10 | 11 | (defn subtract [& vs] 12 | (vec (apply map - vs))) 13 | 14 | (defn magnitude [v] 15 | (math/sqrt (reduce + (map #(math/expt % 2) v)))) 16 | 17 | (defn normalize [v] 18 | (let [m (magnitude v)] 19 | (vec (map #(/ % m) v)))) 20 | 21 | (defn multiply [scalar v] 22 | (vec (map * (repeat scalar) v))) 23 | 24 | (defn divide [v scalar] 25 | (vec (map / v (repeat scalar)))) 26 | 27 | (defn limit [upper v] 28 | (let [m (magnitude v)] 29 | (if (> m upper) 30 | (multiply upper (normalize v)) 31 | v))) 32 | 33 | (defn set-magnitude [mag v] 34 | (multiply mag (normalize v))) 35 | 36 | (defn random-2d [] 37 | (normalize [(- (rand 2) 1.0) (- (rand 2) 1.0)])) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_1_angles_and_angular_motion/angles.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch3-1-angles-and-angular-motion.angles 6 | (:require [quil.core :as qc])) 7 | 8 | (def WIDTH 640.0) 9 | (def HEIGHT 360.0) 10 | (def a (atom 0.0)) 11 | (def a-velocity (atom 0.0)) 12 | 13 | (defn setup []) 14 | 15 | (defn angular-acceleration [] 16 | (qc/map-range (qc/mouse-x) 0.0 WIDTH -0.001, 0.001)) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (swap! a (partial + @a-velocity)) 22 | (swap! a-velocity (partial + (angular-acceleration))) 23 | 24 | (qc/rect-mode :center) 25 | (qc/stroke 0) 26 | (qc/fill 127) 27 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 28 | (qc/rotate @a) 29 | (qc/rect 0 0 64 36)) 30 | 31 | (defn run [] 32 | (qc/defsketch angles 33 | :title "Angles" 34 | :setup setup 35 | :draw draw 36 | :size [WIDTH HEIGHT])) 37 | -------------------------------------------------------------------------------- /src/natureofclojure/ch1_5_vectors_acceleration/motion101.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_7_motion101/NOC_1_7_motion101.pde 7 | ;; 8 | (ns natureofclojure.ch1-5-vectors-acceleration.motion101 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch1-5-vectors-acceleration.mover.no-acceleration :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup [] 16 | (mover/initialize mover/mover WIDTH HEIGHT)) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (mover/update mover/mover) 22 | (mover/check-edges mover/mover WIDTH HEIGHT) 23 | (mover/display @mover/mover)) 24 | 25 | (defn run [] 26 | (qc/defsketch vectors-acceleration 27 | :title "Vectors: Acceleration - Motion 101" 28 | :setup setup 29 | :draw draw 30 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/slider/demo.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.slider.demo 6 | (:require 7 | [quil.core :as q] 8 | [quil.middleware :as m] 9 | [natureofclojure.slider.h-slider :as slider])) 10 | 11 | (def SIZE-W 800.0) 12 | (def SIZE-H 600.0) 13 | 14 | (defn setup [] 15 | {:sliders [(slider/slider {:x 10 :y 10 :label "Slider A"}) 16 | (slider/slider {:x 10 :y 100 :label "Slider B"})]}) 17 | 18 | (defn update [state] 19 | (-> state 20 | (update-in [:sliders] #(doall 21 | (mapv slider/update %))))) 22 | 23 | (defn draw [{:keys [sliders]}] 24 | (q/background 0) 25 | (dorun 26 | (map slider/draw sliders)) 27 | (dorun 28 | (map slider/draw-slider-label sliders))) 29 | 30 | (q/defsketch quil-workflow 31 | :title "Slider Demo" 32 | :size [SIZE-W SIZE-H] 33 | :setup setup 34 | :update update 35 | :draw draw 36 | :middleware [m/fun-mode]) 37 | -------------------------------------------------------------------------------- /src/natureofclojure/ch1_5_vectors_acceleration/motion101_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_8_motion101_acceleration/NOC_1_8_motion101_acceleration.pde 7 | ;; 8 | (ns natureofclojure.ch1-5-vectors-acceleration.motion101-acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch1-5-vectors-acceleration.mover.acceleration :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup [] 16 | (mover/initialize mover/mover WIDTH HEIGHT)) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (mover/update mover/mover) 22 | (mover/check-edges mover/mover WIDTH HEIGHT) 23 | (mover/display @mover/mover)) 24 | 25 | (defn run [] 26 | (qc/defsketch vectors-acceleration 27 | :title "Vectors: Acceleration" 28 | :setup setup 29 | :draw draw 30 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_3/gaussian.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/NOC_I_4_Gaussian/NOC_I_4_Gaussian.pde 7 | ;; 8 | (ns natureofclojure.i-3.gaussian 9 | (:import [java.util Random]) 10 | (:require [quil.core :as qc])) 11 | 12 | (def WIDTH 800) 13 | (def HEIGHT 200) 14 | 15 | ;; Create a Java random number generating object 16 | ;; (This is a mutable thing.) 17 | (def generator (new Random)) 18 | 19 | (defn setup [] 20 | (qc/background 255) 21 | (qc/smooth)) 22 | 23 | (defn draw [] 24 | (qc/no-stroke) 25 | (qc/fill 0 10) 26 | (qc/no-stroke) 27 | (let [sd 60.0 28 | mean (/ WIDTH 2.0) 29 | xloc (+ mean (* sd (. generator nextGaussian)))] 30 | (qc/ellipse xloc (/ HEIGHT 2.0) 16 16))) 31 | 32 | (defn run [] 33 | (qc/defsketch gaussian 34 | :title "Gaussian" 35 | :setup setup 36 | :draw draw 37 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_6_vectors_acceleration_towards_mouse/motion101_mouse_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_10_motion101_acceleration/NOC_1_10_motion101_acceleration.pde 7 | ;; 8 | (ns natureofclojure.ch1-6-vectors-acceleration-towards-mouse.motion101-mouse-acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch1-6-vectors-acceleration-towards-mouse.mover.mouse-acceleration :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup [] 16 | (mover/initialize mover/mover WIDTH HEIGHT)) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (mover/update mover/mover) 22 | (mover/display @mover/mover)) 23 | 24 | (defn run [] 25 | (qc/defsketch vectors-mouse-acceleration 26 | :title "Vectors: Mouse Acceleration" 27 | :setup setup 28 | :draw draw 29 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_3_vector_math/vector_subtraction.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_3_vector_subtraction/NOC_1_3_vector_subtraction.pde 7 | ;; 8 | (ns natureofclojure.ch1-3-vector-math.vector-subtraction 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 500.0) 12 | (def HEIGHT 300.0) 13 | 14 | (defn setup []) 15 | 16 | (defn draw [] 17 | (qc/background 255) 18 | (qc/stroke-weight 2) 19 | (qc/stroke 0) 20 | (qc/no-fill) 21 | 22 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 23 | (qc/ellipse 0 0 4 4) 24 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 25 | center [(/ WIDTH 2.0) (/ HEIGHT 2.0)] 26 | s (map - mouse center)] 27 | (qc/line 0 0 (first s) (second s)))) 28 | 29 | (defn run [] 30 | (qc/defsketch vector-subtraction 31 | :title "Vector Subtraction" 32 | :setup setup 33 | :draw draw 34 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_5_vectors_acceleration/motion101_random_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_9_motion101_acceleration/NOC_1_9_motion101_acceleration.pde 7 | ;; 8 | (ns natureofclojure.ch1-5-vectors-acceleration.motion101-random-acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch1-5-vectors-acceleration.mover.random-acceleration :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup [] 16 | (mover/initialize mover/mover WIDTH HEIGHT)) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (mover/update mover/mover) 22 | (mover/check-edges mover/mover WIDTH HEIGHT) 23 | (mover/display @mover/mover)) 24 | 25 | (defn run [] 26 | (qc/defsketch vectors-random-acceleration 27 | :title "Vectors: Random Acceleration" 28 | :setup setup 29 | :draw draw 30 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_3/random_distribution.clj: -------------------------------------------------------------------------------- 1 | (ns natureofclojure.i-3.random-distribution 2 | (:require [quil.core :as qc])) 3 | 4 | (def WIDTH 800) 5 | (def HEIGHT 200) 6 | (def random-counts (atom (vec (replicate 20 0)))) 7 | 8 | (defn setup []) 9 | 10 | (defn draw 11 | [] 12 | (qc/background 255) 13 | 14 | ;; Pick a random number and increase the count 15 | (let [index (rand-int (count @random-counts))] 16 | (swap! random-counts update-in [index] inc)) 17 | 18 | ;; Draw a rectangle to graph results 19 | (qc/stroke 0) 20 | (qc/stroke-weight 2) 21 | (qc/fill 127) 22 | 23 | (dorun 24 | (let [w (/ WIDTH (count @random-counts)) 25 | draw-rect (fn [x c] 26 | (qc/rect (* x w) 27 | (- HEIGHT c) 28 | (- w 1) 29 | c))] 30 | (map-indexed draw-rect @random-counts)))) 31 | 32 | (defn run [] 33 | (qc/defsketch random-distribution 34 | :title "Random Distribution" 35 | :setup setup 36 | :draw draw 37 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_2_pvector_class/ball/pvector_ball.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch1-2-pvector-class.ball.pvector-ball 6 | (:import [processing.core PVector]) 7 | (:require [quil.core :as qc])) 8 | 9 | (def WIDTH 200.0) 10 | (def HEIGHT 200.0) 11 | (def ball (atom {:location (new PVector 100 100) 12 | :velocity (new PVector 2.5 2)})) 13 | 14 | (defn move [b] 15 | (.add (:location b) (:velocity b))) 16 | 17 | (defn bounce [b] 18 | (let [location (:location b) 19 | velocity (:velocity b)] 20 | (when (or (> (.x location) WIDTH) 21 | (< (.x location) 0)) 22 | (set! (. velocity x) (* -1 (.x velocity)))) 23 | (when (or (> (.y location) HEIGHT) 24 | (< (.y location) 0)) 25 | (set! (. velocity y) (* -1 (.y velocity)))))) 26 | 27 | (defn display [b] 28 | ;; Display circle at x, y location 29 | (qc/stroke 0) 30 | (qc/stroke-weight 2) 31 | (qc/fill 127) 32 | (qc/ellipse (.x (:location b)) (.y (:location b)) 48 48)) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/simple_probability.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/SimpleProbablility/SimpleProbablility.pde 7 | ;; 8 | (ns natureofclojure.i-2.simple-probability 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 200.0) 12 | (def HEIGHT 200.0) 13 | (def x (atom 0)) 14 | (def y (atom 0)) 15 | 16 | (defn setup [] 17 | (qc/background 0) 18 | (qc/smooth)) 19 | 20 | (defn draw [] 21 | (qc/fill 0 1) 22 | (qc/rect 0 0 WIDTH HEIGHT) 23 | 24 | (let [prob (/ (qc/mouse-x) WIDTH) 25 | r (rand)] 26 | (when (< r prob) 27 | (qc/no-stroke) 28 | (qc/fill 255) 29 | (qc/ellipse @x @y 10 10))) 30 | 31 | (swap! x #(mod (+ % 10) WIDTH)) 32 | (when (= (int @x) 0) 33 | (swap! y #(mod (+ % 10) HEIGHT)))) 34 | 35 | (defn run [] 36 | (qc/defsketch simple-probability 37 | :title "Simple Probability" 38 | :setup setup 39 | :draw draw 40 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_4_vector_math_ii/vector_normalize.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/chp1_vectors/NOC_1_6_vector_normalize 7 | ;; 8 | (ns natureofclojure.ch1-4-vector-math-ii.vector-normalize 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup []) 16 | 17 | (defn draw [] 18 | (qc/background 255) 19 | 20 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 21 | center [(/ WIDTH 2.0) (/ HEIGHT 2.0)] 22 | s (mv/subtract mouse center) 23 | n (mv/normalize s) 24 | m (mv/multiply 150 n)] 25 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 26 | (qc/stroke 0) 27 | (qc/stroke-weight 2) 28 | (apply (partial qc/line 0 0) m))) 29 | 30 | (defn run [] 31 | (qc/defsketch vector-normalize 32 | :title "Vector Normalize" 33 | :setup setup 34 | :draw draw 35 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/walker/tends_to_right.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/introduction/NOC_I_3_RandomWalkTendsToRight 7 | ;; 8 | (ns natureofclojure.i-2.walker.tends-to-right 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800) 12 | (def HEIGHT 600) 13 | (def walker (atom {:x (/ WIDTH 2.0) 14 | :y (/ HEIGHT 2.0)})) 15 | 16 | (defn pull-walker 17 | "Slightly altered stepper to pull to the right." 18 | [w-atom] 19 | (let [choice (rand-int 100)] 20 | (cond (< choice 40) (swap! w-atom update-in [:x] #(qc/constrain-float (+ % 1) 0 WIDTH)) 21 | (< choice 60) (swap! w-atom update-in [:x] #(qc/constrain-float (- % 1) 0 WIDTH)) 22 | (< choice 80) (swap! w-atom update-in [:y] #(qc/constrain-float (+ % 1) 0 HEIGHT)) 23 | :else (swap! w-atom update-in [:y] #(qc/constrain-float (- % 1) 0 HEIGHT))))) 24 | 25 | (defn render-walker [w] 26 | (qc/stroke 0) 27 | (qc/point (:x w) (:y w))) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_3_vector_math/vector_multiplication.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_4_vector_multiplication/NOC_1_4_vector_multiplication.pde 7 | ;; 8 | (ns natureofclojure.ch1-3-vector-math.vector-multiplication 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | 14 | (defn setup []) 15 | 16 | (defn draw [] 17 | (qc/background 255) 18 | (qc/stroke-weight 2) 19 | (qc/stroke 0) 20 | (qc/no-fill) 21 | 22 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 23 | (qc/ellipse 0 0 4 4) 24 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 25 | center [(/ WIDTH 2.0) (/ HEIGHT 2.0)] 26 | s (map - mouse center) 27 | m (map * (repeat 0.5) s)] 28 | (qc/line 0 0 (first m) (second m)))) 29 | 30 | (defn run [] 31 | (qc/defsketch vector-multiplication 32 | :title "Vector Multiplication" 33 | :setup setup 34 | :draw draw 35 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_1/walker/traditional.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/introduction/NOC_I_1_RandomWalkTraditional 7 | ;; 8 | (ns natureofclojure.i-1.walker.traditional 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800) 12 | (def HEIGHT 600) 13 | 14 | (def walker (atom {:x (/ WIDTH 2.0) 15 | :y (/ HEIGHT 2.0)})) 16 | 17 | (defn render-walker [w] 18 | (qc/stroke 0) 19 | (qc/point (:x w) (:y w))) 20 | 21 | (defn step-walker [w-atom] 22 | (let [choice (rand-int 4)] 23 | (cond (= choice 0) (swap! w-atom update-in [:x] #(qc/constrain-float (+ % 1) 0 WIDTH)) 24 | (= choice 1) (swap! w-atom update-in [:x] #(qc/constrain-float (- % 1) 0 WIDTH)) 25 | (= choice 2) (swap! w-atom update-in [:y] #(qc/constrain-float (+ % 1) 0 HEIGHT)) 26 | (= choice 3) (swap! w-atom update-in [:y] #(qc/constrain-float (- % 1) 0 HEIGHT))))) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/natureofclojure/ch3_3_simple_harmonic_motion/simple_harmonic_motion.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_05_simple_harmonic_motion/NOC_3_05_simple_harmonic_motion.pde 7 | ;; 8 | (ns natureofclojure.ch3-3-simple-harmonic-motion.simple-harmonic-motion 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | 14 | (defn setup []) 15 | 16 | (defn draw [] 17 | (qc/background 255) 18 | 19 | (qc/stroke 0) 20 | (qc/stroke-weight 2) 21 | (qc/fill 127) 22 | 23 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 24 | 25 | (let [amplitude 300 26 | period 120 27 | x (* amplitude (Math/cos (/ (* qc/TWO-PI (qc/frame-count)) period)))] 28 | (qc/line 0 0 x 0) 29 | (qc/ellipse x 0 48 48))) 30 | 31 | (defn run [] 32 | (qc/defsketch simple-harmonic-motion 33 | :title "Simple Harmonic Motion" 34 | :setup setup 35 | :draw draw 36 | :size [WIDTH HEIGHT])) 37 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_2_applying_a_force/forces.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_1_forces/NOC_2_1_forces.pde 7 | ;; 8 | (ns natureofclojure.ch2-2-applying-a-force.forces 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch2-2-applying-a-force.mover-forces :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | (def m (atom (mover/mover [30.0 30.0]))) 15 | 16 | (defn setup []) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (let [updated-m (-> (mover/apply-force @m [0.01 0.0]) ;; wind 22 | (mover/apply-force [0.0 0.1]) ;; gravity 23 | (mover/update) 24 | (mover/check-edges WIDTH HEIGHT))] 25 | (mover/display updated-m) 26 | (swap! m (constantly updated-m)))) 27 | 28 | (defn run [] 29 | (qc/defsketch what-is-a-force 30 | :title "What is a force?" 31 | :setup setup 32 | :draw draw 33 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_4_vector_math_ii/vector_magnitude.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/Processing/chp1_vectors/NOC_1_5_vector_magnitude 7 | ;; 8 | (ns natureofclojure.ch1-4-vector-math-ii.vector-magnitude 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | 15 | (defn setup []) 16 | 17 | (defn draw [] 18 | (qc/background 255) 19 | 20 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 21 | center [(/ WIDTH 2.0) (/ HEIGHT 2.0)] 22 | s (mv/subtract mouse center) 23 | m (mv/magnitude s)] 24 | (qc/fill 0) 25 | (qc/no-stroke) 26 | (qc/rect 0 0 m 10) 27 | 28 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 29 | (qc/stroke 0) 30 | (qc/stroke-weight 2) 31 | (apply (partial qc/line 0 0) s))) 32 | 33 | (defn run [] 34 | (qc/defsketch vector-magnitude 35 | :title "Vector Magnitude" 36 | :setup setup 37 | :draw draw 38 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_3_simple_harmonic_motion/simpler_harmonic_motion.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_06_simple_harmonic_motion/NOC_3_06_simple_harmonic_motion.pde 7 | ;; 8 | (ns natureofclojure.ch3-3-simple-harmonic-motion.simpler-harmonic-motion 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 640.0) 12 | (def HEIGHT 360.0) 13 | (def ANGULAR_VEL 0.03) 14 | (def angle (atom 0)) 15 | 16 | (defn setup []) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | 21 | (qc/stroke 0) 22 | (qc/stroke-weight 2) 23 | (qc/fill 127) 24 | 25 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 26 | 27 | (let [amplitude 300 28 | x (* amplitude (Math/cos @angle))] 29 | (qc/line 0 0 x 0) 30 | (qc/ellipse x 0 48 48)) 31 | (swap! angle #(+ % ANGULAR_VEL))) 32 | 33 | (defn run [] 34 | (qc/defsketch simpler-harmonic-motion 35 | :title "SimpleR Harmonic Motion" 36 | :setup setup 37 | :draw draw 38 | :size [WIDTH HEIGHT])) 39 | -------------------------------------------------------------------------------- /src/natureofclojure/i_5/walker/noise.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/NOC_I_5_NoiseWalk/Walker.pde 7 | ;; 8 | (ns natureofclojure.i-5.walker.noise 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | (def walker (atom {:location [(/ WIDTH 2.0) 14 | (/ HEIGHT 2.0)] 15 | :n-off [(* 1000 (rand)) 16 | (* 1000 (rand))]})) 17 | 18 | (defn update-walker [w] 19 | (let [n-off-x (first (:n-off w)) 20 | n-off-y (second (:n-off w)) 21 | x (qc/map-range (qc/noise n-off-x) 0 1 0 WIDTH) 22 | y (qc/map-range (qc/noise n-off-y) 0 1 0 HEIGHT)] 23 | {:location [x y] 24 | :n-off (map + (repeat 0.01) (:n-off w))})) 25 | 26 | (defn walk-walker [w-atom] 27 | (swap! w-atom update-walker) 28 | ) 29 | 30 | (defn display-walker [w] 31 | (qc/stroke-weight 2) 32 | (qc/fill 127) 33 | (qc/stroke 0) 34 | (qc/ellipse (first (:location w)) 35 | (second (:location w)) 36 | 48, 48)) -------------------------------------------------------------------------------- /src/natureofclojure/ch6_5_dot_product/behavior.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch6-5-dot-product.behavior 6 | (:require 7 | [quil.core :as q] 8 | [quil.middleware :as m] 9 | [natureofclojure.math.fast-vector :as fvec])) 10 | 11 | (defn arrive-vehicle [vehicle target target-r] 12 | (let [desired (fvec/- target (:location vehicle)) 13 | d (fvec/magnitude desired) 14 | desired (fvec/normalize desired) 15 | desired (if (< d target-r) 16 | (fvec/* desired (q/map-range d 0 target-r 0 (:max-speed vehicle))) 17 | (fvec/* desired (:max-speed vehicle))) 18 | steer (fvec/- desired (:velocity vehicle)) 19 | steer (fvec/limit steer (:max-force vehicle))] 20 | (-> vehicle 21 | (update-in [:acceleration] #(fvec/+ % steer))))) 22 | 23 | (defn move-vehicle [vehicle] 24 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 25 | v (fvec/limit v (:max-speed vehicle)) 26 | loc (fvec/+ v (:location vehicle))] 27 | (-> vehicle 28 | (assoc-in [:velocity] v) 29 | (assoc-in [:location] loc) 30 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 31 | -------------------------------------------------------------------------------- /src/natureofclojure/ch3_1_angles_and_angular_motion/angular_motion.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_01_angular_motion/NOC_3_01_angular_motion.pde 7 | ;; 8 | (ns natureofclojure.ch3-1-angles-and-angular-motion.angular-motion 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | (def a (atom 0.0)) 14 | (def a-velocity (atom 0.0)) 15 | 16 | (defn setup []) 17 | 18 | (defn angular-acceleration [] 19 | ;;(qc/map-range (qc/mouse-x) 0.0 WIDTH -0.001, 0.001) 20 | 0.0001) 21 | 22 | (defn draw [] 23 | (qc/background 255) 24 | (qc/stroke 0) 25 | (qc/stroke-weight 2) 26 | (qc/fill 127) 27 | 28 | (swap! a (partial + @a-velocity)) 29 | (swap! a-velocity (partial + (angular-acceleration))) 30 | 31 | (qc/rect-mode :center) 32 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 33 | (qc/rotate @a) 34 | (qc/line -60 0 60 0) 35 | (qc/ellipse 60 0 16 16) 36 | (qc/ellipse -60 0 16 16)) 37 | 38 | (defn run [] 39 | (qc/defsketch angular-motion 40 | :title "Angular Motion" 41 | :setup setup 42 | :draw draw 43 | :size [WIDTH HEIGHT])) 44 | -------------------------------------------------------------------------------- /src/natureofclojure/ch1_2_pvector_class/ball/clojure_vector_ball.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch1-2-pvector-class.ball.clojure-vector-ball 6 | (:require [quil.core :as qc])) 7 | 8 | (def WIDTH 200.0) 9 | (def HEIGHT 200.0) 10 | (def ball (atom {:location [100 100] 11 | :velocity [2.5 2.0]})) 12 | 13 | (defn move [b-atom] 14 | (swap! b-atom assoc-in [:location] (map + 15 | (:location @b-atom) 16 | (:velocity @b-atom)))) 17 | 18 | (defn bounce [b-atom] 19 | (let [location (:location @b-atom) 20 | velocity (:velocity @b-atom)] 21 | (when (or (> (first location) WIDTH) 22 | (< (first location) 0)) 23 | (swap! b-atom update-in [:velocity] #(map * % [-1 1]))) 24 | (when (or (> (second location) HEIGHT) 25 | (< (second location) 0)) 26 | (swap! b-atom update-in [:velocity] #(map * % [1 -1]))))) 27 | 28 | (defn display [b] 29 | ;; Display circle at x, y location 30 | (qc/stroke 0) 31 | (qc/stroke-weight 2) 32 | (qc/fill 127) 33 | (qc/ellipse (first (:location b)) 34 | (second (:location b)) 35 | 48 36 | 48)) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_1_vectors/bouncingball_novectors.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_1_bouncingball_novectors/NOC_1_1_bouncingball_novectors.pde 7 | ;; 8 | (ns natureofclojure.ch1-1-vectors.bouncingball-novectors 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | (def x (atom 100)) 14 | (def y (atom 100)) 15 | (def x-speed (atom 2.5)) 16 | (def y-speed (atom 2)) 17 | 18 | (defn setup [] 19 | (qc/smooth)) 20 | 21 | (defn draw [] 22 | (qc/background 255) 23 | 24 | ;; Add the current speed to the location 25 | (swap! x + @x-speed) 26 | (swap! y + @y-speed) 27 | 28 | (when (or (> @x WIDTH) 29 | (< @x 0)) 30 | (swap! x-speed * -1)) 31 | (when (or (> @y HEIGHT) 32 | (< @y 0)) 33 | (swap! y-speed * -1)) 34 | 35 | ;; Display circle at x, y location 36 | (qc/stroke 0) 37 | (qc/stroke-weight 2) 38 | (qc/fill 127) 39 | (qc/ellipse @x @y 48 48)) 40 | 41 | (defn run [] 42 | (qc/defsketch bouncingball-novectors 43 | :title "Bouncing Ball - No Vectors" 44 | :setup setup 45 | :draw draw 46 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/attractor.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_6_attraction/Attractor.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.attractor 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-attractor [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:mass] mass))) 15 | 16 | (defn attractor 17 | ([] 18 | {:location [] 19 | :mass 20.0 20 | :g 1.0}) 21 | ([location] 22 | (attractor location 1.0)) 23 | ([location mass] 24 | (init-attractor location mass (attractor)))) 25 | 26 | (defn attract [a m] 27 | (let [force (mv/subtract (:location a) (:location m)) 28 | d (mv/magnitude force) 29 | d (qc/constrain d 1.0 5.0) 30 | n (mv/normalize force) 31 | strength (/ (* (:g a) (:mass a) (:mass m)) (* d d))] 32 | (mv/multiply strength n))) 33 | 34 | (defn display [a] 35 | (qc/ellipse-mode :center) 36 | (qc/stroke-weight 4) 37 | (qc/stroke 0) 38 | (qc/fill 127 200) 39 | (let [d (* 2.0 (:mass a))] 40 | (apply #(qc/ellipse %1 %2 d d) (:location a)))) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_2_trigonometry_and_polar_coordinates/polar_to_cartesian.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_04_PolarToCartesian/NOC_3_04_PolarToCartesian.pde 7 | ;; 8 | (ns natureofclojure.ch3-2-trigonometry-and-polar-coordinates.polar-to-cartesian 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 400.0) 13 | (def theta (atom 0.0)) 14 | (def t (atom 0.0)) 15 | 16 | (defn setup []) 17 | 18 | (defn draw [] 19 | (qc/background 255) 20 | (qc/ellipse-mode :center) 21 | (qc/stroke 0) 22 | (qc/stroke-weight 2) 23 | 24 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 25 | 26 | (let [n (qc/noise @t) 27 | r (* n 0.5 HEIGHT) 28 | x (* r (Math/cos @theta)) 29 | y (* r (Math/sin @theta)) 30 | d (* n 48)] 31 | (qc/fill (qc/map-range n 0.0 1.0 0.0 255.0)) 32 | (qc/line 0 0 x y) 33 | (qc/ellipse x y d d) 34 | (swap! theta (partial + (qc/map-range (- 1.0 n) 0.0 1.0 0.0 0.08)))) 35 | (swap! t (partial + 0.003))) 36 | 37 | (defn run [] 38 | (qc/defsketch polar-to-cartesian 39 | :title "Polar to Cartesian" 40 | :setup setup 41 | :draw draw 42 | :size [WIDTH HEIGHT])) 43 | -------------------------------------------------------------------------------- /src/natureofclojure/ch3_1_angles_and_angular_motion/attractor.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_02_forces_angular_motion/Attractor.pde 7 | ;; 8 | (ns natureofclojure.ch3-1-angles-and-angular-motion.attractor 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-attractor [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:mass] mass))) 15 | 16 | (defn attractor 17 | ([] 18 | {:location [] 19 | :mass 20.0 20 | :g 1.0}) 21 | ([location] 22 | (attractor location 1.0)) 23 | ([location mass] 24 | (init-attractor location mass (attractor)))) 25 | 26 | (defn attract [a m] 27 | (let [force (mv/subtract (:location a) (:location m)) 28 | d (mv/magnitude force) 29 | d (qc/constrain d 1.0 5.0) 30 | n (mv/normalize force) 31 | strength (/ (* (:g a) (:mass a) (:mass m)) (* d d))] 32 | (mv/multiply strength n))) 33 | 34 | (defn display [a] 35 | (qc/ellipse-mode :center) 36 | (qc/stroke-weight 4) 37 | (qc/stroke 0) 38 | (qc/fill 127 200) 39 | (let [d (* 2.0 (:mass a))] 40 | (apply #(qc/ellipse %1 %2 d d) (:location a)))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_2_applying_a_force/forces_many.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_2_forces_many/NOC_2_2_forces_many.pde 7 | ;; 8 | (ns natureofclojure.ch2-2-applying-a-force.forces-many 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch2-2-applying-a-force.mover-forces :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | (def movers (atom [])) 15 | 16 | (defn setup [] 17 | (let [ms (vec 18 | (doall 19 | (for [i (range 20) 20 | :let [mass (+ 0.1 (rand 3.9))]] 21 | (mover [0.0 0.0] mass))))] 22 | (swap! movers (constantly ms)))) 23 | 24 | (defn step-mover [m] 25 | (-> (mover/apply-force m [0.01 0.0]) ;; wind 26 | (mover/apply-force [0.0 0.1]) ;; gravity 27 | (mover/update) 28 | (mover/check-edges WIDTH HEIGHT))) 29 | 30 | (defn draw [] 31 | (qc/background 255) 32 | (let [stepped-movers (map step-mover @movers)] 33 | (dorun 34 | (map mover/display stepped-movers)) 35 | (swap! movers (constantly stepped-movers)))) 36 | 37 | (defn run [] 38 | (qc/defsketch forces-many 39 | :title "Forces: Many" 40 | :setup setup 41 | :draw draw 42 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_2_pvector_class/bouncingball_pvectors.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_2_bouncingball_vectors/NOC_1_2_bouncingball_vectors.pde 7 | ;; 8 | (ns natureofclojure.ch1-2-pvector-class.bouncingball-pvectors 9 | (:import [processing.core PVector]) 10 | (:require [quil.core :as qc])) 11 | 12 | (def WIDTH 200.0) 13 | (def HEIGHT 200.0) 14 | (def location (new PVector 100 100)) 15 | (def velocity (new PVector 2.5 2)) 16 | 17 | (defn setup [] 18 | (qc/background 255)) 19 | 20 | (defn draw [] 21 | (qc/no-stroke) 22 | (qc/fill 255, 10) 23 | (qc/rect 0 0 WIDTH HEIGHT) 24 | 25 | ;; Add the current speed to the location 26 | (.add location velocity) 27 | 28 | (when (or (> (.x location) WIDTH) 29 | (< (.x location) 0)) 30 | (set! (. velocity x) (* -1 (.x velocity)))) 31 | (when (or (> (.y location) HEIGHT) 32 | (< (.y location) 0)) 33 | (set! (. velocity y) (* -1 (.y velocity)))) 34 | 35 | ;; Display circle at x, y location 36 | (qc/stroke 0) 37 | (qc/fill 175) 38 | (qc/ellipse (.x location) (.y location) 16 16)) 39 | 40 | (defn run [] 41 | (qc/defsketch bouncingball-pvectors 42 | :title "Bouncing Ball - PVectors" 43 | :setup setup 44 | :draw draw 45 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_3_simulating_mass/forces_many_realgravity.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_3_forces_many_realgravity/NOC_2_3_forces_many_realgravity.pde 7 | ;; 8 | (ns natureofclojure.ch2-3-simulating-mass.forces-many-realgravity 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch2-3-simulating-mass.mover-forces :as mover])) 11 | 12 | (def WIDTH 800.0) 13 | (def HEIGHT 200.0) 14 | (def movers (atom [])) 15 | 16 | (defn setup [] 17 | (let [ms (vec 18 | (doall 19 | (for [i (range 20) 20 | :let [mass (+ 0.1 (rand 3.9))]] 21 | (mover [0.0 0.0] mass))))] 22 | (swap! movers (constantly ms)))) 23 | 24 | (defn step-mover [m] 25 | (-> (mover/apply-force m [0.01 0.0]) ;; wind 26 | (mover/apply-massless-force [0.0 0.1]) ;; gravity 27 | (mover/update) 28 | (mover/check-edges WIDTH HEIGHT))) 29 | 30 | (defn draw [] 31 | (qc/background 255) 32 | (let [stepped-movers (map step-mover @movers)] 33 | (dorun 34 | (map mover/display stepped-movers)) 35 | (swap! movers (constantly stepped-movers)))) 36 | 37 | (defn run [] 38 | (qc/defsketch forces-many-realgravity 39 | :title "Forces: Many w/ Real Gravity" 40 | :setup setup 41 | :draw draw 42 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/walker/trail.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/RandomWalkTrail/Walker.pde 7 | ;; 8 | (ns natureofclojure.i-2.walker.trail 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 200.0) 12 | (def HEIGHT 200.0) 13 | (def walker (atom {:location [(/ WIDTH 2.0) 14 | (/ HEIGHT 2.0)] 15 | :history []})) ;; history is vec of vecs [[x y]..] 16 | 17 | (defn updated-walker [w] 18 | (let [vel [(- (rand 4) 2) (- (rand 4) 2)] 19 | loc (vec (map + (:location w) vel)) 20 | loc [(qc/constrain (first loc) 0 (- WIDTH 1)) 21 | (qc/constrain (second loc) 0 (- HEIGHT 1))] 22 | h (vec (take-last 1000 (conj (:history w) loc)))] 23 | (-> (update-in w [:location] (constantly loc)) 24 | (update-in [:history] (constantly h))))) 25 | 26 | (defn step-walker [w-atom] 27 | (swap! w-atom updated-walker)) 28 | 29 | (defn loc-x [w] 30 | (first (:location w))) 31 | 32 | (defn loc-y [w] 33 | (second (:location w))) 34 | 35 | (defn render-walker [w] 36 | (qc/stroke 0) 37 | (qc/fill 175) 38 | (qc/rect-mode :center) 39 | (qc/rect (loc-x w) (loc-y w) 16 16) 40 | 41 | (qc/begin-shape) 42 | (qc/stroke 0) 43 | (qc/no-fill) 44 | (dorun 45 | (map #(qc/vertex (first %) (second %)) (:history w))) 46 | (qc/end-shape)) -------------------------------------------------------------------------------- /src/natureofclojure/i_2/multiple_probability.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/MultipleProbability/MultipleProbability.pde 7 | ;; 8 | (ns natureofclojure.i-2.multiple-probability 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 200.0) 12 | (def HEIGHT 200.0) 13 | (def x (atom 0)) 14 | (def y (atom 0)) 15 | 16 | (defn setup [] 17 | (qc/background 0) 18 | (qc/smooth)) 19 | 20 | (defn draw [] 21 | ;; create an alpha blended background 22 | (qc/fill 0 1) 23 | (qc/rect 0 0 WIDTH HEIGHT) 24 | 25 | ;; probabilities for 3 different cases (these need to add up to 100% 26 | ;; since something always occurs here!) 27 | ;; 28 | ;; 15% chance of black (we don't actually need this line since it is 29 | ;; by definition, the "in all other cases" part of our else) 30 | (let [p1 0.05 ;; 5% chance of pure white occurring 31 | p2 (+ 0.80 p1) ;; 80% chance of gray occurring 32 | num (rand)] ;; pick a random number between 0 and 1 33 | (cond (< num p1) (qc/fill 255) 34 | (< num p2) (qc/fill 150) 35 | :else (qc/fill 0))) 36 | (qc/stroke 200) 37 | (qc/rect @x @y 10 10) 38 | 39 | (swap! x #(mod (+ % 10) WIDTH)) 40 | (when (= (int @x) 0) 41 | (swap! y #(mod (+ % 10) HEIGHT)))) 42 | 43 | (defn run [] 44 | (qc/defsketch multiple-probability 45 | :title "Multiple Probability" 46 | :setup setup 47 | :draw draw 48 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/i_3/gaussian2.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/Gaussian2/Gaussian2.pde 7 | ;; 8 | (ns natureofclojure.i-3.gaussian2 9 | (:import [java.util Random]) 10 | (:require [quil.core :as qc])) 11 | 12 | (def WIDTH 200) 13 | (def HEIGHT 200) 14 | 15 | ;; Create a Java random number generating object 16 | ;; (This is a mutable thing.) 17 | (def generator (new Random)) 18 | 19 | (defn setup [] 20 | (qc/background 0) 21 | (qc/smooth)) 22 | 23 | (defn scale-by-std [v sd mean] 24 | (+ (* v sd) mean)) 25 | 26 | (defn gauss-color [sd mean] 27 | (let [c (float (. generator nextGaussian))] 28 | (qc/constrain (scale-by-std c sd mean) 0 255))) 29 | 30 | (defn draw [] 31 | (qc/fill 0 1) 32 | (qc/rect 0 0 WIDTH HEIGHT) 33 | (qc/no-stroke) 34 | (let [sd 100 35 | mean 100 36 | r (gauss-color sd mean) 37 | g (gauss-color sd mean) 38 | b (gauss-color sd mean) 39 | sd-xy (/ WIDTH 10.0) 40 | mean-xy (/ WIDTH 2.0) 41 | x-loc (scale-by-std (float (. generator nextGaussian)) 42 | sd-xy 43 | mean-xy) 44 | y-loc (scale-by-std (float (. generator nextGaussian)) 45 | sd-xy 46 | mean-xy)] 47 | (qc/fill r g b) 48 | (qc/ellipse x-loc y-loc 8 8))) 49 | 50 | (defn run [] 51 | (qc/defsketch gaussian2 52 | :title "Gaussian 2" 53 | :setup setup 54 | :draw draw 55 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_1_what_is_a_force/mover/mouse_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch2-1-what-is-a-force.mover.mouse-acceleration 6 | (:require [quil.core :as qc]) 7 | (:use [natureofclojure.math.vector :as mv])) 8 | 9 | (def mover (atom {:location [] 10 | :velocity [] 11 | :top-speed 5.0})) 12 | 13 | (defn init-mover [width height m] 14 | (-> (assoc-in m [:location] [(/ width 2.0) (/ height 2.0)]) 15 | (assoc-in [:velocity] [0.0 0.0]))) 16 | 17 | (defn initialize [m-atom width height] 18 | (swap! m-atom (partial init-mover width height))) 19 | 20 | (defn update-mover [m] 21 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 22 | acc (mv/subtract mouse (:location m)) 23 | acc (mv/set-magnitude 0.1 acc)] 24 | (-> (update-in m [:velocity] #(mv/add % acc)) 25 | (update-in [:location] #(mv/add % (:velocity m))) 26 | (update-in [:velocity] #(mv/limit (:top-speed m) %))))) 27 | 28 | (defn update [m-atom] 29 | (swap! m-atom update-mover)) 30 | 31 | (defn display [m] 32 | (qc/stroke 0) 33 | (qc/stroke-weight 2) 34 | (qc/fill 127) 35 | (apply #(qc/ellipse %1 %2 48 48) (:location m))) 36 | 37 | (defn check-edges [m-atom width height] 38 | (let [loc (:location @m-atom) 39 | x (first loc) 40 | y (second loc)] 41 | (cond (> x width) (swap! m-atom assoc-in [:location] [0 y]) 42 | (< x 0) (swap! m-atom assoc-in [:location] [width y]) 43 | (> y height) (swap! m-atom assoc-in [:location] [x 0]) 44 | (< y 0) (swap! m-atom assoc-in [:location] [x height])))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_4_friction_force/forces_friction.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_4_forces_friction/NOC_2_4_forces_friction.pde 7 | ;; 8 | (ns natureofclojure.ch2-4-friction-force.forces-friction 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.ch2-4-friction-force.mover :as mover] 11 | [natureofclojure.math.vector :as mv])) 12 | 13 | (def WIDTH 383.0) 14 | (def HEIGHT 200.0) 15 | (def movers (atom [])) 16 | 17 | (defn setup [] 18 | (let [ms (vec 19 | (doall 20 | (for [i (range 20) 21 | :let [mass (+ 1.0 (rand 3.0))]] 22 | (mover [0.0 0.0] mass))))] 23 | (swap! movers (constantly ms)))) 24 | 25 | (defn friction [m] 26 | (let [c 0.05 27 | v (:velocity m)] 28 | (if (= (mv/magnitude v) 0.0) 29 | [0.0 0.0] 30 | (->> (mv/multiply -1.0 v) 31 | (mv/normalize) 32 | (mv/multiply c))))) 33 | 34 | (defn step-mover [m] 35 | (-> (mover/apply-force m (friction m)) ;; friction 36 | (mover/apply-force [0.01 0.0]) ;; wind 37 | (mover/apply-massless-force [0.0 0.1]) ;; gravity 38 | (mover/update) 39 | (mover/check-edges WIDTH HEIGHT))) 40 | 41 | (defn draw [] 42 | (qc/background 255) 43 | (let [stepped-movers (map step-mover @movers)] 44 | (dorun 45 | (map mover/display stepped-movers)) 46 | (swap! movers (constantly stepped-movers)))) 47 | 48 | (defn run [] 49 | (qc/defsketch forces-friction 50 | :title "Forces Friction" 51 | :setup setup 52 | :draw draw 53 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_5_vectors_acceleration/mover/random_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_9_motion101_acceleration/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch1-5-vectors-acceleration.mover.random-acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (def mover (atom {:location [] 13 | :velocity [] 14 | :top-speed 6.0})) 15 | 16 | (defn init-mover [width height m] 17 | (-> (assoc-in m [:location] [(/ width 2.0) (/ height 2.0)]) 18 | (assoc-in [:velocity] [0.0 0.0]))) 19 | 20 | (defn initialize [m-atom width height] 21 | (swap! m-atom (partial init-mover width height))) 22 | 23 | (defn update-mover [m] 24 | (let [acc (mv/multiply 2.0 (mv/random-2d))] 25 | (-> (update-in m [:velocity] #(mv/add % acc)) 26 | (update-in [:velocity] #(mv/limit (:top-speed m) %)) 27 | (update-in [:location] #(mv/add % (:velocity m)))))) 28 | 29 | (defn update [m-atom] 30 | (swap! m-atom update-mover)) 31 | 32 | (defn display [m] 33 | (qc/stroke 0) 34 | (qc/stroke-weight 2) 35 | (qc/fill 127) 36 | (apply #(qc/ellipse %1 %2 48 48) (:location m))) 37 | 38 | (defn check-edges [m-atom width height] 39 | (let [loc (:location @m-atom) 40 | x (first loc) 41 | y (second loc)] 42 | (cond (> x width) (swap! m-atom assoc-in [:location] [0 y]) 43 | (< x 0) (swap! m-atom assoc-in [:location] [width y]) 44 | (> y height) (swap! m-atom assoc-in [:location] [x 0]) 45 | (< y 0) (swap! m-atom assoc-in [:location] [x height])))) -------------------------------------------------------------------------------- /src/natureofclojure/ch1_5_vectors_acceleration/mover/acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_8_motion101_acceleration/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch1-5-vectors-acceleration.mover.acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (def mover (atom {:location [] 13 | :velocity [] 14 | :acceleration [] 15 | :top-speed 10.0})) 16 | 17 | (defn init-mover [width height m] 18 | (-> (assoc-in m [:location] [(/ width 2.0) (/ height 2.0)]) 19 | (assoc-in [:velocity] [0.0 0.0]) 20 | (assoc-in [:acceleration] [-0.001 0.01]))) 21 | 22 | (defn initialize [m-atom width height] 23 | (swap! m-atom (partial init-mover width height))) 24 | 25 | (defn update-mover [m] 26 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 27 | (update-in [:velocity] #(mv/limit (:top-speed m) %)) 28 | (update-in [:location] #(mv/add % (:velocity m))))) 29 | 30 | (defn update [m-atom] 31 | (swap! m-atom update-mover)) 32 | 33 | (defn display [m] 34 | (qc/stroke 0) 35 | (qc/stroke-weight 2) 36 | (qc/fill 127) 37 | (apply #(qc/ellipse %1 %2 48 48) (:location m))) 38 | 39 | (defn check-edges [m-atom width height] 40 | (let [loc (:location @m-atom) 41 | x (first loc) 42 | y (second loc)] 43 | (cond (> x width) (swap! m-atom assoc-in [:location] [0 y]) 44 | (< x 0) (swap! m-atom assoc-in [:location] [width y]) 45 | (> y height) (swap! m-atom assoc-in [:location] [x 0]) 46 | (< y 0) (swap! m-atom assoc-in [:location] [x height])))) -------------------------------------------------------------------------------- /src/natureofclojure/ch6_5_dot_product/simple_scalar_projection.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/chp6_agents/SimpleScalarProjection/SimpleScalarProjection.pde 7 | ;; 8 | (ns natureofclojure.ch6-5-dot-product.simple-scalar-projection 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fv])) 13 | 14 | (defn setup [] 15 | {}) 16 | 17 | (defn update [state] 18 | state) 19 | 20 | (defn scalar-projection [p a b] 21 | (let [ap (fv/- p a) 22 | ab (fv/- b a) 23 | ab-unit (fv/normalize ab) 24 | shadow (fv/* (fv/dot ap ab-unit) ab-unit)] 25 | (fv/+ a shadow))) 26 | 27 | (defn draw [state] 28 | (q/background 255) 29 | (let [a (fv/fvec 20 300) 30 | [a-x a-y] (fv/x-y a) 31 | b (fv/fvec 500 250) 32 | [b-x b-y] (fv/x-y b) 33 | mouse (fv/fvec (q/mouse-x) (q/mouse-y)) 34 | [m-x m-y] (fv/x-y mouse)] 35 | (q/stroke 0) 36 | (q/stroke-weight 2) 37 | (q/line a-x a-y b-x b-y) 38 | (q/line a-x a-y m-x m-y) 39 | (q/fill 0) 40 | (q/ellipse a-x a-y 8 8) 41 | (q/ellipse b-x b-y 8 8) 42 | (q/ellipse m-x m-y 8 8) 43 | (let [norm (scalar-projection mouse a b) 44 | [norm-x norm-y] (fv/x-y norm)] 45 | (q/stroke 50) 46 | (q/stroke-weight 1) 47 | (q/line m-x m-y norm-x norm-y) 48 | 49 | (q/no-stroke) 50 | (q/fill 255 0 0) 51 | (q/ellipse norm-x norm-y 16 16)))) 52 | 53 | (q/defsketch quil-workflow 54 | :title "Vectors: The Dot Product" 55 | :size [640 360] 56 | :setup setup 57 | :update update 58 | :draw draw 59 | :middleware [m/fun-mode]) 60 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/attraction.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_6_attraction/NOC_2_6_attraction.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.attraction 9 | (:require [quil.core :as qc] 10 | [natureofclojure.ch2-6-gravitational-attraction.mover :as mover] 11 | [natureofclojure.ch2-6-gravitational-attraction.attractor :as attractor])) 12 | 13 | (def WIDTH 640.0) 14 | (def HEIGHT 360.0) 15 | (def movers (atom [])) 16 | (def attractor (atom nil)) 17 | 18 | (defn reset-movers! [] 19 | (let [ms (vec 20 | (doall 21 | (for [i (range 1) 22 | :let [mass (+ 1.0 (rand 3.0))]] 23 | (mover/mover [1.0 0.0] [(rand WIDTH) (rand HEIGHT)] mass))))] 24 | (swap! movers (constantly ms)))) 25 | 26 | (defn setup [] 27 | (reset-movers!) 28 | (swap! attractor (constantly 29 | (attractor/attractor [(/ WIDTH 2.0) (/ HEIGHT 2.0)])))) 30 | 31 | (defn step-mover [m] 32 | (let [attractive-force (attractor/attract @attractor m)] 33 | (-> (mover/apply-force m attractive-force) 34 | (mover/update)))) 35 | 36 | (defn draw [] 37 | (qc/background 255) 38 | (let [stepped-movers (map step-mover @movers)] 39 | (dorun 40 | (map mover/display stepped-movers)) 41 | (attractor/display @attractor) 42 | (swap! movers (constantly stepped-movers)))) 43 | 44 | (defn mouse-pressed [] 45 | (reset-movers!)) 46 | 47 | (defn run [] 48 | (qc/defsketch gravitational-attraction 49 | :title "Gravitational Attraction" 50 | :setup setup 51 | :draw draw 52 | :size [WIDTH HEIGHT] 53 | :mouse-pressed mouse-pressed)) 54 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_5_drag_force/liquid.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_5_fluidresistance/Liquid.pde 7 | ;; 8 | (ns natureofclojure.ch2-5-drag-force.liquid 9 | (:require [quil.core :as qc] 10 | [clojure.math.numeric-tower :as math] 11 | [natureofclojure.math.vector :as mv])) 12 | 13 | (defn init [origin size c liq] 14 | (-> (assoc-in liq [:origin] origin) 15 | (assoc-in [:size] size) 16 | (assoc-in [:c] c))) 17 | 18 | (defn liquid 19 | ([] 20 | {:origin [] 21 | :size [] 22 | :c 0.03}) 23 | ([origin size c] 24 | (init origin size c (liquid)))) 25 | 26 | (defn origin-x [liq] 27 | (first (:origin liq))) 28 | 29 | (defn origin-y [liq] 30 | (second (:origin liq))) 31 | 32 | (defn size-w [liq] 33 | (first (:size liq))) 34 | 35 | (defn size-h [liq] 36 | (second (:size liq))) 37 | 38 | (defn contains? [liq location] 39 | (let [m-location location 40 | m-x (first location) 41 | m-y (second location) 42 | x (origin-x liq) 43 | y (origin-y liq) 44 | w (size-w liq) 45 | h (size-h liq)] 46 | (and (> m-x x) 47 | (< m-x (+ x w)) 48 | (> m-y y) 49 | (< m-y (+ y h))))) 50 | 51 | (defn drag [liq v] 52 | (let [speed (mv/magnitude v)] 53 | (if (= speed 0.0) 54 | [0.0 0.0] 55 | (let [c (:c liq) 56 | drag-magnitude (* c (math/expt speed 2)) 57 | drag-force (mv/multiply -1.0 v) 58 | n (mv/normalize drag-force)] 59 | (mv/multiply drag-magnitude n))))) 60 | 61 | (defn display [liq] 62 | (qc/no-stroke) 63 | (qc/fill 50) 64 | (qc/rect (origin-x liq) (origin-y liq) 65 | (size-w liq) (size-h liq))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/attraction_many.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_7_attraction_many/NOC_2_7_attraction_many.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.attraction-many 9 | (:require [quil.core :as qc] 10 | [natureofclojure.ch2-6-gravitational-attraction.mover :as mover] 11 | [natureofclojure.ch2-6-gravitational-attraction.attractor :as attractor])) 12 | 13 | (def WIDTH 800.0) 14 | (def HEIGHT 200.0) 15 | (def movers (atom [])) 16 | (def attractor (atom nil)) 17 | 18 | (defn reset-movers! [] 19 | (let [ms (vec 20 | (doall 21 | (for [i (range 10) 22 | :let [mass (+ 0.1 (rand 1.9))]] 23 | (mover/mover [1.0 0.0] [(rand WIDTH) (rand HEIGHT)] mass))))] 24 | (swap! movers (constantly ms)))) 25 | 26 | (defn setup [] 27 | (reset-movers!) 28 | (swap! attractor (constantly 29 | (attractor/attractor [(/ WIDTH 2.0) (/ HEIGHT 2.0)])))) 30 | 31 | (defn step-mover [m] 32 | (let [attractive-force (attractor/attract @attractor m)] 33 | (-> (mover/apply-force m attractive-force) 34 | (mover/update)))) 35 | 36 | (defn draw [] 37 | (qc/background 255) 38 | (let [stepped-movers (map step-mover @movers)] 39 | (dorun 40 | (map mover/display stepped-movers)) 41 | (attractor/display @attractor) 42 | (swap! movers (constantly stepped-movers)))) 43 | 44 | (defn mouse-pressed [] 45 | (reset-movers!)) 46 | 47 | (defn run [] 48 | (qc/defsketch gravitational-attraction-many 49 | :title "Gravitational Attraction: Many" 50 | :setup setup 51 | :draw draw 52 | :size [WIDTH HEIGHT] 53 | :mouse-pressed mouse-pressed)) 54 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_5_dot_product/angle_between.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/chp6_agents/Exercise_6_09_AngleBetween/Exercise_6_09_AngleBetween.pde 7 | ;; 8 | (ns natureofclojure.ch6-5-dot-product.angle-between 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fv])) 13 | 14 | (defn setup [] 15 | {}) 16 | 17 | (defn update [state] 18 | state) 19 | 20 | (defn draw-vector [v loc scayl] 21 | (let [arrow-size 6.0 22 | [loc-x loc-y] (fv/x-y loc)] 23 | (q/with-translation [loc-x loc-y] 24 | (q/with-rotation [(fv/heading v)] 25 | (let [len (* (fv/magnitude v) scayl)] 26 | (q/line 0 0 len 0) 27 | (q/line len 0 (- len arrow-size) (/ arrow-size 2.0)) 28 | (q/line len 0 (- len arrow-size) (/ arrow-size -2.0))))))) 29 | 30 | (defn draw-text [v x-axis] 31 | (q/fill 0) 32 | (let [theta (fv/angle-between v x-axis) 33 | degrees (* theta (/ 180.0 Math/PI))] 34 | (q/text (str (int degrees) " degrees\n" theta " radians") 10 160))) 35 | 36 | (defn draw [state] 37 | (q/background 255) 38 | (q/stroke 0) 39 | (q/stroke-weight 2) 40 | (let [mouse-loc (fv/fvec (q/mouse-x) (q/mouse-y)) 41 | center-loc (fv/fvec (/ (q/width) 2.0) (/ (q/height) 2.0)) 42 | v (-> (fv/- mouse-loc center-loc) 43 | (fv/normalize) 44 | (fv/* 75.0)) 45 | x-axis (fv/fvec 75.0 0.0)] 46 | (draw-vector v center-loc 1.0) 47 | (draw-vector x-axis center-loc 1.0) 48 | (draw-text v x-axis))) 49 | 50 | (q/defsketch quil-workflow 51 | :title "Vectors: The Dot Product" 52 | :size [640 360] 53 | :setup setup 54 | :update update 55 | :draw draw 56 | :middleware [m/fun-mode]) 57 | -------------------------------------------------------------------------------- /src/natureofclojure/ch1_6_vectors_acceleration_towards_mouse/mover/mouse_acceleration.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp1_vectors/NOC_1_10_motion101_acceleration/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch1-6-vectors-acceleration-towards-mouse.mover.mouse-acceleration 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (def mover (atom {:location [] 13 | :velocity [] 14 | :top-speed 5.0})) 15 | 16 | (defn init-mover [width height m] 17 | (-> (assoc-in m [:location] [(/ width 2.0) (/ height 2.0)]) 18 | (assoc-in [:velocity] [0.0 0.0]))) 19 | 20 | (defn initialize [m-atom width height] 21 | (swap! m-atom (partial init-mover width height))) 22 | 23 | (defn update-mover [m] 24 | (let [mouse [(qc/mouse-x) (qc/mouse-y)] 25 | acc (mv/subtract mouse (:location m)) 26 | acc (mv/normalize acc) 27 | acc (mv/multiply 0.2 acc)] 28 | (-> (update-in m [:velocity] #(mv/add % acc)) 29 | (update-in [:velocity] #(mv/limit (:top-speed m) %)) 30 | (update-in [:location] #(mv/add % (:velocity m)))))) 31 | 32 | (defn update [m-atom] 33 | (swap! m-atom update-mover)) 34 | 35 | (defn display [m] 36 | (qc/stroke 0) 37 | (qc/stroke-weight 2) 38 | (qc/fill 127) 39 | (apply #(qc/ellipse %1 %2 48 48) (:location m))) 40 | 41 | (defn check-edges [m-atom width height] 42 | (let [loc (:location @m-atom) 43 | x (first loc) 44 | y (second loc)] 45 | (cond (> x width) (swap! m-atom assoc-in [:location] [0 y]) 46 | (< x 0) (swap! m-atom assoc-in [:location] [width y]) 47 | (> y height) (swap! m-atom assoc-in [:location] [x 0]) 48 | (< y 0) (swap! m-atom assoc-in [:location] [x height])))) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_1_angles_and_angular_motion/forces_angular_motion.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_02_forces_angular_motion/NOC_3_02_forces_angular_motion.pde 7 | ;; 8 | (ns natureofclojure.ch3-1-angles-and-angular-motion.forces-angular-motion 9 | (:require [quil.core :as qc] 10 | [natureofclojure.ch3-1-angles-and-angular-motion.mover :as mover] 11 | [natureofclojure.ch3-1-angles-and-angular-motion.attractor :as attractor])) 12 | 13 | (def WIDTH 800.0) 14 | (def HEIGHT 200.0) 15 | (def movers (atom [])) 16 | (def attractor (atom nil)) 17 | 18 | (defn reset-movers! [] 19 | (let [ms (vec 20 | (doall 21 | (for [i (range 10) 22 | :let [mass (+ 0.1 (rand 1.9))]] 23 | (mover/mover [1.0 0.0] [(rand WIDTH) (rand HEIGHT)] mass))))] 24 | (swap! movers (constantly ms)))) 25 | 26 | (defn setup [] 27 | (reset-movers!) 28 | (swap! attractor (constantly 29 | (attractor/attractor [(/ WIDTH 2.0) (/ HEIGHT 2.0)])))) 30 | 31 | (defn step-mover [m] 32 | (let [attractive-force (attractor/attract @attractor m)] 33 | (-> (mover/apply-force m attractive-force) 34 | (mover/update)))) 35 | 36 | (defn draw [] 37 | (qc/background 0) 38 | (let [stepped-movers (map step-mover @movers)] 39 | (dorun 40 | (map mover/display stepped-movers)) 41 | (attractor/display @attractor) 42 | (swap! movers (constantly stepped-movers)))) 43 | 44 | (defn mouse-pressed [] 45 | (reset-movers!)) 46 | 47 | (defn run [] 48 | (qc/defsketch forces-angular-motion 49 | :title "Forces: Angular Motion" 50 | :setup setup 51 | :draw draw 52 | :size [WIDTH HEIGHT] 53 | :mouse-pressed mouse-pressed)) 54 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_5_drag_force/mouse_drag.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch2-5-drag-force.mouse-drag 6 | (:require [quil.core :as qc] 7 | [clojure.math.numeric-tower :as math]) 8 | (:use [natureofclojure.ch2-5-drag-force.mover :as mover] 9 | [natureofclojure.math.vector :as mv])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | (def movers (atom [])) 14 | (def mouse-pressed? (atom false)) 15 | 16 | (defn setup [] 17 | (let [ms (vec 18 | (doall 19 | (for [i (range 20) 20 | :let [mass (+ 1.0 (rand 3.0))]] 21 | (mover [0.0 0.0] mass))))] 22 | (swap! movers (constantly ms)))) 23 | 24 | (defn drag [m] 25 | (let [c -0.03 26 | v (:velocity m) 27 | speed (mv/magnitude v)] 28 | (if (= speed 0.0) 29 | [0.0 0.0] 30 | (->> (mv/normalize v) 31 | (mv/multiply (* c (math/expt speed 2))))))) 32 | 33 | (defn step-mover [m] 34 | (let [m (if @mouse-pressed? 35 | (mover/apply-force m (drag m)) ;; drag 36 | m)] 37 | (-> (mover/apply-force m [0.01 0.0]) ;; wind 38 | (mover/apply-massless-force [0.0 0.1]) ;; gravity 39 | (mover/update) 40 | (mover/check-edges WIDTH HEIGHT)))) 41 | 42 | (defn draw [] 43 | (qc/background 255) 44 | (let [stepped-movers (map step-mover @movers)] 45 | (dorun 46 | (map mover/display stepped-movers)) 47 | (swap! movers (constantly stepped-movers)))) 48 | 49 | (defn mouse-pressed [] 50 | (swap! mouse-pressed? (constantly true))) 51 | 52 | (defn mouse-released [] 53 | (swap! mouse-pressed? (constantly false))) 54 | 55 | (defn run [] 56 | (qc/defsketch forces-friction 57 | :title "Forces Friction" 58 | :setup setup 59 | :draw draw 60 | :size [WIDTH HEIGHT] 61 | :mouse-pressed mouse-pressed 62 | :mouse-released mouse-released)) -------------------------------------------------------------------------------- /src/natureofclojure/i_4/monte_carlo_distribution.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/introduction/MonteCarloDistribution/MonteCarloDistribution.pde 7 | ;; 8 | (ns natureofclojure.i-4.monte-carlo-distribution 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 200) 12 | (def HEIGHT 200) 13 | (def vals (atom (vec (replicate WIDTH 0)))) 14 | (def norms (atom (vec (replicate WIDTH 0)))) 15 | 16 | (defn setup []) 17 | 18 | (defn monte-carlo 19 | "An algorithm for picking a random number based on monte carlo method 20 | Here probability is determined by formula y = x" 21 | [] 22 | (let [r1 (rand) 23 | r2 (rand) 24 | y (* r1 r1)] ;; y = x * x (change for different results) 25 | ;; if r2 is valid, we'll use this one 26 | (if (< r2 y) 27 | r1 28 | (recur)))) 29 | 30 | (defn pick-random-values 31 | "Get random values" 32 | [] 33 | (let [n (monte-carlo) 34 | index (int (* n WIDTH))] 35 | (swap! vals update-in [index] inc))) 36 | 37 | (defn normalize-values 38 | "Normalize vals if necessary" 39 | [] 40 | (let [max-y (apply max @vals) 41 | is-normalized? (> max-y HEIGHT)] 42 | (dorun 43 | (for [x (range WIDTH) 44 | :let [v (nth @vals x) 45 | y (if is-normalized? 46 | (* HEIGHT (/ v max-y)) 47 | v)]] 48 | (swap! norms update-in [x] (constantly y)))))) 49 | 50 | (defn draw [] 51 | (qc/background 100) 52 | (qc/stroke 255) 53 | (pick-random-values) 54 | (normalize-values) 55 | 56 | ;; Draw line: 57 | (dorun 58 | (for [x (range 0 WIDTH)] 59 | (qc/line x HEIGHT x (- HEIGHT (nth @norms x)))))) 60 | 61 | (defn run [] 62 | (qc/defsketch monte-carlo-distribution 63 | :title "Monte Carlo Distribution" 64 | :setup setup 65 | :draw draw 66 | :size [WIDTH HEIGHT])) -------------------------------------------------------------------------------- /src/natureofclojure/math/fast_vector.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.math.fast-vector 6 | (:require 7 | [clojure.core.matrix :as matrix] 8 | [clojure.core.matrix.operators :as mop])) 9 | 10 | (defn setup-vectorz [] 11 | (matrix/set-current-implementation :vectorz)) 12 | (setup-vectorz) 13 | 14 | ;; Implementation Specific: 15 | (defn distance [a b] 16 | (matrix/distance a b)) 17 | 18 | (defn magnitude-squared [v] 19 | (.magnitudeSquared v)) 20 | 21 | (defn magnitude [v] 22 | (.magnitude v)) 23 | 24 | (defn x-y [v] 25 | (.toList v)) 26 | 27 | (defn dot [a b] 28 | (matrix/dot a b)) 29 | 30 | (defn normalize [v] 31 | (matrix/normalise v)) 32 | 33 | (defn fvec [x y] 34 | (matrix/array [x y])) 35 | 36 | 37 | ;; Operators: 38 | 39 | (defn + [a b] 40 | (mop/+ a b)) 41 | 42 | (defn - [a b] 43 | (mop/- a b)) 44 | 45 | (defn * [a b] 46 | (mop/* a b)) 47 | 48 | (defn / [a b] 49 | (mop// a b)) 50 | 51 | 52 | ;; Convenience: 53 | 54 | (defn angle-between 55 | "Computes the angle (in radians) between two vectors." 56 | [a b] 57 | (let [dot-product (dot a b)] 58 | (Math/acos (/ dot-product 59 | (* (magnitude a) (magnitude b)))))) 60 | 61 | (defn from-angle [theta] 62 | (fvec (Math/cos theta) (Math/sin theta))) 63 | 64 | (defn limit [v max-mag] 65 | (if (> (magnitude-squared v) (clojure.core/* max-mag max-mag)) 66 | (* (normalize v) max-mag) 67 | v)) 68 | 69 | (defn heading [v] 70 | (let [[x y] (x-y v)] 71 | (* -1.0 (Math/atan2 (* -1.0 y) x)))) 72 | 73 | (defn scalar-projection 74 | "Computes the scalar projection of vector p on vector from a to b." 75 | [p a b] 76 | (let [ap (- p a) 77 | ab (- b a) 78 | ab-unit (normalize ab) 79 | shadow (* (dot ap ab-unit) ab-unit)] 80 | (+ a shadow))) 81 | 82 | (defn set-mag 83 | "Create a vector with the magnitude given by len." 84 | [v len] 85 | (-> (normalize v) 86 | (* len))) 87 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/mutual_attraction.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_8_mutual_attraction/NOC_2_8_mutual_attraction.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.mutual-attraction 9 | (:require [quil.core :as qc] 10 | [natureofclojure.ch2-6-gravitational-attraction.mutual-mover :as mover])) 11 | 12 | (def WIDTH 1200.0) 13 | (def HEIGHT 800.0) 14 | (def movers (atom [])) 15 | 16 | (defn reset-movers! [] 17 | (let [ms (vec 18 | (doall 19 | (for [i (range 20) 20 | :let [mass (+ 0.1 (rand 1.9))]] 21 | (mover/mover [0.0 0.0] [(rand WIDTH) (rand HEIGHT)] mass))))] 22 | (swap! movers (constantly ms)))) 23 | 24 | (defn setup [] 25 | (qc/smooth) 26 | (reset-movers!)) 27 | 28 | (defn attract-movers [] 29 | (let [cnt (count @movers) 30 | g 0.4] 31 | (dorun 32 | (for [i (range cnt) 33 | j (range cnt) 34 | :when (not= (int i) (int j)) 35 | :let [m (nth @movers i) 36 | f (mover/attract (nth @movers j) (nth @movers i) g)]] 37 | (let [mvrs (assoc-in @movers [i] (mover/apply-force m f))] 38 | (swap! movers (constantly mvrs))))))) 39 | 40 | (defn draw [] 41 | (qc/background 255) 42 | (attract-movers) 43 | (let [stepped-movers (vec 44 | (doall 45 | (map mover/update @movers)))] 46 | (dorun 47 | (map mover/display stepped-movers)) 48 | (swap! movers (constantly stepped-movers)) 49 | ) 50 | ) 51 | 52 | (defn mouse-pressed [] 53 | (reset-movers!)) 54 | 55 | (defn run [] 56 | (qc/defsketch gravitational-attraction-mutual 57 | :title "Gravitational Attraction: Mutual" 58 | :setup setup 59 | :draw draw 60 | :size [WIDTH HEIGHT] 61 | :mouse-pressed mouse-pressed)) 62 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_5_drag_force/fluid_resistance.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_5_fluidresistance/NOC_2_5_fluidresistance.pde 7 | ;; 8 | (ns natureofclojure.ch2-5-drag-force.fluid-resistance 9 | (:require [quil.core :as qc] 10 | [natureofclojure.ch2-5-drag-force.mover :as mover] 11 | [natureofclojure.ch2-5-drag-force.liquid :as liquid])) 12 | 13 | (def WIDTH 800.0) 14 | (def HEIGHT 200.0) 15 | (def movers (atom [])) 16 | (def liq (atom (liquid/liquid [0 (/ HEIGHT 2.0)] 17 | [WIDTH (/ HEIGHT 2.0)] 18 | 0.1))) 19 | 20 | (defn reset-movers! [] 21 | (let [ms (vec 22 | (doall 23 | (for [i (range 20) 24 | :let [mass (+ 1.0 (rand 3.0))]] 25 | (mover/mover [(rand WIDTH) 0.0] mass))))] 26 | (swap! movers (constantly ms)))) 27 | 28 | (defn setup [] 29 | (reset-movers!)) 30 | 31 | (defn step-mover [m] 32 | (let [drag-force (if (liquid/contains? @liq (:location m)) 33 | (liquid/drag @liq (:velocity m)) 34 | [0.0 0.0])] 35 | (-> (mover/apply-force m drag-force) ;; friction 36 | (mover/apply-force [0.01 0.0]) ;; wind 37 | (mover/apply-massless-force [0.0 0.1]) ;; gravity 38 | (mover/update) 39 | (mover/check-edges WIDTH HEIGHT)))) 40 | 41 | (defn draw [] 42 | (qc/background 255) 43 | (liquid/display @liq) 44 | (let [stepped-movers (map step-mover @movers)] 45 | (dorun 46 | (map mover/display stepped-movers)) 47 | (swap! movers (constantly stepped-movers)))) 48 | 49 | (defn mouse-pressed [] 50 | (reset-movers!)) 51 | 52 | (defn run [] 53 | (qc/defsketch fluid-resistance 54 | :title "Fluid Resistance" 55 | :setup setup 56 | :draw draw 57 | :size [WIDTH HEIGHT] 58 | :mouse-pressed mouse-pressed)) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_3_simple_harmonic_motion/oscillating_objects.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_06_simple_harmonic_motion/NOC_3_06_simple_harmonic_motion.pde 7 | ;; 8 | (ns natureofclojure.ch3-3-simple-harmonic-motion.oscillating-objects 9 | (:require [quil.core :as qc])) 10 | 11 | (def WIDTH 800.0) 12 | (def HEIGHT 200.0) 13 | (def NUM_OSC 10) 14 | 15 | ;; Oscillator is a map, that looks like this: 16 | ;; { :angle [x y] :velocity [x y] :amplitude [x y] } 17 | (def oscillators (atom [])) 18 | (defn gen-osc 19 | [] 20 | {:angle [0 0] 21 | :velocity [(- (rand 0.1) 0.05), (- (rand 0.1) 0.05)] 22 | :amplitude [(qc/random 20 (/ WIDTH 2.0)) (qc/random (/ HEIGHT 2.0))]}) 23 | (defn gen-all-osc 24 | [] 25 | (vec 26 | (doall 27 | (for [i (range NUM_OSC)] 28 | (gen-osc))))) 29 | 30 | (defn oscillate 31 | [osc] 32 | (let [velocity (:velocity osc) 33 | angle (:angle osc) 34 | new-angle (map + velocity angle)] 35 | (assoc-in osc [:angle] new-angle))) 36 | 37 | (defn display-osc 38 | [osc] 39 | (let [angle (:angle osc) 40 | amplitude (:amplitude osc) 41 | x (* (Math/sin (first angle)) (first amplitude)) 42 | y (* (Math/sin (second angle)) (second amplitude))] 43 | (qc/push-matrix) 44 | (qc/translate (/ WIDTH 2.0) (/ HEIGHT 2.0)) 45 | (qc/stroke 0) 46 | (qc/stroke-weight 2) 47 | (qc/fill 127 127) 48 | (qc/line 0 0 x y) 49 | (qc/ellipse x y 32 32) 50 | (qc/pop-matrix))) 51 | 52 | (defn setup [] 53 | (qc/smooth) 54 | (swap! oscillators #(do 55 | % 56 | (gen-all-osc)))) 57 | 58 | (defn draw [] 59 | (qc/background 255) 60 | (dorun 61 | (map #(-> % 62 | (oscillate) 63 | (display-osc)) @oscillators))) 64 | 65 | (defn run [] 66 | (qc/defsketch oscillating-objects 67 | :title "Oscillating Objects" 68 | :setup setup 69 | :draw draw 70 | :size [WIDTH HEIGHT])) 71 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_4_flow_field_following/core.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://vimeo.com/channels/natureofcode/63101109 7 | ;; 8 | (ns natureofclojure.ch6-4-flow-field-following 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec])) 13 | 14 | (def RESOLUTION 10) 15 | (def FLOW-SCALE (- RESOLUTION 2)) 16 | (def T 0.0) 17 | (def T-OFFSET 0.05) 18 | (def XY-OFFSET 0.1) 19 | 20 | (defn f-theta [x y t] 21 | (let [x-off (* XY-OFFSET x) 22 | y-off (* XY-OFFSET y)] 23 | (q/map-range (q/noise x-off y-off t) 24 | 0.0 1.0 25 | 0.0 q/TWO-PI))) 26 | 27 | (defn f-vec [x y t] 28 | (fvec/from-angle (f-theta x y t))) 29 | 30 | (defn init-flow-field [] 31 | (into {} (for [x (range (quot (q/width) RESOLUTION)) 32 | y (range (quot (q/height) RESOLUTION))] 33 | [[x y] (f-vec x y T)]))) 34 | 35 | (defn setup [] 36 | (q/frame-rate 60) 37 | {:time T 38 | :flow (init-flow-field)}) 39 | 40 | (defn update-flow-field [t flow] 41 | (let [update-vec (fn [[[x y] v]] 42 | [[x y] (f-vec x y t)])] 43 | (into {} (doall 44 | (map update-vec flow))))) 45 | 46 | (defn update [state] 47 | (let [{:keys [time]} state 48 | time (+ T-OFFSET time)] 49 | (-> state 50 | (assoc-in [:time] time) 51 | (update-in [:flow] (partial update-flow-field time))))) 52 | 53 | (defn draw-flow-field [flow] 54 | (doseq [[key v] flow] 55 | (let [[x y] (map #(+ (/ RESOLUTION 2.0) (* RESOLUTION %)) key) 56 | len (* FLOW-SCALE (fvec/magnitude v))] 57 | (q/with-translation [x y] 58 | (q/with-rotation [(fvec/heading v)] 59 | (q/line 0 0 len 0)))))) 60 | 61 | (defn draw [state] 62 | (q/background 0) 63 | (q/stroke 255 55 141 255) 64 | (q/stroke-weight 0.5) 65 | (draw-flow-field (:flow state))) 66 | 67 | (q/defsketch quil-workflow 68 | :title "Steering Behavior: Flow Field Following" 69 | :size [800 600] 70 | :setup setup 71 | :update update 72 | :draw draw 73 | :middleware [m/fun-mode]) 74 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_7_grouping/separation.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/NOC_6_07_Separation 7 | ;; 8 | (ns natureofclojure.ch6-7-grouping.separation 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-7-grouping.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def VEHICLE-R 30.0) 19 | (def VEHICLE-D (* 2 VEHICLE-R)) 20 | 21 | (def SEPARATION-DIST VEHICLE-D) 22 | 23 | (defn random-vehicle 24 | ([] 25 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 26 | ([x y] 27 | {:location (fvec/fvec x y) 28 | :velocity (fvec/fvec 0.0 0.0) 29 | :acceleration (fvec/fvec 0.0 0.0) 30 | :max-speed 3.0 31 | :max-force 0.2})) 32 | 33 | (def VEHICLES 34 | (vec 35 | (for [_ (range 10)] 36 | (random-vehicle)))) 37 | 38 | (defn setup [] 39 | {:vehicles VEHICLES}) 40 | 41 | (defn update-vehicles [vehicles] 42 | (doall (map #(->> % 43 | (beh/separate SEPARATION-DIST vehicles) 44 | (beh/move-vehicle) 45 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 46 | vehicles))) 47 | 48 | (defn update [{:keys [vehicles] :as state}] 49 | (-> state 50 | (update-in [:vehicles] update-vehicles))) 51 | 52 | (defn draw-vehicle 53 | [{:keys [location]}] 54 | (let [[x y] (fvec/x-y location)] 55 | (q/with-translation [x y] 56 | (q/ellipse 0 0 VEHICLE-D VEHICLE-D)))) 57 | 58 | (defn draw [state] 59 | (q/background 0) 60 | (let [{:keys [vehicles]} state] 61 | (q/stroke 0.5) 62 | (q/fill 180) 63 | (doall (map draw-vehicle vehicles)))) 64 | 65 | (defn mouse-dragged [state event] 66 | (let [{:keys [x y]} event] 67 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 68 | 69 | (q/defsketch quil-workflow 70 | :title "Group Steering Behaviors: Separation" 71 | :size [SIZE-W SIZE-H] 72 | :setup setup 73 | :update update 74 | :draw draw 75 | :mouse-dragged mouse-dragged 76 | :middleware [m/fun-mode]) 77 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_7_grouping/alignment.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/Alignment 7 | ;; 8 | (ns natureofclojure.ch6-7-grouping.alignment 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-7-grouping.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def VEHICLE-R 5.0) 19 | (def VEHICLE-D (* 2 VEHICLE-R)) 20 | 21 | (def NEIGHBOR-DIST 30.0) 22 | 23 | (defn random-vehicle 24 | ([] 25 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 26 | ([x y] 27 | {:location (fvec/fvec x y) 28 | :velocity (fvec/fvec (- (rand 80.0) 40.0) 29 | (- (rand 80.0) 40.0)) 30 | :acceleration (fvec/fvec 0.0 0.0) 31 | :max-speed (+ 4.0 (rand 4.0)) 32 | :max-force (+ 0.2 (rand 0.2))})) 33 | 34 | (def VEHICLES 35 | (vec 36 | (for [_ (range 10)] 37 | (random-vehicle)))) 38 | 39 | (defn setup [] 40 | {:vehicles VEHICLES}) 41 | 42 | (defn update-vehicles [vehicles] 43 | (doall (map #(->> % 44 | (beh/align NEIGHBOR-DIST vehicles) 45 | (beh/move-vehicle) 46 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 47 | vehicles))) 48 | 49 | (defn update [{:keys [vehicles] :as state}] 50 | (-> state 51 | (update-in [:vehicles] update-vehicles))) 52 | 53 | (defn draw-vehicle 54 | [{:keys [location]}] 55 | (let [[x y] (fvec/x-y location)] 56 | (q/with-translation [x y] 57 | (q/ellipse 0 0 VEHICLE-D VEHICLE-D)))) 58 | 59 | (defn draw [state] 60 | (q/background 255) 61 | (let [{:keys [vehicles]} state] 62 | (q/fill 255 0 0) 63 | (doall (map draw-vehicle vehicles)))) 64 | 65 | (defn mouse-pressed [state event] 66 | (let [{:keys [x y]} event] 67 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 68 | 69 | (q/defsketch quil-workflow 70 | :title "Group Steering Behaviors: Alignment" 71 | :size [SIZE-W SIZE-H] 72 | :setup setup 73 | :update update 74 | :draw draw 75 | :mouse-pressed mouse-pressed 76 | :middleware [m/fun-mode]) 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # natureofclojure 2 | 3 | A bunch of Clojure [Quil](https://github.com/quil/quil "Quil") examples based on [Daniel Shiffman's Nature of Code video channel on Vimeo](https://vimeo.com/channels/natureofcode/ "Nature of Code videos"). 4 | 5 | [Check out the videos on Vimeo.](https://vimeo.com/channels/natureofcode/ "Nature of Code videos") 6 | Seriously, check them out, they're great. 7 | 8 | ## Caveat 9 | I'm probably going to base this on the videos, as opposed to the website/book. This is for no better reason than that I've read a lot of the book already and want to watch the videos now. 10 | 11 | Go [buy the book](http://natureofcode.com "Nature of Code book") if you haven't alreaddy. Seriously, [buy it](http://natureofcode.com "Nature of Code book"), it's the decent thing to do. 12 | 13 | ## Usage 14 | 15 | These sketches require the [Clojure Quil library](https://github.com/quil/quil "Quil"), for working with [Processing](http://processing.org "Processing"). 16 | 17 | Install dependencies in root dir: 18 | 19 | ```` 20 | $ cd path/to/natureofclojure 21 | $ lein deps 22 | ```` 23 | 24 | You can view these example sketches by running them from the repl. I use Emacs and the Cider nREPL. If you have [the same setup](https://gist.github.com/4698169 "My Clojure Emacs setup") you can just start a nREPL process and eval the sketch buffer. 25 | 26 | Starting with Chapter 3, part 4, I've started working with Quil Middleware and Functional mode. This is how you get it to run. 27 | ````clojure 28 | ;; go to buffer for the example you wish to run 29 | C-c M-j ;; M-x cider-jack-in 30 | C-c M-n ;; M-x cider-repl-set-ns (optional) 31 | M-x cider-eval-buffer ;; keybinding? 32 | 33 | ;; Make changes 34 | C-c C-e ;; M-x cider-eval-last-sexp 35 | ;; This hot-reloades your changes. 36 | ```` 37 | 38 | Helpful buffer commands for working with nREPL: 39 | ```` 40 | M-C-x (eval form under point in repl <-- allows live coding!!!) 41 | C-c C-z (switch to repl buffer) 42 | ```` 43 | See others at the [nREPL README](https://github.com/kingtim/nrepl.el "nREPL README"). 44 | 45 | ## License 46 | 47 | Copyright © 2014 [Pas de Chocolat, LLC](http://pasdechocolat.com/ "Awesome website") 48 | This work is licensed under a [Creative Commons Attribution-ShareAlike 2.0 Generic License](http://creativecommons.org/licenses/by-sa/2.0/ "Creative Commons Attribution-ShareAlike 2.0 Generic License"). 49 | 50 | -------------------------------------------------------------------------------- /src/natureofclojure/i_5/landscape.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.i-5.landscape 6 | (:require [quil.core :as qc])) 7 | 8 | (def WIDTH 800.0) 9 | (def HEIGHT 200.0) 10 | 11 | (def INITIAL-LANDSCAPE-WIDTH 800) 12 | (def INITIAL-LANDSCAPE-HEIGHT 400) 13 | (def INITIAL-Z-OFFSET 0.0) 14 | 15 | (defn initial-z-landscape [cols rows z-value] 16 | (apply merge 17 | (doall 18 | (for [x (range cols) 19 | y (range rows)] 20 | {[x y] z-value})))) 21 | 22 | (def landscape 23 | (atom {:size-cell 20.0 24 | :width INITIAL-LANDSCAPE-WIDTH 25 | :height INITIAL-LANDSCAPE-HEIGHT 26 | :z-off INITIAL-Z-OFFSET 27 | :z (initial-z-landscape INITIAL-LANDSCAPE-WIDTH 28 | INITIAL-LANDSCAPE-HEIGHT 29 | 0.0)})) 30 | 31 | (defn landscape-cols [ls] 32 | (/ (:width ls) (:size-cell ls))) 33 | 34 | (defn landscape-rows [ls] 35 | (/ (:height ls) (:size-cell ls))) 36 | 37 | (defn calculate-z [cols rows z-off] 38 | (apply merge 39 | (doall 40 | (for [x (range cols) 41 | y (range rows) 42 | :let [x-off (* 0.01 x) 43 | y-off (* 0.01 y)]] 44 | {[x y] (qc/map-range (qc/noise x-off y-off z-off) 0 1 -400 400)})))) 45 | 46 | (defn update-landscape-z [ls] 47 | (let [z (calculate-z (:width ls) 48 | (:height ls) 49 | (:z-off ls))] 50 | (-> (assoc-in ls [:z] z) 51 | (update-in [:z-off] #(+ % 0.01))))) 52 | 53 | (defn calculate! [ls-atom] 54 | (swap! ls-atom update-landscape-z)) 55 | 56 | (defn render [ls] 57 | (let [scl (:size-cell ls) 58 | w (:width ls) 59 | h (:height ls) 60 | z (:z ls)] 61 | (dorun 62 | (for [x (range (- w 1)) 63 | y (range (- h 1))] 64 | (do 65 | (qc/stroke 0) 66 | (qc/fill 100 100) 67 | 68 | (qc/push-matrix) 69 | (qc/begin-shape :quads) 70 | (qc/translate (- (* x scl) (/ w 2.0)) 71 | (- (* y scl) (/ h 2.0)) 72 | 0) 73 | (qc/vertex 0 0 (z [ x y])) 74 | (qc/vertex scl 0 (z [(inc x) y])) 75 | (qc/vertex scl scl (z [(inc x) (inc y)])) 76 | (qc/vertex 0 scl (z [ x (inc y)])) 77 | (qc/end-shape) 78 | (qc/pop-matrix)))))) -------------------------------------------------------------------------------- /src/natureofclojure/ch6_7_grouping/cohesion.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/NOC_6_07_Separation 7 | ;; and seeking from: 8 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/chp6_agents/NOC_6_08_SeparationAndSeek/Vehicle.pde 9 | ;; 10 | (ns natureofclojure.ch6-7-grouping.cohesion 11 | (:require 12 | [quil.core :as q] 13 | [quil.middleware :as m] 14 | [natureofclojure.math.fast-vector :as fvec] 15 | [natureofclojure.ch6-7-grouping.behavior :as beh])) 16 | 17 | (def SIZE-W 800.0) 18 | (def SIZE-H 600.0) 19 | 20 | (def VEHICLE-R 10.0) 21 | (def VEHICLE-D (* 2 VEHICLE-R)) 22 | 23 | (def COHESION-DIST 20) 24 | 25 | (defn random-v-comp [] 26 | (let [r (+ 20.0 (rand 40.0))] 27 | (if (> (rand 1.0) 0.5) 28 | (* -1 r) 29 | r))) 30 | 31 | (defn random-vehicle 32 | ([] 33 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 34 | ([x y] 35 | {:location (fvec/fvec x y) 36 | :velocity (fvec/fvec (random-v-comp) 37 | (random-v-comp)) 38 | :acceleration (fvec/fvec 0.0 0.0) 39 | :max-speed 3.0 40 | :max-force 0.2})) 41 | 42 | (def VEHICLES 43 | (vec 44 | (for [_ (range 10)] 45 | (random-vehicle)))) 46 | 47 | (defn setup [] 48 | {:vehicles VEHICLES}) 49 | 50 | (defn update-vehicles [vehicles] 51 | (doall (map #(->> % 52 | (beh/glom COHESION-DIST vehicles) 53 | (beh/move-vehicle) 54 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 55 | vehicles))) 56 | 57 | (defn update [{:keys [vehicles] :as state}] 58 | (-> state 59 | (update-in [:vehicles] update-vehicles))) 60 | 61 | (defn draw-vehicle 62 | [{:keys [location]}] 63 | (let [[x y] (fvec/x-y location)] 64 | (q/with-translation [x y] 65 | (q/ellipse 0 0 VEHICLE-D VEHICLE-D)))) 66 | 67 | (defn draw [state] 68 | (q/background 0) 69 | (let [{:keys [vehicles]} state] 70 | (q/stroke 0.5) 71 | (q/fill 180) 72 | (doall (map draw-vehicle vehicles)))) 73 | 74 | (defn mouse-dragged [state event] 75 | (let [{:keys [x y]} event] 76 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 77 | 78 | (q/defsketch quil-workflow 79 | :title "Group Steering Behaviors: Separation" 80 | :size [SIZE-W SIZE-H] 81 | :setup setup 82 | :update update 83 | :draw draw 84 | :mouse-dragged mouse-dragged 85 | :middleware [m/fun-mode]) 86 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_2_applying_a_force/mover_forces.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_1_forces/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-2-applying-a-force.mover-forces 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:velocity] [0.0 0.0]) 15 | (assoc-in [:acceleration] [0.0 0.0]) 16 | (assoc-in [:mass] mass))) 17 | 18 | (defn mover 19 | ([] 20 | {:location [] 21 | :velocity [] 22 | :acceleration [] 23 | :mass 1.0}) 24 | ([location] 25 | (mover location 1.0)) 26 | ([location mass] 27 | (init-mover location mass (mover)))) 28 | 29 | (defn apply-force [m f] 30 | (let [f (mv/divide f (:mass m))] 31 | (update-in m [:acceleration] #(mv/add % f)))) 32 | 33 | (defn update [m] 34 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 35 | (update-in [:velocity] #(mv/limit 5.0 %)) 36 | (update-in [:location] #(mv/add % (:velocity m))) 37 | (assoc-in [:acceleration] [0.0 0.0]))) 38 | 39 | (defn display [m] 40 | (qc/stroke 0) 41 | (qc/stroke-weight 2) 42 | (qc/fill 127) 43 | (apply #(qc/ellipse %1 %2 48 48) (:location m))) 44 | 45 | (defn loc-x [m] 46 | (first (:location m))) 47 | 48 | (defn loc-y [m] 49 | (second (:location m))) 50 | 51 | (defn vel-x [m] 52 | (first (:velocity m))) 53 | 54 | (defn vel-y [m] 55 | (second (:velocity m))) 56 | 57 | (defn bounce-x-right [m width] 58 | (-> (assoc-in m [:location] [width 59 | (loc-y m)]) 60 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 61 | (vel-y m)]))) 62 | 63 | (defn bounce-x-left [m] 64 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 65 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 66 | (vel-y m)]))) 67 | 68 | (defn bounce-y-bottom [m height] 69 | (-> (assoc-in m [:location] [(loc-x m) 70 | height]) 71 | (assoc-in [:velocity] [(vel-x m) 72 | (* -1.0 (vel-y m))]))) 73 | 74 | (defn check-edges [m width height] 75 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 76 | (< (loc-x m) 0) (bounce-x-left m) 77 | :else m)] 78 | (if (> (loc-y m) height) 79 | (bounce-y-bottom m height) 80 | m))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_5_drag_force/mover.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_5_fluidresistance/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-5-drag-force.mover 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:velocity] [0.0 0.0]) 15 | (assoc-in [:acceleration] [0.0 0.0]) 16 | (assoc-in [:mass] mass))) 17 | 18 | (defn mover 19 | ([] 20 | {:location [] 21 | :velocity [] 22 | :acceleration [] 23 | :mass 1.0}) 24 | ([location] 25 | (mover location 1.0)) 26 | ([location mass] 27 | (init-mover location mass (mover)))) 28 | 29 | (defn apply-massless-force [m f] 30 | (update-in m [:acceleration] #(mv/add % f))) 31 | 32 | (defn apply-force [m f] 33 | (let [f (mv/divide f (:mass m))] 34 | (apply-massless-force m f))) 35 | 36 | (defn update [m] 37 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 38 | (update-in [:velocity] #(mv/limit 6.0 %)) 39 | (update-in [:location] #(mv/add % (:velocity m))) 40 | (assoc-in [:acceleration] [0.0 0.0]))) 41 | 42 | (defn display [m] 43 | (qc/stroke 0) 44 | (qc/stroke-weight 2) 45 | (qc/fill 127 200) 46 | (let [d (* 16.0 (:mass m))] 47 | (apply #(qc/ellipse %1 %2 d d) (:location m)))) 48 | 49 | (defn loc-x [m] 50 | (first (:location m))) 51 | 52 | (defn loc-y [m] 53 | (second (:location m))) 54 | 55 | (defn vel-x [m] 56 | (first (:velocity m))) 57 | 58 | (defn vel-y [m] 59 | (second (:velocity m))) 60 | 61 | (defn bounce-x-right [m width] 62 | (-> (assoc-in m [:location] [width 63 | (loc-y m)]) 64 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 65 | (vel-y m)]))) 66 | 67 | (defn bounce-x-left [m] 68 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 69 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 70 | (vel-y m)]))) 71 | 72 | (defn bounce-y-bottom [m height] 73 | (-> (assoc-in m [:location] [(loc-x m) 74 | height]) 75 | (assoc-in [:velocity] [(vel-x m) 76 | (* -0.9 (vel-y m))]))) 77 | 78 | (defn check-edges [m width height] 79 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 80 | (< (loc-x m) 0) (bounce-x-left m) 81 | :else m)] 82 | (if (> (loc-y m) height) 83 | (bounce-y-bottom m height) 84 | m))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_4_friction_force/mover.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_4_forces_friction/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-4-friction-force.mover 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:velocity] [0.0 0.0]) 15 | (assoc-in [:acceleration] [0.0 0.0]) 16 | (assoc-in [:mass] mass))) 17 | 18 | (defn mover 19 | ([] 20 | {:location [] 21 | :velocity [] 22 | :acceleration [] 23 | :mass 1.0}) 24 | ([location] 25 | (mover location 1.0)) 26 | ([location mass] 27 | (init-mover location mass (mover)))) 28 | 29 | (defn apply-massless-force [m f] 30 | (update-in m [:acceleration] #(mv/add % f))) 31 | 32 | (defn apply-force [m f] 33 | (let [f (mv/divide f (:mass m))] 34 | (apply-massless-force m f))) 35 | 36 | (defn update [m] 37 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 38 | (update-in [:velocity] #(mv/limit 6.0 %)) 39 | (update-in [:location] #(mv/add % (:velocity m))) 40 | (assoc-in [:acceleration] [0.0 0.0]))) 41 | 42 | (defn display [m] 43 | (qc/stroke 0) 44 | (qc/stroke-weight 2) 45 | (qc/fill 127 100) 46 | (let [d (* 16.0 (:mass m))] 47 | (apply #(qc/ellipse %1 %2 d d) (:location m)))) 48 | 49 | (defn loc-x [m] 50 | (first (:location m))) 51 | 52 | (defn loc-y [m] 53 | (second (:location m))) 54 | 55 | (defn vel-x [m] 56 | (first (:velocity m))) 57 | 58 | (defn vel-y [m] 59 | (second (:velocity m))) 60 | 61 | (defn bounce-x-right [m width] 62 | (-> (assoc-in m [:location] [width 63 | (loc-y m)]) 64 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 65 | (vel-y m)]))) 66 | 67 | (defn bounce-x-left [m] 68 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 69 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 70 | (vel-y m)]))) 71 | 72 | (defn bounce-y-bottom [m height] 73 | (-> (assoc-in m [:location] [(loc-x m) 74 | height]) 75 | (assoc-in [:velocity] [(vel-x m) 76 | (* -1.0 (vel-y m))]))) 77 | 78 | (defn check-edges [m width height] 79 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 80 | (< (loc-x m) 0) (bounce-x-left m) 81 | :else m)] 82 | (if (> (loc-y m) height) 83 | (bounce-y-bottom m height) 84 | m))) -------------------------------------------------------------------------------- /src/natureofclojure/ch2_3_simulating_mass/mover_forces.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_3_forces_many_realgravity/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-3-simulating-mass.mover-forces 9 | (:require [quil.core :as qc]) 10 | (:use [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover [location mass m] 13 | (-> (assoc-in m [:location] location) 14 | (assoc-in [:velocity] [0.0 0.0]) 15 | (assoc-in [:acceleration] [0.0 0.0]) 16 | (assoc-in [:mass] mass))) 17 | 18 | (defn mover 19 | ([] 20 | {:location [] 21 | :velocity [] 22 | :acceleration [] 23 | :mass 1.0}) 24 | ([location] 25 | (mover location 1.0)) 26 | ([location mass] 27 | (init-mover location mass (mover)))) 28 | 29 | (defn apply-massless-force [m f] 30 | (update-in m [:acceleration] #(mv/add % f))) 31 | 32 | (defn apply-force [m f] 33 | (let [f (mv/divide f (:mass m))] 34 | (apply-massless-force m f))) 35 | 36 | (defn update [m] 37 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 38 | (update-in [:velocity] #(mv/limit 6.0 %)) 39 | (update-in [:location] #(mv/add % (:velocity m))) 40 | (assoc-in [:acceleration] [0.0 0.0]))) 41 | 42 | (defn display [m] 43 | (qc/stroke 0) 44 | (qc/stroke-weight 2) 45 | (qc/fill 127 100) 46 | (let [d (* 16.0 (:mass m))] 47 | (apply #(qc/ellipse %1 %2 d d) (:location m)))) 48 | 49 | (defn loc-x [m] 50 | (first (:location m))) 51 | 52 | (defn loc-y [m] 53 | (second (:location m))) 54 | 55 | (defn vel-x [m] 56 | (first (:velocity m))) 57 | 58 | (defn vel-y [m] 59 | (second (:velocity m))) 60 | 61 | (defn bounce-x-right [m width] 62 | (-> (assoc-in m [:location] [width 63 | (loc-y m)]) 64 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 65 | (vel-y m)]))) 66 | 67 | (defn bounce-x-left [m] 68 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 69 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 70 | (vel-y m)]))) 71 | 72 | (defn bounce-y-bottom [m height] 73 | (-> (assoc-in m [:location] [(loc-x m) 74 | height]) 75 | (assoc-in [:velocity] [(vel-x m) 76 | (* -1.0 (vel-y m))]))) 77 | 78 | (defn check-edges [m width height] 79 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 80 | (< (loc-x m) 0) (bounce-x-left m) 81 | :else m)] 82 | (if (> (loc-y m) height) 83 | (bounce-y-bottom m height) 84 | m))) -------------------------------------------------------------------------------- /src/natureofclojure/ch3_4_pendulum_simulation/core.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp3_oscillation/NOC_3_10_PendulumExample 7 | ;; 8 | (ns natureofclojure.ch3-4-pendulum-simulation.core 9 | (:require [quil.core :as q] 10 | [quil.middleware :as m])) 11 | 12 | (defn angular-acc 13 | "Calculate angular acceleration of a body in gravity" 14 | [gravity radius angle] 15 | (* -1 (/ gravity radius) (Math/sin angle))) 16 | 17 | (def G 0.4) 18 | (def LEN 175) 19 | (def START-ANGLE (/ Math/PI 4.0)) 20 | (def START-ANG-VEL 0.0) 21 | (def DAMPING 0.995) 22 | 23 | (defn setup [] 24 | (q/frame-rate 30) 25 | (q/color-mode :hsb) 26 | {:len LEN 27 | :ang-vel START-ANG-VEL 28 | :angle START-ANGLE 29 | :g G 30 | :dragging false}) 31 | 32 | (defn update [state] 33 | (if (:dragging state) 34 | (let [origin-x (/ (q/width) 2.0) 35 | origin-y 0.0 36 | diff-x (- origin-x (q/mouse-x)) 37 | diff-y (- origin-y (q/mouse-y)) 38 | a (- (Math/atan2 (* -1.0 diff-y) diff-x) 39 | (/ Math/PI 2.0))] 40 | (-> state 41 | (assoc-in [:angle] a))) 42 | (let [{:keys [angle ang-vel g len]} state 43 | ang-acc (angular-acc g len angle) 44 | ang-vel (* DAMPING (+ ang-vel ang-acc))] 45 | (-> state 46 | (update-in [:ang-vel] (constantly ang-vel)) 47 | (update-in [:angle] #(+ ang-vel %)))))) 48 | 49 | (defn draw-ball 50 | [x y] 51 | (q/stroke 255) 52 | (q/stroke-weight 2) 53 | (q/line 0, 0, x, y) 54 | (q/no-stroke) 55 | (q/fill 255 255 255) 56 | (q/ellipse x y 50 50)) 57 | 58 | (defn loc [len angle] 59 | [(* len (Math/sin angle)) 60 | (* len (Math/cos angle))]) 61 | 62 | (defn draw [state] 63 | (q/background 0) 64 | (let [{:keys [len angle]} state 65 | [x y] (loc len angle)] 66 | (q/with-translation [(/ (q/width) 2) 67 | 0] 68 | (draw-ball x y)))) 69 | 70 | (defn mouse-pressed [state event] 71 | (let [{:keys [len angle]} state 72 | [x y] (loc len angle) 73 | d (q/dist (- (q/mouse-x) (/ (q/width) 2.0)) (q/mouse-y) x y)] 74 | (-> state 75 | (assoc-in [:dragging] (< d len))))) 76 | 77 | (defn mouse-released [state event] 78 | (-> state 79 | (assoc-in [:ang-vel] 0.0) 80 | (assoc-in [:dragging] false))) 81 | 82 | (q/defsketch quil-workflow 83 | :title "pendulum example" 84 | :size [800 600] 85 | :setup setup 86 | :update update 87 | :draw draw 88 | :mouse-pressed mouse-pressed 89 | :mouse-released mouse-released 90 | :middleware [m/fun-mode]) 91 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/mutual_mover.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_8_mutual_attraction/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.mutual-mover 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (def colors [[200,215,80], 13 | [190,90,212], 14 | [204,72,47], 15 | [130,187,205], 16 | [89,48,92], 17 | [64,92,59], 18 | [115,214,164], 19 | [218,154,57], 20 | [110,119,201], 21 | [93,47,35], 22 | [202,154,187], 23 | [199,70,103], 24 | [107,220,76], 25 | [197,129,106], 26 | [197,197,158], 27 | [91,156,67], 28 | [139,128,54], 29 | [75,87,102], 30 | [196,75,152]]) 31 | 32 | (defn init-mover 33 | ([location mass m] 34 | (init-mover [0.0 0.0] location mass m)) 35 | ([velocity location mass m] 36 | (-> (assoc-in m [:location] location) 37 | (assoc-in [:velocity] velocity) 38 | (assoc-in [:acceleration] [0.0 0.0]) 39 | (assoc-in [:mass] mass) 40 | (assoc-in [:color-rgb] (nth colors (rand (count colors))))))) 41 | 42 | (defn mover 43 | ([] 44 | {:location [] 45 | :velocity [] 46 | :acceleration [] 47 | :mass 1.0}) 48 | ([location] 49 | (mover location 1.0)) 50 | ([location mass] 51 | (init-mover location mass (mover))) 52 | ([velocity location mass] 53 | (init-mover velocity location mass (mover)))) 54 | 55 | (defn attract [m other-mover g] 56 | (let [f (mv/subtract (:location m) (:location other-mover)) 57 | d (mv/magnitude f) 58 | d (qc/constrain d 5.0 25.0) 59 | n (mv/normalize f) 60 | strength (/ (* g (:mass m) (:mass other-mover)) (* d d))] 61 | (mv/multiply strength n))) 62 | 63 | (defn apply-massless-force [m f] 64 | (update-in m [:acceleration] #(mv/add % f))) 65 | 66 | (defn apply-force [m f] 67 | (let [f (mv/divide f (:mass m))] 68 | (apply-massless-force m f))) 69 | 70 | (defn update [m] 71 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 72 | (update-in [:velocity] #(mv/limit 6.0 %)) 73 | (update-in [:location] #(mv/add % (:velocity m))) 74 | (assoc-in [:acceleration] [0.0 0.0]))) 75 | 76 | (defn display [m] 77 | (qc/no-stroke) 78 | (apply #(qc/fill %1 %2 %3 200) (:color-rgb m)) 79 | (let [d (* 16.0 (:mass m))] 80 | (apply #(qc/ellipse %1 %2 d d) (:location m)))) 81 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_6_steering_behaviors/behavior.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch6-6-steering-behaviors.behavior 6 | (:require 7 | [quil.core :as q] 8 | [quil.middleware :as m] 9 | [natureofclojure.math.fast-vector :as fvec])) 10 | 11 | (defn steer [target vehicle] 12 | (let [{:keys [location max-force max-speed velocity]} vehicle 13 | desired (fvec/- target location) 14 | desired (fvec/* (fvec/normalize desired) max-speed) 15 | steer-f (fvec/limit (fvec/- desired velocity) max-force)] 16 | (update-in vehicle [:acceleration] #(fvec/+ % steer-f)))) 17 | 18 | (defn clamped-normal [normal-point a b] 19 | (let [[n-x _] (fvec/x-y normal-point) 20 | [a-x _] (fvec/x-y a) 21 | [b-x _] (fvec/x-y b)] 22 | (if (and (<= a-x n-x) 23 | (<= n-x b-x)) 24 | normal-point 25 | b))) 26 | 27 | (defn follow [path path-r vehicle] 28 | (let [;; Predict location in future 29 | predict (fvec/* (fvec/normalize (:velocity vehicle)) 50) 30 | predict-loc (fvec/+ (:location vehicle) predict) 31 | 32 | ;; Look at line segment 33 | [a b] path 34 | 35 | ;; Get normal point to that line 36 | normal-point (fvec/scalar-projection predict-loc a b) 37 | normal-point (clamped-normal normal-point a b) 38 | 39 | ;; Find target point a little ahead of the normal 40 | dir (fvec/* (fvec/normalize (fvec/- b a)) 10) 41 | target (fvec/+ dir normal-point) 42 | 43 | ;; Only steer if outside path radius 44 | d (fvec/distance predict-loc normal-point)] 45 | (if (> d path-r) 46 | (steer target vehicle) 47 | vehicle))) 48 | 49 | (defn borders 50 | ([path-start path-end vehicle-r vehicle] 51 | "Assumes multiple path segments (at least two)." 52 | (let [{:keys [location]} vehicle 53 | [x y] (fvec/x-y location) 54 | [start-x start-y] (fvec/x-y path-start) 55 | [end-x end-y] (fvec/x-y path-end)] 56 | (if (> x (+ end-x vehicle-r)) 57 | (assoc-in vehicle [:location] 58 | (fvec/fvec (- start-x vehicle-r) 59 | (+ start-y (- y end-y)))) 60 | vehicle))) 61 | ([path vehicle-r vehicle] 62 | "Assumes there is only one path segment." 63 | (borders (first path) (last path) vehicle-r vehicle))) 64 | 65 | (defn move-vehicle [vehicle] 66 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 67 | v (fvec/limit v (:max-speed vehicle)) 68 | loc (fvec/+ v (:location vehicle))] 69 | (-> vehicle 70 | (assoc-in [:velocity] v) 71 | (assoc-in [:location] loc) 72 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 73 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_2_steering_behaviors_seek/core.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://vimeo.com/channels/natureofcode/63089177 7 | ;; 8 | (ns natureofclojure.ch6-2-steering-behaviors-seek 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec])) 13 | 14 | (def VEHICLE-R 5.0) 15 | (def VEHICLES 16 | [{:location (fvec/fvec 20 20) 17 | :velocity (fvec/fvec 0 0) 18 | :acceleration (fvec/fvec 0 0) 19 | :max-speed 4 20 | :max-force 0.1}]) 21 | 22 | (defn setup [] 23 | {:x 0 :y 0 24 | :vehicles VEHICLES}) 25 | 26 | (defn seek-vehicle [vehicle] 27 | (let [target (fvec/fvec (q/mouse-x) (q/mouse-y)) 28 | desired (fvec/- target (:location vehicle)) 29 | desired (fvec/normalize desired) 30 | desired (fvec/* desired (:max-speed vehicle)) 31 | steer (fvec/- desired (:velocity vehicle)) 32 | steer (fvec/limit steer (:max-force vehicle))] 33 | (-> vehicle 34 | (update-in [:acceleration] #(fvec/+ % steer))))) 35 | 36 | (defn update-vehicle [vehicle] 37 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 38 | v (fvec/limit v (:max-speed vehicle)) 39 | loc (fvec/+ v (:location vehicle))] 40 | (-> vehicle 41 | (assoc-in [:velocity] v) 42 | (assoc-in [:location] loc) 43 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 44 | 45 | (defn update [state] 46 | (-> state 47 | (update-in [:vehicles] #(doall (map (comp update-vehicle 48 | seek-vehicle) %))))) 49 | 50 | (defn draw-vehicle 51 | [vehicle] 52 | (let [{:keys [location velocity]} vehicle 53 | [x y] (fvec/x-y location) 54 | theta (+ (/ Math/PI 2.0) 55 | (fvec/heading velocity))] 56 | (q/with-translation [x y] 57 | (q/with-rotation [theta] 58 | (q/begin-shape) 59 | (q/vertex 0 (* -2.0 VEHICLE-R)) 60 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 61 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 62 | (q/end-shape :close))))) 63 | 64 | (defn draw [state] 65 | (q/background 0) 66 | (let [{:keys [x y]} state] 67 | (q/fill 255) 68 | (q/with-translation [x y] 69 | (q/ellipse 0 0 20 20)) 70 | (q/fill 255 0 0) 71 | (doall (map draw-vehicle (:vehicles state))))) 72 | 73 | (defn mouse-moved [state event] 74 | (-> state 75 | (assoc-in [:x] (:x event)) 76 | (assoc-in [:y] (:y event)))) 77 | 78 | (q/defsketch quil-workflow 79 | :title "Steering Behavior: Seek" 80 | :size [800 600] 81 | :setup setup 82 | :update update 83 | :draw draw 84 | :mouse-moved mouse-moved 85 | :middleware [m/fun-mode]) 86 | -------------------------------------------------------------------------------- /src/natureofclojure/ch2_6_gravitational_attraction/mover.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp2_forces/NOC_2_6_attraction/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch2-6-gravitational-attraction.mover 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover 13 | ([location mass m] 14 | (init-mover [0.0 0.0] location mass m)) 15 | ([velocity location mass m] 16 | (-> (assoc-in m [:location] location) 17 | (assoc-in [:velocity] velocity) 18 | (assoc-in [:acceleration] [0.0 0.0]) 19 | (assoc-in [:mass] mass)))) 20 | 21 | (defn mover 22 | ([] 23 | {:location [] 24 | :velocity [] 25 | :acceleration [] 26 | :mass 1.0}) 27 | ([location] 28 | (mover location 1.0)) 29 | ([location mass] 30 | (init-mover location mass (mover))) 31 | ([velocity location mass] 32 | (init-mover velocity location mass (mover)))) 33 | 34 | (defn apply-massless-force [m f] 35 | (update-in m [:acceleration] #(mv/add % f))) 36 | 37 | (defn apply-force [m f] 38 | (let [f (mv/divide f (:mass m))] 39 | (apply-massless-force m f))) 40 | 41 | (defn update [m] 42 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 43 | (update-in [:velocity] #(mv/limit 6.0 %)) 44 | (update-in [:location] #(mv/add % (:velocity m))) 45 | (assoc-in [:acceleration] [0.0 0.0]))) 46 | 47 | (defn display [m] 48 | (qc/stroke 0) 49 | (qc/stroke-weight 2) 50 | (qc/fill 127 200) 51 | (let [d (* 16.0 (:mass m))] 52 | (apply #(qc/ellipse %1 %2 d d) (:location m)))) 53 | 54 | (defn loc-x [m] 55 | (first (:location m))) 56 | 57 | (defn loc-y [m] 58 | (second (:location m))) 59 | 60 | (defn vel-x [m] 61 | (first (:velocity m))) 62 | 63 | (defn vel-y [m] 64 | (second (:velocity m))) 65 | 66 | (defn bounce-x-right [m width] 67 | (-> (assoc-in m [:location] [width 68 | (loc-y m)]) 69 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 70 | (vel-y m)]))) 71 | 72 | (defn bounce-x-left [m] 73 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 74 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 75 | (vel-y m)]))) 76 | 77 | (defn bounce-y-bottom [m height] 78 | (-> (assoc-in m [:location] [(loc-x m) 79 | height]) 80 | (assoc-in [:velocity] [(vel-x m) 81 | (* -0.9 (vel-y m))]))) 82 | 83 | (defn check-edges [m width height] 84 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 85 | (< (loc-x m) 0) (bounce-x-left m) 86 | :else m)] 87 | (if (> (loc-y m) height) 88 | (bounce-y-bottom m height) 89 | m))) 90 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_8_flocking/separation_seek.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/NOC_6_08_SeparationAndSeek 7 | ;; 8 | (ns natureofclojure.ch6-8-flocking.separation-seek 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-8-flocking.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def VEHICLE-R 10.0) 19 | (def VEHICLE-D (* 2 VEHICLE-R)) 20 | 21 | (def SEPARATION-DIST 30) 22 | 23 | (defn random-v-comp [] 24 | (let [r (+ 20.0 (rand 40.0))] 25 | (if (> (rand 1.0) 0.5) 26 | (* -1 r) 27 | r))) 28 | 29 | (defn random-vehicle 30 | ([] 31 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 32 | ([x y] 33 | {:location (fvec/fvec x y) 34 | :velocity (fvec/fvec (random-v-comp) 35 | (random-v-comp)) 36 | :acceleration (fvec/fvec 0.0 0.0) 37 | :max-speed 3.0 38 | :max-force 0.2})) 39 | 40 | (def VEHICLES 41 | (vec 42 | (for [_ (range 10)] 43 | (random-vehicle)))) 44 | 45 | (defn setup [] 46 | {:vehicles VEHICLES}) 47 | 48 | (defn apply-behaviors [all vehicle] 49 | (let [sep-factor 2.0 50 | seek-factor 1.0 51 | sep-force (fvec/* 52 | (beh/separate SEPARATION-DIST all vehicle) 53 | sep-factor) 54 | target (fvec/fvec (q/mouse-x) (q/mouse-y)) 55 | seek-force (fvec/* 56 | (beh/seek target vehicle) 57 | seek-factor)] 58 | (-> vehicle 59 | (beh/apply-force sep-force) 60 | (beh/apply-force seek-force)))) 61 | 62 | (defn update-vehicles [vehicles] 63 | (doall (map #(->> % 64 | (apply-behaviors vehicles) 65 | (beh/move-vehicle) 66 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 67 | vehicles))) 68 | 69 | (defn update [{:keys [vehicles] :as state}] 70 | (-> state 71 | (update-in [:vehicles] update-vehicles))) 72 | 73 | (defn draw-vehicle 74 | [{:keys [location]}] 75 | (let [[x y] (fvec/x-y location)] 76 | (q/with-translation [x y] 77 | (q/ellipse 0 0 VEHICLE-D VEHICLE-D)))) 78 | 79 | (defn draw [state] 80 | (q/background 0) 81 | (let [{:keys [vehicles]} state] 82 | (q/stroke 0.5) 83 | (q/fill 180) 84 | (doall (map draw-vehicle vehicles)))) 85 | 86 | (defn mouse-dragged [state event] 87 | (let [{:keys [x y]} event] 88 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 89 | 90 | (q/defsketch quil-workflow 91 | :title "Flocking: Separation & Seek" 92 | :size [SIZE-W SIZE-H] 93 | :setup setup 94 | :update update 95 | :draw draw 96 | :mouse-dragged mouse-dragged 97 | :middleware [m/fun-mode]) 98 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_3_steering_behaviors_arrive/core.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://vimeo.com/channels/natureofcode/63089177 7 | ;; 8 | (ns natureofclojure.ch6-3-steering-behaviors-arrive 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec])) 13 | 14 | (def TARGET-R 100.0) 15 | (def VEHICLE-R 5.0) 16 | (def VEHICLES 17 | [{:location (fvec/fvec 20 20) 18 | :velocity (fvec/fvec 0 0) 19 | :acceleration (fvec/fvec 0 0) 20 | :max-speed 4 21 | :max-force 0.1}]) 22 | 23 | (defn setup [] 24 | {:x 0 :y 0 25 | :vehicles VEHICLES}) 26 | 27 | (defn arrive-vehicle [vehicle] 28 | (let [target (fvec/fvec (q/mouse-x) (q/mouse-y)) 29 | desired (fvec/- target (:location vehicle)) 30 | d (fvec/magnitude desired) 31 | desired (fvec/normalize desired) 32 | desired (if (< d TARGET-R) 33 | (fvec/* desired (q/map-range d 0 TARGET-R 0 (:max-speed vehicle))) 34 | (fvec/* desired (:max-speed vehicle))) 35 | steer (fvec/- desired (:velocity vehicle)) 36 | steer (fvec/limit steer (:max-force vehicle))] 37 | (-> vehicle 38 | (update-in [:acceleration] #(fvec/+ % steer))))) 39 | 40 | (defn update-vehicle [vehicle] 41 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 42 | v (fvec/limit v (:max-speed vehicle)) 43 | loc (fvec/+ v (:location vehicle))] 44 | (-> vehicle 45 | (assoc-in [:velocity] v) 46 | (assoc-in [:location] loc) 47 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 48 | 49 | (defn update [state] 50 | (-> state 51 | (update-in [:vehicles] #(doall (map (comp update-vehicle 52 | arrive-vehicle) %))))) 53 | 54 | (defn draw-vehicle 55 | [vehicle] 56 | (let [{:keys [location velocity]} vehicle 57 | [x y] (fvec/x-y location) 58 | theta (+ (/ Math/PI 2.0) 59 | (fvec/heading velocity))] 60 | (q/with-translation [x y] 61 | (q/with-rotation [theta] 62 | (q/begin-shape) 63 | (q/vertex 0 (* -2.0 VEHICLE-R)) 64 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 65 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 66 | (q/end-shape :close))))) 67 | 68 | (defn draw [state] 69 | (q/background 0) 70 | (let [{:keys [x y]} state] 71 | (q/fill 255) 72 | (q/with-translation [x y] 73 | (q/ellipse 0 0 20 20)) 74 | (q/fill 255 0 0) 75 | (doall (map draw-vehicle (:vehicles state))))) 76 | 77 | (defn mouse-moved [state event] 78 | (-> state 79 | (assoc-in [:x] (:x event)) 80 | (assoc-in [:y] (:y event)))) 81 | 82 | (q/defsketch quil-workflow 83 | :title "Steering Behavior: Seek" 84 | :size [800 600] 85 | :setup setup 86 | :update update 87 | :draw draw 88 | :mouse-moved mouse-moved 89 | :middleware [m/fun-mode]) 90 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_6_steering_behaviors/path_following_simple.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; 7 | ;; 8 | (ns natureofclojure.ch6-6-steering-behaviors.path-following-simple 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-6-steering-behaviors.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def PATH-R 20.0) 19 | 20 | (def VEHICLE-R 5.0) 21 | 22 | (defn random-vehicle [x y] 23 | {:location (fvec/fvec x y) 24 | :velocity (fvec/fvec 0.0 0.0) 25 | :acceleration (fvec/fvec 0.0 0.0) 26 | :max-speed (+ 4.0 (rand 4.0)) 27 | :max-force (+ 0.2 (rand 0.2))}) 28 | 29 | (def VEHICLES 30 | [(random-vehicle (rand SIZE-W) (rand SIZE-H))]) 31 | 32 | (defn random-path [] 33 | [(fvec/fvec 0.0 (rand SIZE-H)) 34 | (fvec/fvec SIZE-W (rand SIZE-H))]) 35 | 36 | (def PATH (random-path)) 37 | 38 | (defn setup [] 39 | {:vehicles VEHICLES 40 | :path PATH}) 41 | 42 | (defn update-vehicles [path vehicles] 43 | (doall (map #(->> % 44 | (beh/follow path PATH-R) 45 | (beh/move-vehicle) 46 | (beh/borders path VEHICLE-R)) 47 | vehicles))) 48 | 49 | (defn update [{:keys [vehicles path] :as state}] 50 | (-> state 51 | (update-in [:vehicles] (partial update-vehicles path)))) 52 | 53 | (defn draw-vehicle 54 | [vehicle] 55 | (let [{:keys [location velocity]} vehicle 56 | [x y] (fvec/x-y location) 57 | theta (+ (/ Math/PI 2.0) 58 | (fvec/heading velocity))] 59 | (q/with-translation [x y] 60 | (q/with-rotation [theta] 61 | (q/begin-shape) 62 | (q/vertex 0 (* -2.0 VEHICLE-R)) 63 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 64 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 65 | (q/end-shape :close))))) 66 | 67 | (defn draw-path [path] 68 | (let [[a b] path 69 | [a-x a-y] (fvec/x-y a) 70 | [b-x b-y] (fvec/x-y b)] 71 | (q/no-stroke) 72 | (q/fill 200 255) 73 | (q/quad a-x (+ a-y PATH-R) a-x (- a-y PATH-R) b-x (- b-y PATH-R) b-x (+ b-y PATH-R)) 74 | (q/stroke 100) 75 | (q/stroke-weight 1) 76 | (q/line a-x a-y b-x b-y))) 77 | 78 | (defn draw [state] 79 | (q/background 255) 80 | (let [{:keys [path vehicles]} state] 81 | (q/fill 255) 82 | (draw-path path) 83 | (q/fill 255 0 0) 84 | (doall (map draw-vehicle vehicles)))) 85 | 86 | (defn key-pressed [state event] 87 | (assoc-in state [:path] (random-path))) 88 | 89 | (defn mouse-pressed [state event] 90 | (let [{:keys [x y]} event] 91 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 92 | 93 | (q/defsketch quil-workflow 94 | :title "Steering Behaviors: Simple Path Following" 95 | :size [SIZE-W SIZE-H] 96 | :setup setup 97 | :update update 98 | :draw draw 99 | :key-pressed key-pressed 100 | :mouse-pressed mouse-pressed 101 | :middleware [m/fun-mode]) 102 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_8_flocking/boids.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/NOC_6_09_Flocking 7 | ;; 8 | (ns natureofclojure.ch6-8-flocking.separation-seek 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-8-flocking.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def VEHICLE-R 4.0) 19 | 20 | (def SEPARATION-DIST 30) 21 | (def NEIGHBOR-DIST 100) 22 | (def GLOM-DIST 50) 23 | 24 | (defn random-v-comp [] 25 | (let [r (+ 20.0 (rand 40.0))] 26 | (if (> (rand 1.0) 0.5) 27 | (* -1 r) 28 | r))) 29 | 30 | (defn random-vehicle 31 | ([] 32 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 33 | ([x y] 34 | {:location (fvec/fvec x y) 35 | :velocity (fvec/fvec (random-v-comp) 36 | (random-v-comp)) 37 | :acceleration (fvec/fvec 0.0 0.0) 38 | :max-speed 3.0 39 | :max-force 0.2})) 40 | 41 | (def VEHICLES 42 | (vec 43 | (for [_ (range 10)] 44 | (random-vehicle)))) 45 | 46 | (defn setup [] 47 | {:vehicles VEHICLES}) 48 | 49 | (defn flock [all vehicle] 50 | (let [sep-factor 1.5 51 | align-factor 1.0 52 | glom-factor 1.0 53 | sep-force (fvec/* 54 | (beh/separate SEPARATION-DIST all vehicle) 55 | sep-factor) 56 | align-force (fvec/* 57 | (beh/align NEIGHBOR-DIST all vehicle) 58 | align-factor) 59 | glom-force (fvec/* 60 | (beh/glom GLOM-DIST all vehicle) 61 | glom-factor)] 62 | (-> vehicle 63 | (beh/apply-force sep-force) 64 | (beh/apply-force align-force) 65 | (beh/apply-force glom-force)))) 66 | 67 | (defn update-vehicles [vehicles] 68 | (doall 69 | (map #(->> % 70 | (flock vehicles) 71 | (beh/move-vehicle) 72 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 73 | vehicles))) 74 | 75 | (defn update [{:keys [vehicles] :as state}] 76 | (-> state 77 | (update-in [:vehicles] update-vehicles))) 78 | 79 | (defn draw-vehicle 80 | [{:keys [location velocity]}] 81 | (let [[x y] (fvec/x-y location) 82 | theta (+ (/ Math/PI 2.0) 83 | (fvec/heading velocity))] 84 | (q/with-translation [x y] 85 | (q/with-rotation [theta] 86 | (q/begin-shape) 87 | (q/vertex 0 (* -2.0 VEHICLE-R)) 88 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 89 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 90 | (q/end-shape :close))))) 91 | 92 | (defn draw [state] 93 | (q/background 0) 94 | (let [{:keys [vehicles]} state] 95 | (q/stroke 0.5) 96 | (q/fill 180) 97 | (doall (map draw-vehicle vehicles)))) 98 | 99 | (defn mouse-dragged [state event] 100 | (let [{:keys [x y]} event] 101 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 102 | 103 | (q/defsketch quil-workflow 104 | :title "Flocking: Boids" 105 | :size [SIZE-W SIZE-H] 106 | :setup setup 107 | :update update 108 | :draw draw 109 | :mouse-dragged mouse-dragged 110 | :middleware [m/fun-mode]) 111 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_5_dot_product/mover_projection.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; 7 | ;; 8 | (ns natureofclojure.ch6-5-dot-product.mover-projection 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-5-dot-product.behavior :as beh])) 14 | 15 | (def TARGET-R 100.0) 16 | (def VEHICLE-R 5.0) 17 | (def VEHICLES 18 | [{:location (fvec/fvec 20 20) 19 | :velocity (fvec/fvec 0 0) 20 | :acceleration (fvec/fvec 0 0) 21 | :max-speed 4 22 | :max-force 0.1} 23 | {:location (fvec/fvec 80 100) 24 | :velocity (fvec/fvec 0 0) 25 | :acceleration (fvec/fvec 0 0) 26 | :max-speed 8 27 | :max-force 0.2}]) 28 | 29 | (defn setup [] 30 | {:x 0 :y 0 31 | :vehicles VEHICLES}) 32 | 33 | (defn update-vehicles [vehicles] 34 | (let [target (fvec/fvec (q/mouse-x) (q/mouse-y))] 35 | (doall (map #(-> % 36 | (beh/arrive-vehicle target TARGET-R) 37 | (beh/move-vehicle)) 38 | vehicles)))) 39 | 40 | (defn update [state] 41 | (-> state 42 | (update-in [:vehicles] update-vehicles))) 43 | 44 | (defn draw-vehicle 45 | [vehicle] 46 | (let [{:keys [location velocity]} vehicle 47 | [x y] (fvec/x-y location) 48 | theta (+ (/ Math/PI 2.0) 49 | (fvec/heading velocity))] 50 | (q/with-translation [x y] 51 | (q/with-rotation [theta] 52 | (q/begin-shape) 53 | (q/vertex 0 (* -2.0 VEHICLE-R)) 54 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 55 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 56 | (q/end-shape :close))))) 57 | 58 | (defn scalar-projection [p a b] 59 | (let [ap (fvec/- p a) 60 | ab (fvec/- b a) 61 | ab-unit (fvec/normalize ab) 62 | shadow (fvec/* (fvec/dot ap ab-unit) ab-unit)] 63 | (fvec/+ a shadow))) 64 | 65 | (defn draw-vehicle-projection [a b vehicle] 66 | (let [[a-x a-y] (fvec/x-y a) 67 | mouse (:location vehicle) 68 | [m-x m-y] (fvec/x-y mouse)] 69 | (q/stroke 255) 70 | (q/line a-x a-y m-x m-y) 71 | (let [norm (scalar-projection mouse a b) 72 | [norm-x norm-y] (fvec/x-y norm)] 73 | (q/stroke 50) 74 | (q/stroke-weight 1) 75 | (q/line m-x m-y norm-x norm-y) 76 | 77 | (q/no-stroke) 78 | (q/fill 255 0 0) 79 | (q/ellipse norm-x norm-y 16 16)))) 80 | 81 | (defn draw-projections [vehicles] 82 | (let [a (fvec/fvec 20 (- (q/height) 20)) 83 | [a-x a-y] (fvec/x-y a) 84 | b (fvec/fvec (- (q/width) 50) (- (q/height) 70)) 85 | [b-x b-y] (fvec/x-y b)] 86 | (q/stroke 255) 87 | (q/stroke-weight 1) 88 | (q/line a-x a-y b-x b-y) 89 | (q/fill 255) 90 | (q/ellipse a-x a-y 8 8) 91 | (q/ellipse b-x b-y 8 8) 92 | (dorun 93 | (map (partial draw-vehicle-projection a b) vehicles)))) 94 | 95 | (defn draw [state] 96 | (q/background 0) 97 | (let [{:keys [x y vehicles]} state] 98 | (q/fill 255) 99 | (q/with-translation [x y] 100 | (q/ellipse 0 0 20 20)) 101 | (q/fill 255 0 0) 102 | (doall (map draw-vehicle vehicles)) 103 | (draw-projections vehicles))) 104 | 105 | (defn mouse-moved [state event] 106 | (-> state 107 | (assoc-in [:x] (:x event)) 108 | (assoc-in [:y] (:y event)))) 109 | 110 | (q/defsketch quil-workflow 111 | :title "Dot Product: Projections" 112 | :size [800 600] 113 | :setup setup 114 | :update update 115 | :draw draw 116 | :mouse-moved mouse-moved 117 | :middleware [m/fun-mode]) 118 | -------------------------------------------------------------------------------- /src/natureofclojure/slider/h_slider.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Based on: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/chp6_agents/flocking_sliders/scrollbar.pde 7 | ;; 8 | (ns natureofclojure.slider.h-slider 9 | (:require 10 | [quil.core :as q])) 11 | 12 | (defn slider 13 | [{:keys [x y w h label loose] :or {w 200.0 h 20.0 label "" loose 2.0}}] 14 | {:w w 15 | :h h 16 | :label label 17 | :loose loose 18 | :x-pos x 19 | :y-pos (- y (/ h 2.0)) 20 | :s-pos x 21 | :new-s-pos x 22 | :s-pos-min x 23 | :s-pos-max (- (+ x w) h) 24 | :over? false 25 | :scrollbar? false 26 | :locked? false}) 27 | 28 | (defn over? [slider mx my] 29 | (and (> mx (:x-pos slider)) 30 | (< mx (+ (:x-pos slider) 31 | (:w slider))) 32 | (> my (:y-pos slider)) 33 | (< my (+ (:y-pos slider) 34 | (:h slider))))) 35 | 36 | (defn constrain [x x-min x-max] 37 | (max x-min (min x x-max))) 38 | 39 | (defn update [slider m-x m-y mouse-pressed?] 40 | (let [s slider 41 | o? (over? s m-x m-y) 42 | s (assoc-in s [:over?] o?) 43 | 44 | s (cond-> s 45 | (and mouse-pressed? o?) 46 | (-> 47 | (assoc-in [:scrollbar?] true) 48 | (assoc-in [:locked?] true)) 49 | 50 | (not mouse-pressed?) 51 | (-> 52 | (assoc-in [:scrollbar?] false) 53 | (assoc-in [:locked?] false))) 54 | 55 | s (if (:locked? s) 56 | (assoc-in s [:new-s-pos] (constrain (- m-x 57 | (/ (:h s) 58 | 2.0)) 59 | (:s-pos-min s) 60 | (:s-pos-max s))) 61 | s) 62 | s (if-not (= (:new-s-pos s) 63 | (:s-pos s)) 64 | (update-in s [:s-pos] #(+ % 65 | (/ (- (:new-s-pos s) 66 | %) 67 | (:loose s)))) 68 | s)] 69 | s)) 70 | 71 | (defn set-pos 72 | "Set slider position as ratio from 0.0 to 1.0" 73 | [slider pos] 74 | (let [new-s-pos (+ (:x-pos slider) 75 | (* pos (- (:s-pos-max slider) 76 | (:s-pos-min slider))))] 77 | (-> slider 78 | (assoc-in [:s-pos] new-s-pos) 79 | (assoc-in [:new-s-pos] new-s-pos)))) 80 | 81 | (defn get-pos 82 | "Get slider position as ratio from 0.0 to 1.0" 83 | [slider] 84 | (/ (- (:s-pos slider) 85 | (:x-pos slider)) 86 | (- (:s-pos-max slider) 87 | (:s-pos-min slider)))) 88 | 89 | (defn draw 90 | [slider] 91 | (q/push-style) 92 | (q/fill 255) 93 | (q/rect-mode :corner) 94 | (q/rect (:x-pos slider) (:y-pos slider) 95 | (:w slider) (:h slider)) 96 | (if (or (:over? slider) (:locked? slider)) 97 | (q/fill 153 102 0) 98 | (q/fill 102 102 102)) 99 | (q/rect (:s-pos slider) (:y-pos slider) 100 | (:h slider) (:h slider)) 101 | (q/pop-style) 102 | slider) 103 | 104 | (defn draw-slider-label [slider] 105 | (let [{:keys [x-pos y-pos w h label]} slider 106 | v (get-pos slider) 107 | spacing 4.0] 108 | (q/push-style) 109 | (q/fill 255) 110 | (q/text-align :left) 111 | (q/text (str label ": " (format "%.3f" v)) 112 | (+ x-pos w spacing) 113 | (+ y-pos h)) 114 | (q/pop-style) 115 | slider)) 116 | -------------------------------------------------------------------------------- /src/natureofclojure/ch3_1_angles_and_angular_motion/mover.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/blob/master/Processing/chp3_oscillation/NOC_3_02_forces_angular_motion/Mover.pde 7 | ;; 8 | (ns natureofclojure.ch3-1-angles-and-angular-motion.mover 9 | (:require [quil.core :as qc] 10 | [natureofclojure.math.vector :as mv])) 11 | 12 | (defn init-mover 13 | ([location mass m] 14 | (init-mover [0.0 0.0] location mass m)) 15 | ([velocity location mass m] 16 | (-> (assoc-in m [:location] location) 17 | (assoc-in [:velocity] velocity) 18 | (assoc-in [:acceleration] [0.0 0.0]) 19 | (assoc-in [:mass] mass)))) 20 | 21 | (defn mover 22 | ([] 23 | {:location [] 24 | :velocity [] 25 | :acceleration [] 26 | :mass 1.0 27 | :angle 0.0 28 | :a-velocity 0.0 29 | :a-acceleration 0.0}) 30 | ([location] 31 | (mover location 1.0)) 32 | ([location mass] 33 | (init-mover location mass (mover))) 34 | ([velocity location mass] 35 | (init-mover velocity location mass (mover)))) 36 | 37 | (defn apply-massless-force [m f] 38 | (update-in m [:acceleration] #(mv/add % f))) 39 | 40 | (defn apply-force [m f] 41 | (let [f (mv/divide f (:mass m))] 42 | (apply-massless-force m f))) 43 | 44 | (defn update-velocity [m] 45 | (-> (update-in m [:velocity] #(mv/add % (:acceleration m))) 46 | (update-in [:velocity] #(mv/limit 6.0 %)))) 47 | 48 | (defn update-location [m] 49 | (update-in m [:location] #(mv/add % (:velocity m)))) 50 | 51 | (defn update-angular-acceleration [m] 52 | (assoc-in m [:a-acceleration] (/ (first (:acceleration m)) 10.0))) 53 | 54 | (defn update-angular-velocity [m] 55 | (-> (update-in m [:a-velocity] #(+ % (:a-acceleration m))) 56 | (update-in [:a-velocity] #(qc/constrain % -0.1 0.1)))) 57 | 58 | (defn update-angle [m] 59 | (update-in m [:angle] #(+ % (:a-velocity m)))) 60 | 61 | (defn update [m] 62 | (-> (update-velocity m) 63 | (update-location) 64 | (update-angular-acceleration) 65 | (update-angular-velocity) 66 | (update-angle) 67 | (assoc-in [:acceleration] [0.0 0.0]))) 68 | 69 | (defn loc-x [m] 70 | (first (:location m))) 71 | 72 | (defn loc-y [m] 73 | (second (:location m))) 74 | 75 | (defn display [m] 76 | (qc/stroke 255) 77 | (qc/fill 236 30 140 200) 78 | (qc/rect-mode :center) 79 | (qc/push-matrix) 80 | (qc/translate (loc-x m) (loc-y m)) 81 | (qc/rotate (:angle m)) 82 | (let [w (* 16.0 (:mass m))] 83 | (qc/stroke-weight 2) 84 | (qc/line 0 0 (/ w 2.0) 0) 85 | (qc/stroke-weight 0) 86 | (qc/rect 0 0 w w)) 87 | (qc/pop-matrix)) 88 | 89 | (defn vel-x [m] 90 | (first (:velocity m))) 91 | 92 | (defn vel-y [m] 93 | (second (:velocity m))) 94 | 95 | (defn bounce-x-right [m width] 96 | (-> (assoc-in m [:location] [width 97 | (loc-y m)]) 98 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 99 | (vel-y m)]))) 100 | 101 | (defn bounce-x-left [m] 102 | (-> (assoc-in m [:location] [0.0 (loc-y m)]) 103 | (assoc-in [:velocity] [(* -1.0 (vel-x m)) 104 | (vel-y m)]))) 105 | 106 | (defn bounce-y-bottom [m height] 107 | (-> (assoc-in m [:location] [(loc-x m) 108 | height]) 109 | (assoc-in [:velocity] [(vel-x m) 110 | (* -0.9 (vel-y m))]))) 111 | 112 | (defn check-edges [m width height] 113 | (let [m (cond (> (loc-x m) width) (bounce-x-right m width) 114 | (< (loc-x m) 0) (bounce-x-left m) 115 | :else m)] 116 | (if (> (loc-y m) height) 117 | (bounce-y-bottom m height) 118 | m))) 119 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_7_grouping/behavior.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch6-7-grouping.behavior 6 | (:require 7 | [quil.core :as q] 8 | [quil.middleware :as m] 9 | [natureofclojure.math.fast-vector :as fvec])) 10 | 11 | (defn dist-vehicle [loc vehicles] 12 | (mapv (fn [v] 13 | (let [d (fvec/distance (:location v) loc)] 14 | [d v])) 15 | vehicles)) 16 | 17 | (defn apply-force [vehicle f-vector] 18 | (update-in vehicle [:acceleration] #(fvec/+ % f-vector))) 19 | 20 | (defn between-0 [upper-d d] 21 | (and (> d 0.0) 22 | (< d upper-d))) 23 | 24 | (defn glom [glom-dist all vehicle] 25 | (let [{:keys [location max-force max-speed velocity]} vehicle 26 | dist-veh (doall 27 | (->> all 28 | (dist-vehicle location) 29 | (filter (fn [[d _]] (between-0 glom-dist d))))) 30 | num-vehicles (count dist-veh)] 31 | (if (< 0 num-vehicles) 32 | (let [sum-loc (doall 33 | (reduce (fn [sum [d v]] 34 | (fvec/+ sum (:location v))) 35 | (fvec/fvec 0 0) dist-veh)) 36 | steer (-> sum-loc 37 | (fvec/- location) 38 | (fvec/normalize) 39 | (fvec/* max-speed) 40 | (fvec/- velocity) 41 | (fvec/limit max-force))] 42 | (apply-force vehicle steer)) 43 | vehicle))) 44 | 45 | (defn separate [separation-dist all vehicle] 46 | (let [{:keys [location max-force max-speed velocity]} vehicle 47 | dist-veh (doall 48 | (->> all 49 | (dist-vehicle location) 50 | (filter (fn [[d _]] (between-0 separation-dist d))))) 51 | num-vehicles (count dist-veh)] 52 | (if (< 0 num-vehicles) 53 | (let [sum-dir (doall 54 | (reduce (fn [avg-dir [d v]] 55 | (let [diff (-> (fvec/- location (:location v)) 56 | (fvec/normalize) 57 | (fvec// d))] 58 | (fvec/+ avg-dir diff))) 59 | (fvec/fvec 0 0) dist-veh)) 60 | steer (-> sum-dir 61 | (fvec/normalize) 62 | (fvec/set-mag max-speed) 63 | (fvec/- velocity) 64 | (fvec/limit max-force))] 65 | (apply-force vehicle steer)) 66 | vehicle))) 67 | 68 | (defn align [neighbor-dist all vehicle] 69 | (let [{:keys [location max-force max-speed velocity]} vehicle 70 | dist-veh (doall 71 | (->> all 72 | (dist-vehicle location) 73 | (filter (fn [[d _]] (between-0 neighbor-dist d))))) 74 | num-vehicles (count dist-veh)] 75 | (if (< 0 num-vehicles) 76 | (let [sum-dir (doall 77 | (reduce (fn [avg-dir [d v]] 78 | (fvec/+ avg-dir (:velocity v))) 79 | (fvec/fvec 0 0) dist-veh)) 80 | steer (-> sum-dir 81 | (fvec// num-vehicles) 82 | (fvec/normalize) 83 | (fvec/* max-speed) 84 | (fvec/- velocity) 85 | (fvec/limit max-force))] 86 | (apply-force vehicle steer)) 87 | vehicle))) 88 | 89 | (defn borders 90 | [edge-x edge-y vehicle-r vehicle] 91 | "Assumes multiple path segments (at least two)." 92 | (let [{:keys [location]} vehicle 93 | [x y] (fvec/x-y location)] 94 | (cond-> 95 | vehicle 96 | (> x (+ edge-x vehicle-r)) 97 | (assoc-in [:location] 98 | (fvec/fvec (- 0 vehicle-r) y)) 99 | 100 | (< x (- 0 vehicle-r)) 101 | (assoc-in [:location] 102 | (fvec/fvec (+ edge-x vehicle-r) y)) 103 | 104 | (> y (+ edge-y vehicle-r)) 105 | (assoc-in [:location] 106 | (fvec/fvec x (- 0 vehicle-r))) 107 | 108 | (< y (- 0 vehicle-r)) 109 | (assoc-in [:location] 110 | (fvec/fvec x (+ edge-y vehicle-r)))))) 111 | 112 | (defn move-vehicle [vehicle] 113 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 114 | v (fvec/limit v (:max-speed vehicle)) 115 | loc (fvec/+ v (:location vehicle))] 116 | (-> vehicle 117 | (assoc-in [:velocity] v) 118 | (assoc-in [:location] loc) 119 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 120 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_6_steering_behaviors/complex_path.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; 7 | ;; 8 | (ns natureofclojure.ch6-6-steering-behaviors.complex-path 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-6-steering-behaviors.behavior :as beh])) 14 | 15 | (def SIZE-W 800.0) 16 | (def SIZE-H 600.0) 17 | 18 | (def PATH-R 20.0) 19 | 20 | (def VEHICLE-R 5.0) 21 | 22 | (defn random-vehicle [x y] 23 | {:location (fvec/fvec x y) 24 | :velocity (fvec/fvec 0.0 0.0) 25 | :acceleration (fvec/fvec 0.0 0.0) 26 | :max-speed (+ 4.0 (rand 4.0)) 27 | :max-force (+ 0.2 (rand 0.2))}) 28 | 29 | (def QTR-H (/ SIZE-H 4.0)) 30 | (def HALF-H (/ SIZE-H 2.0)) 31 | 32 | (defn random-path [] 33 | [(fvec/fvec 0.0 (rand SIZE-H)) 34 | (fvec/fvec (* SIZE-W (/ 1.0 4.0)) (+ QTR-H (rand HALF-H))) 35 | (fvec/fvec (* SIZE-W (/ 2.0 4.0)) (+ QTR-H (rand HALF-H))) 36 | (fvec/fvec (* SIZE-W (/ 3.0 4.0)) (+ QTR-H (rand HALF-H))) 37 | (fvec/fvec SIZE-W (rand SIZE-H))]) 38 | 39 | (defn setup [] 40 | {:vehicles [(random-vehicle (rand SIZE-W) (rand SIZE-H))] 41 | :path (random-path)}) 42 | 43 | (defn insert-normal [location segment] 44 | (let [norm (apply (partial fvec/scalar-projection location) segment)] 45 | [norm segment])) 46 | 47 | (defn path-segments [path] 48 | (partition 2 1 path)) 49 | 50 | (defn closest-segment [path location] 51 | (let [norm-segs (map (partial insert-normal location) 52 | (path-segments path)) 53 | valid-pts (map (fn [[norm [p-a p-b :as seg]]] 54 | ;; Unfortunately have to clamp twice. 55 | (let [n (beh/clamped-normal norm p-a p-b)] 56 | [n seg])) 57 | norm-segs) 58 | dist-segs (doall 59 | (map (fn [[norm segment]] 60 | [(fvec/distance location norm) segment]) 61 | valid-pts)) 62 | by-dist (fn [dist-segs] 63 | (sort (comparator 64 | (fn [[a _] [b _]] 65 | (< a b))) 66 | dist-segs))] 67 | (last (first (by-dist dist-segs))))) 68 | 69 | (defn update-vehicle [path vehicle] 70 | (let [{:keys [location]} vehicle 71 | closest-seg (closest-segment path location)] 72 | (->> vehicle 73 | (beh/follow closest-seg PATH-R) 74 | (beh/move-vehicle) 75 | (beh/borders (first path) (last path) VEHICLE-R)))) 76 | 77 | (defn update-vehicles [path vehicles] 78 | (doall (map (partial update-vehicle path) 79 | vehicles))) 80 | 81 | (defn update [{:keys [vehicles path] :as state}] 82 | (-> state 83 | (update-in [:vehicles] (partial update-vehicles path)))) 84 | 85 | (defn draw-vehicle 86 | [vehicle] 87 | (let [{:keys [location velocity]} vehicle 88 | [x y] (fvec/x-y location) 89 | theta (+ (/ Math/PI 2.0) 90 | (fvec/heading velocity))] 91 | (q/with-translation [x y] 92 | (q/with-rotation [theta] 93 | (q/begin-shape) 94 | (q/vertex 0 (* -2.0 VEHICLE-R)) 95 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 96 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 97 | (q/end-shape :close))))) 98 | 99 | (defn draw-path-segment [path] 100 | (let [[a b] path 101 | [a-x a-y] (fvec/x-y a) 102 | [b-x b-y] (fvec/x-y b)] 103 | (q/no-stroke) 104 | (q/fill 200 255) 105 | (q/quad a-x (+ a-y PATH-R) a-x (- a-y PATH-R) b-x (- b-y PATH-R) b-x (+ b-y PATH-R)) 106 | (q/stroke 100) 107 | (q/stroke-weight 1) 108 | (q/line a-x a-y b-x b-y))) 109 | 110 | (defn draw-path [path] 111 | (doseq [segment (path-segments path)] 112 | (draw-path-segment segment))) 113 | 114 | (defn draw [state] 115 | (q/background 255) 116 | (let [{:keys [path vehicles]} state] 117 | (q/fill 255) 118 | (draw-path path) 119 | (q/fill 255 0 0) 120 | (doall (map draw-vehicle vehicles)))) 121 | 122 | (defn key-pressed [state event] 123 | (assoc-in state [:path] (random-path))) 124 | 125 | (defn mouse-pressed [state event] 126 | (let [{:keys [x y]} event] 127 | (update-in state [:vehicles] #(conj % (random-vehicle x y))))) 128 | 129 | (q/defsketch quil-workflow 130 | :title "Steering Behaviors: Complex Path Following" 131 | :size [SIZE-W SIZE-H] 132 | :setup setup 133 | :update update 134 | :draw draw 135 | :key-pressed key-pressed 136 | :mouse-pressed mouse-pressed 137 | :middleware [m/fun-mode]) 138 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_8_flocking/behavior.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | (ns natureofclojure.ch6-8-flocking.behavior 6 | (:require 7 | [quil.core :as q] 8 | [quil.middleware :as m] 9 | [natureofclojure.math.fast-vector :as fvec])) 10 | 11 | (defn dist-vehicle [loc vehicles] 12 | (mapv (fn [v] 13 | (let [d (fvec/distance (:location v) loc)] 14 | [d v])) 15 | vehicles)) 16 | 17 | (defn apply-force [vehicle f-vector] 18 | (update-in vehicle [:acceleration] #(fvec/+ % f-vector))) 19 | 20 | (defn between-0 [upper-d d] 21 | (and (> d 0.0) 22 | (< d upper-d))) 23 | 24 | (defn align 25 | "Returns the alignment force for nearby vehicles, an average 26 | velocity of sorts. This force must be applied." 27 | [neighbor-dist all vehicle] 28 | (let [{:keys [location max-force max-speed velocity]} vehicle 29 | dist-veh (doall 30 | (->> all 31 | (dist-vehicle location) 32 | (filter (fn [[d _]] (between-0 neighbor-dist d))))) 33 | num-vehicles (count dist-veh)] 34 | (if (< 0 num-vehicles) 35 | (let [sum-dir (doall 36 | (reduce (fn [avg-dir [d v]] 37 | (fvec/+ avg-dir (:velocity v))) 38 | (fvec/fvec 0 0) dist-veh))] 39 | (-> sum-dir 40 | (fvec// num-vehicles) 41 | (fvec/normalize) 42 | (fvec/* max-speed) 43 | (fvec/- velocity) 44 | (fvec/limit max-force))) 45 | (fvec/fvec 0.0 0.0)))) 46 | 47 | (defn glom 48 | "Returns the cohesive force, which must be applied." 49 | [glom-dist all vehicle] 50 | (let [{:keys [location max-force max-speed velocity]} vehicle 51 | dist-veh (doall 52 | (->> all 53 | (dist-vehicle location) 54 | (filter (fn [[d _]] (between-0 glom-dist d))))) 55 | num-vehicles (count dist-veh)] 56 | (if (< 0 num-vehicles) 57 | (let [sum-loc (doall 58 | (reduce (fn [sum [d v]] 59 | (fvec/+ sum (:location v))) 60 | (fvec/fvec 0 0) dist-veh))] 61 | (-> sum-loc 62 | (fvec/- location) 63 | (fvec/normalize) 64 | (fvec/* max-speed) 65 | (fvec/- velocity) 66 | (fvec/limit max-force))) 67 | (fvec/fvec 0.0 0.0)))) 68 | 69 | (defn seek 70 | "Returns the seek force, which must be applied." 71 | [target vehicle] 72 | (let [{:keys [location max-force max-speed velocity]} vehicle] 73 | (-> (fvec/- target location) 74 | (fvec/normalize) 75 | (fvec/* max-speed) 76 | (fvec/- velocity) 77 | (fvec/limit max-force)))) 78 | 79 | (defn separate 80 | "Returns separation force, based on neighbor distance and desired 81 | separation distance. Force must be applied to a vehicles accel." 82 | [sep-dist all vehicle] 83 | (let [{:keys [location max-force max-speed velocity]} vehicle 84 | dist-veh (doall 85 | (->> all 86 | (dist-vehicle location) 87 | (filter (fn [[d _]] (between-0 sep-dist d))))) 88 | num-vehicles (count dist-veh)] 89 | (if (< 0 num-vehicles) 90 | (let [sum-dir (doall 91 | (reduce (fn [avg-dir [d v]] 92 | (let [diff (-> (fvec/- location (:location v)) 93 | (fvec/normalize) 94 | (fvec// d))] 95 | (fvec/+ avg-dir diff))) 96 | (fvec/fvec 0 0) dist-veh))] 97 | (-> sum-dir 98 | (fvec/normalize) 99 | (fvec/set-mag max-speed) 100 | (fvec/- velocity) 101 | (fvec/limit max-force))) 102 | (fvec/fvec 0.0 0.0)))) 103 | 104 | (defn borders 105 | [edge-x edge-y vehicle-r vehicle] 106 | "Assumes multiple path segments (at least two)." 107 | (let [{:keys [location]} vehicle 108 | [x y] (fvec/x-y location)] 109 | (cond-> 110 | vehicle 111 | (> x (+ edge-x vehicle-r)) 112 | (assoc-in [:location] 113 | (fvec/fvec (- 0 vehicle-r) y)) 114 | 115 | (< x (- 0 vehicle-r)) 116 | (assoc-in [:location] 117 | (fvec/fvec (+ edge-x vehicle-r) y)) 118 | 119 | (> y (+ edge-y vehicle-r)) 120 | (assoc-in [:location] 121 | (fvec/fvec x (- 0 vehicle-r))) 122 | 123 | (< y (- 0 vehicle-r)) 124 | (assoc-in [:location] 125 | (fvec/fvec x (+ edge-y vehicle-r)))))) 126 | 127 | (defn move-vehicle [vehicle] 128 | (let [v (fvec/+ (:velocity vehicle) (:acceleration vehicle)) 129 | v (fvec/limit v (:max-speed vehicle)) 130 | loc (fvec/+ v (:location vehicle))] 131 | (-> vehicle 132 | (assoc-in [:velocity] v) 133 | (assoc-in [:location] loc) 134 | (assoc-in [:acceleration] (fvec/fvec 0 0))))) 135 | -------------------------------------------------------------------------------- /src/natureofclojure/ch6_8_flocking/boid_slider.clj: -------------------------------------------------------------------------------- 1 | ;; Based on the Nature of Code 2 | ;; by Daniel Shiffman 3 | ;; http://natureofcode.com 4 | ;; 5 | ;; Specifically: 6 | ;; https://github.com/shiffman/The-Nature-of-Code-Examples/tree/master/chp6_agents/NOC_6_09_Flocking 7 | ;; 8 | (ns natureofclojure.ch6-8-flocking.boid-slider 9 | (:require 10 | [quil.core :as q] 11 | [quil.middleware :as m] 12 | [natureofclojure.math.fast-vector :as fvec] 13 | [natureofclojure.ch6-8-flocking.behavior :as beh] 14 | [natureofclojure.slider.h-slider :as slider])) 15 | 16 | (def SIZE-W 800.0) 17 | (def SIZE-H 600.0) 18 | 19 | (def VEHICLE-R 4.0) 20 | 21 | (def SEPARATION-FACTOR 1.5) 22 | (def SEPARATION-DIST 30) 23 | (def ALIGN-FACTOR 1.0) 24 | (def NEIGHBOR-DIST 100) 25 | (def GLOM-FACTOR 1.0) 26 | (def GLOM-DIST 50) 27 | 28 | (def SEP-FACTOR-MIN 0.0) 29 | (def SEP-FACTOR-MAX 5.0) 30 | (def SEP-DIST-MIN 0.0) 31 | (def SEP-DIST-MAX 300.0) 32 | 33 | (def ALIGN-FACTOR-MIN 0.0) 34 | (def ALIGN-FACTOR-MAX 5.0) 35 | (def NEIGHBOR-DIST-MIN 0.0) 36 | (def NEIGHBOR-DIST-MAX 300.0) 37 | 38 | (def GLOM-FACTOR-MIN 0.0) 39 | (def GLOM-FACTOR-MAX 5.0) 40 | (def GLOM-DIST-MIN 0.0) 41 | (def GLOM-DIST-MAX 300.0) 42 | 43 | (defn random-v-comp [] 44 | (let [r (+ 20.0 (rand 40.0))] 45 | (if (> (rand 1.0) 0.5) 46 | (* -1 r) 47 | r))) 48 | 49 | (defn random-vehicle 50 | ([] 51 | (random-vehicle (rand SIZE-W) (rand SIZE-H))) 52 | ([x y] 53 | {:location (fvec/fvec x y) 54 | :velocity (fvec/fvec (random-v-comp) 55 | (random-v-comp)) 56 | :acceleration (fvec/fvec 0.0 0.0) 57 | :max-speed 3.0 58 | :max-force 0.2})) 59 | 60 | (def VEHICLES 61 | (vec 62 | (for [_ (range 10)] 63 | (random-vehicle)))) 64 | 65 | (defn map-pos [v min-v max-v] 66 | (q/map-range v min-v max-v 0.0 1.0)) 67 | 68 | (defn gen-slider [n label pos] 69 | (let [y (* (inc n) 20)] 70 | (-> (slider/slider {:x 10 :y y :w 100 :h 10 :label label}) 71 | (slider/set-pos pos)))) 72 | 73 | (def SLIDERS [(gen-slider 0 "separation force" 74 | (map-pos SEPARATION-FACTOR SEP-FACTOR-MIN SEP-FACTOR-MAX)) 75 | (gen-slider 1 "separation distance" 76 | (map-pos SEPARATION-DIST SEP-DIST-MIN SEP-DIST-MAX)) 77 | (gen-slider 2 "alignment force" 78 | (map-pos ALIGN-FACTOR ALIGN-FACTOR-MIN ALIGN-FACTOR-MAX)) 79 | (gen-slider 3 "neighbor distance" 80 | (map-pos NEIGHBOR-DIST NEIGHBOR-DIST-MIN NEIGHBOR-DIST-MAX)) 81 | (gen-slider 4 "glom force" 82 | (map-pos GLOM-FACTOR GLOM-FACTOR-MIN GLOM-FACTOR-MAX)) 83 | (gen-slider 5 "glom distance" 84 | (map-pos GLOM-DIST GLOM-DIST-MIN GLOM-DIST-MAX))]) 85 | 86 | (defn setup [] 87 | (-> {:vehicles VEHICLES 88 | :sliders SLIDERS 89 | :sep-factor SEPARATION-FACTOR 90 | :sep-dist SEPARATION-DIST 91 | :align-factor ALIGN-FACTOR 92 | :neighbor-dist NEIGHBOR-DIST 93 | :glom-factor GLOM-FACTOR 94 | :glom-dist GLOM-DIST})) 95 | 96 | (defn flock [state all vehicle] 97 | (let [{:keys [sep-factor sep-dist 98 | align-factor neighbor-dist 99 | glom-factor glom-dist]} state 100 | sep-force (fvec/* 101 | (beh/separate sep-dist all vehicle) 102 | sep-factor) 103 | align-force (fvec/* 104 | (beh/align neighbor-dist all vehicle) 105 | align-factor) 106 | glom-force (fvec/* 107 | (beh/glom glom-dist all vehicle) 108 | glom-factor)] 109 | (-> vehicle 110 | (beh/apply-force sep-force) 111 | (beh/apply-force align-force) 112 | (beh/apply-force glom-force)))) 113 | 114 | (defn update-vehicles [state vehicles] 115 | (doall 116 | (mapv #(->> % 117 | (flock state vehicles) 118 | (beh/move-vehicle) 119 | (beh/borders SIZE-W SIZE-H VEHICLE-R)) 120 | vehicles))) 121 | 122 | (defn update-sliders [sliders m-x m-y mouse-pressed?] 123 | (doall 124 | (mapv #(slider/update % m-x m-y mouse-pressed?) 125 | sliders))) 126 | 127 | (defn map-factor [factor min-v max-v] 128 | (q/map-range factor 0.0 1.0 min-v max-v)) 129 | 130 | (defn update [{:keys [sliders vehicles] :as state}] 131 | (let [[m-x m-y] [(q/mouse-x) (q/mouse-y)] 132 | mouse-pressed? (q/mouse-pressed?) 133 | updated-sliders (update-sliders sliders m-x m-y mouse-pressed?) 134 | sep-v (map-factor (slider/get-pos (nth updated-sliders 0)) 135 | SEP-FACTOR-MIN SEP-FACTOR-MAX) 136 | sep-d (map-factor (slider/get-pos (nth updated-sliders 1)) 137 | SEP-DIST-MIN SEP-DIST-MAX) 138 | 139 | align-v (map-factor (slider/get-pos (nth updated-sliders 2)) 140 | ALIGN-FACTOR-MIN ALIGN-FACTOR-MAX) 141 | neighbor-d (map-factor (slider/get-pos (nth updated-sliders 3)) 142 | NEIGHBOR-DIST-MIN NEIGHBOR-DIST-MAX) 143 | 144 | glom-v (map-factor (slider/get-pos (nth updated-sliders 4)) 145 | GLOM-FACTOR-MIN GLOM-FACTOR-MAX) 146 | glom-d (map-factor (slider/get-pos (nth updated-sliders 5)) 147 | GLOM-DIST-MIN GLOM-DIST-MAX)] 148 | (-> state 149 | (assoc-in [:sep-factor] sep-v) 150 | (assoc-in [:sep-dist] sep-d) 151 | (assoc-in [:align-factor] align-v) 152 | (assoc-in [:neighbor-dist] neighbor-d) 153 | (assoc-in [:glom-factor] glom-v) 154 | (assoc-in [:glom-dist] glom-d) 155 | (#(update-in % [:vehicles] (partial update-vehicles %))) 156 | (assoc-in [:sliders] updated-sliders)))) 157 | 158 | (defn draw-vehicle 159 | [{:keys [location velocity]}] 160 | (let [[x y] (fvec/x-y location) 161 | theta (+ (/ Math/PI 2.0) 162 | (fvec/heading velocity))] 163 | (q/with-translation [x y] 164 | (q/with-rotation [theta] 165 | (q/begin-shape) 166 | (q/vertex 0 (* -2.0 VEHICLE-R)) 167 | (q/vertex (* -1.0 VEHICLE-R) (* 2.0 VEHICLE-R)) 168 | (q/vertex VEHICLE-R (* 2.0 VEHICLE-R)) 169 | (q/end-shape :close))))) 170 | 171 | (defn draw [state] 172 | (q/background 0) 173 | (let [{:keys [sliders vehicles]} state] 174 | (doall (map (comp 175 | slider/draw 176 | slider/draw-slider-label) 177 | sliders)) 178 | (q/stroke 0.5) 179 | (q/fill 180) 180 | (doall (map draw-vehicle vehicles)))) 181 | 182 | (defn is-over-sliders? [x y] 183 | (and (< x (/ SIZE-W 2.0)) 184 | (< y (/ SIZE-H 2.0)))) 185 | 186 | (defn mouse-dragged [state event] 187 | (let [{:keys [x y]} event] 188 | (if-not (is-over-sliders? x y) 189 | (update-in state [:vehicles] #(conj % (random-vehicle x y))) 190 | state))) 191 | 192 | (q/defsketch quil-workflow 193 | :title "Flocking: Boids" 194 | :size [SIZE-W SIZE-H] 195 | :setup setup 196 | :update update 197 | :draw draw 198 | :mouse-dragged mouse-dragged 199 | :middleware [m/fun-mode]) 200 | --------------------------------------------------------------------------------