Skip to content

Commit

Permalink
Chapter 1 Examples 5, 6, and 7
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramblurr committed Jun 4, 2024
1 parent ecd9f9b commit 6b51c81
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 3 deletions.
10 changes: 9 additions & 1 deletion dev/user.clj
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@
(= 5.0 (tm/mag (v/vec2 4 3)))
(tm/+ (v/vec2 1 1) (v/vec2 1 1))
(tm/normalize (v/vec2 2 3))
(g/heading-xy (v/vec2 2 3)))
(g/heading-xy (v/vec2 2 3))
(g/rotate (v/vec2 1 1) Math/PI)
(tm/mix (v/vec2 1 1) (v/vec2 2 2) 0.5)
(g/dist (v/vec2 1 1) (v/vec2 2 2))
(g/angle-between (v/vec2 1 1) (v/vec2 2 3))

;;
)

;;
)
38 changes: 38 additions & 0 deletions notebooks/chapter_1.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,41 @@ But this it may be surprising. `(tm/+ (v/vec2 1 1) (v/vec2 1 1))` produces a vec
Ok, for this one I got tired of destructuring the vectors or using `first` and `second` to yoink out the components to pass to quil's `line` function. A little helper goes a long way.

By the way, Daniel's exposition on the vector math in this chapter is really great. Don't just look at the code, refer to the text and the illustrations to really get an understanding of the vector math.


## [Example 1.5: Vector Magnitude](https://natureofcode.com/vectors/#example-15-vector-magnitude)


```clojure
^{::clerk/no-cache true ::clerk/viewer clerk/code}
(slurp "src/noc/chapter_1_5.cljs")
(show-sketch :c1.5)
```

Here I pulled out the line helper into a util namespace, because I imagine we will use it a lot in the future.

## [Example 1.6: Normalizing a Vector](https://natureofcode.com/vectors/#example-16-normalizing-a-vector)


```clojure
^{::clerk/no-cache true ::clerk/viewer clerk/code}
(slurp "src/noc/chapter_1_6.cljs")
(show-sketch :c1.6)
```

## [Example 1.7: Motion 101 (Velocity)](https://natureofcode.com/vectors/#example-17-motion-101-velocity)


```clojure
^{::clerk/no-cache true ::clerk/viewer clerk/code}
(slurp "src/noc/chapter_1_7.cljs")
(show-sketch :c1.7)
```

Wow, so I discovered several things while writing this example.

1. The `(v/x some-vector)` and `(v/y some-vector)` functions (where `v` is `[thi.ng.geom.vector :as v]`) will return the corresponding x and y components. This could be handy in the future
2. But since the vector type implements all the interfaces to be treated as a map, you can also `assoc` with it while referring to the keys `:x` and `:y`

I used the 2nd discovery to implement a bounds checking function that is rather generic, while still being readable. I am quite pleased with that.

29 changes: 29 additions & 0 deletions src/noc/chapter_1_5.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(ns noc.chapter-1-5
(:require
[noc.quil.util :as u]
[thi.ng.math.core :as tm]
[thi.ng.geom.vector :as v]
[quil.core :as q]))

(def size [640 240])

(defn init-state [{:keys [width height] :as state}]
{})

(defn setup! [{:keys [width height]}]
(q/background 255))

(defn tick [state]
state)

(defn draw! [{:keys [width height mouse-x mouse-y]}]
(let [zero (v/vec2 0 0)
mouse (v/vec2 mouse-x mouse-y)
center (v/vec2 (quot width 2) (quot height 2))
subtracted (tm/- mouse center)
m (tm/mag subtracted)]
(q/background 255)
(q/fill 0)
(q/rect 10 10 m 10)
(q/translate (quot width 2) (quot height 2))
(u/line zero subtracted)))
32 changes: 32 additions & 0 deletions src/noc/chapter_1_6.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(ns noc.chapter-1-6
(:require
[noc.quil.util :as u]
[thi.ng.math.core :as tm]
[thi.ng.geom.vector :as v]
[quil.core :as q]))

(def size [640 240])

