-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbounce.cljs
106 lines (93 loc) · 3.36 KB
/
bounce.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
(ns la-vie-en-cloj.bounce
(:require [mondrian.anim :as anim]
[mondrian.canvas :as canvas]
[mondrian.color :as color]
[mondrian.math :as math]
[mondrian.plot :as plot]
[mondrian.ui :as ui]
[monet.canvas :as m])
(:use-macros [mondrian.macros :only [defmondrian]]))
;; ---------------------------------------------------------------------
;; Update pipeline
;;
;; Initial state:
;; :drawing -- The top-level DOM element that contains the canvas,
;; the sliders, etc.
;; :ctx -- The canvas context.
;; :w -- The width of the canvas.
;; :h -- The height of the canvas.
;;
;; Configuration values (as defined on the mondrian element):
;; :ball-size -- Radius of the circle in pixels.
;; :speed-pps -- The speed of the circle in pixels-per-second.
;; :persist-image -- Whether or not to clear the background in
;; between frames.
;;
;; After merge-control-values:
;; :... -- One key for each control (identified by the control name).
;; Zero or more controls may be present under the mondrian element,
;; in which case the missing values must have been provided in as
;; defaults in the element itself.
;;
;; After move:
;; :x -- X location of the center of the circle (may be off-canvas
;; depending on the speed and the framerate).
;; :y -- Y location of the center of the circle (may be off-canvas
;; depending on the speed and the framerate).
;; :direction -- Direction (in radians) in which the circle is moving.
;;
;; After bounce:
;; :x -- X location of the center of the circle after bouncing the
;; circle off of walls (if necessary).
;; :x -- Y location of the center of the circle after bouncing the
;; circle off of walls (if necessary).
(defn merge-control-values
"Merge the current values of the controls into state."
[{:keys [drawing] :as state}]
(merge state (ui/update-controls drawing)))
(defn move
[{:keys [delta-t-ms speed-pps x y w h direction] :as state}]
(let [direction (math/radians direction)
pixels-per-millisecond (/ speed-pps 1000)
delta-pixels (* delta-t-ms pixels-per-millisecond)
dx (math/circle-x delta-pixels direction)
dy (math/circle-y delta-pixels direction)
clamped-x (-> x (+ dx) (max 0) (min w))
clamped-y (-> y (+ dy) (max 0) (min h))]
(assoc state :x clamped-x :y clamped-y)))
(defn bounce
[{:keys [w h x y] :as state}]
(cond
(not (< 0 x w)) (update-in state [:direction] #(- 180 %))
(not (< 0 y h)) (update-in state [:direction] #(- 360 %))
:else state))
(defn update-pipeline
[state]
(-> state
merge-control-values
move
bounce))
;; ---------------------------------------------------------------------
;; Render stack
;;
(defn clear-background
[{:keys [ctx w h persist-image]}]
(when-not persist-image
(-> ctx
(m/fill-style "rgba(25,29,33,0.75)") ;; Alpha adds motion blur
(m/fill-rect {:x 0 :y 0 :w w :h h}))))
(defn draw-ball
[{:keys [ctx ball-size x y]}]
(m/fill-style ctx "red")
(m/circle ctx {:x x :y y :r ball-size}))
(defn render-stack
[state]
(clear-background state)
(draw-ball state))
;; ---------------------------------------------------------------------
;; Main entry point
;;
(defmondrian bounce-anim
{:x 100 :y 100 :direction (rand-int 360)}
update-pipeline
render-stack)