(defn init-state [{:keys [width height] :as state}]
{})

(defn setup! [{:keys [width height]}]
(q/background 255))

(defn tick [state]
state)

(defn draw! [{:keys [width height mouse-x mouse-y]}]
(let [zero (v/vec2 0 0)
mouse (v/vec2 mouse-x mouse-y)
center (v/vec2 (quot width 2) (quot height 2))
subtracted (tm/- mouse center)
normed (tm/* (tm/normalize subtracted) 50)]
(q/background 255)
(q/translate (quot width 2) (quot height 2))
(q/stroke 200)
(q/stroke-weight 2)
(u/line zero subtracted)
(q/stroke 0)
(q/stroke-weight 8)
(u/line zero normed)))
59 changes: 59 additions & 0 deletions src/noc/chapter_1_7.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns noc.chapter-1-7
(:require
[noc.quil.util :as u]
[thi.ng.math.core :as tm]
[thi.ng.geom.vector :as v]
[quil.core :as q]))

(def size [640 240])

(defn init-state [{:keys [width height] :as state}]
{:mover {:position (v/vec2 (q/random width) (q/random height))
:velocity (v/vec2 (q/random -2 2) (q/random -2 2))}})

(defn setup! [{:keys [width height]}]
(q/background 255))

;; These were my first pass at the implementation
;; but I wasn't happy that it has so much repeated code
(comment
(defn enforce-bound-x [width position]
(let [x (v/x position)]
(cond (>= x width) (v/vec2 0 (v/y position))
(<= x 0) (v/vec2 width (v/y position))
:else position)))

(defn enforce-bound-y [height position]
(let [y (v/y position)]
(cond (>= y height) (v/vec2 (v/y position) 0)
(<= y 0) (v/vec2 (v/y position) height)
:else position))))

;; ... so I refactored it to this
;; `dimension` is either width or height
;; `component` is either :x or :y, perhaps there's a better name?
(defn enforce-bound [dimension component position]
(let [value (component position)]
(cond (>= value dimension) (assoc position component 0)
(<= value 0) (assoc position component dimension)
:else position)))

(defn tick-mover [width height {:keys [velocity] :as mover}]
(-> mover
(update :position #(tm/+ % velocity))
(update :position #(enforce-bound width :x %))
(update :position #(enforce-bound height :y %))))

(defn tick [{:keys [width height] :as state}]
(-> state
(update :mover #(tick-mover width height %))))

(defn draw-mover [{:keys [position]}]
(q/stroke 0)
(q/stroke-weight 2)
(q/fill 127)
(q/ellipse (v/x position) (v/y position) 48 48))

(defn draw! [{:keys [mover]}]
(q/background 255)
(draw-mover mover))
5 changes: 5 additions & 0 deletions src/noc/quil/util.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(ns noc.quil.util
(:require [quil.core :as q]))

(defn line [[x1 y1] [x2 y2]]
(q/line x1 y1 x2 y2))
10 changes: 8 additions & 2 deletions src/noc/sketch.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
[noc.chapter-1-2 :as c1.2]
[noc.chapter-1-3e :as c1.3e]
[noc.chapter-1-3 :as c1.3]
[noc.chapter-1-4 :as c1.4]))
[noc.chapter-1-4 :as c1.4]
[noc.chapter-1-5 :as c1.5]
[noc.chapter-1-6 :as c1.6]
[noc.chapter-1-7 :as c1.7]))

(def sketches
{:walker (sketch-> c0.1)
Expand All @@ -45,7 +48,10 @@
:c1.2 (sketch-> c1.2)
:c1.3e (sketch-3d-> c1.3e)
:c1.3 (sketch-> c1.3)
:c1.4 (sketch-> c1.4)})
:c1.4 (sketch-> c1.4)
:c1.5 (sketch-> c1.5)
:c1.6 (sketch-> c1.6)
:c1.7 (sketch-> c1.7)})

(defn load-sketch [s]
(when-let [sk (get sketches s)]
Expand Down

0 comments on commit 6b51c81

Please sign in to comment.