Removed nested defns and moved top level let bindings to defs

master
Abhinav Sarkar 2013-10-12 21:50:48 +05:30
parent a03a829a5e
commit f2ed5e513d
1 changed files with 231 additions and 233 deletions

View File

@ -29,8 +29,6 @@
;; | renderer | ;; | renderer |
;; +----------+ ;; +----------+
(defn rand [] (.random js/Math))
(defn abs [x] (.abs js/Math x)) (defn abs [x] (.abs js/Math x))
(def PI 3.141592653589793) (def PI 3.141592653589793)
@ -53,22 +51,20 @@
(defn next-pos [[x y] [vel-x vel-y] tick] (defn next-pos [[x y] [vel-x vel-y] tick]
[(+ x (* vel-x tick)) (+ y (* vel-y tick))]) [(+ x (* vel-x tick)) (+ y (* vel-y tick))])
(defn ^:export frpong [] (def width (- (.-scrollWidth (.-body js/document)) 20))
(let [body-el (.-body js/document) (def height (- (.-scrollHeight (.-body js/document)) 125))
width (- (.-scrollWidth body-el) 20) (def padding 5)
height (- (.-scrollHeight body-el) 125) (def paddle-size 100)
padding 5 (def paddle-width 10)
paddle-size 100 (def ball-radius 8)
paddle-width 10 (def ball-speed 0.33)
ball-radius 8 (def init-pos [(/ width 2) (/ height 2)])
ball-speed 0.33 (def paddle-step 20)
init-pos [(/ width 2) (/ height 2)] (def max-paddle-y (- height paddle-size))
paddle-step 20 (def ef-paddle-width (+ paddle-width padding))
max-paddle-y (- height paddle-size) (def init-paddle-pos (/ (- height paddle-size) 2))
ef-paddle-width (+ paddle-width padding)
init-paddle-pos (/ (- height paddle-size) 2)]
(defn layout-game (defn layout-game
"Lays out the game screen." "Lays out the game screen."
[] []
(doto (dom/by-id "canvas") (doto (dom/by-id "canvas")
@ -86,7 +82,7 @@
(dom/set-attr! (dom/by-id "lpaddle") "x" 0) (dom/set-attr! (dom/by-id "lpaddle") "x" 0)
(dom/set-attr! (dom/by-id "rpaddle") "x" (- width paddle-width))) (dom/set-attr! (dom/by-id "rpaddle") "x" (- width paddle-width)))
(defn start-game (defn start-game
"Sets up the game by creating the signals and setting up the components and starts the game." "Sets up the game by creating the signals and setting up the components and starts the game."
[] []
(let [frames (frame-chan) ;; frames signal (let [frames (frame-chan) ;; frames signal
@ -109,7 +105,7 @@
(put! pr-pos init-paddle-pos) (put! pr-pos init-paddle-pos)
(put! game-state [:moving 0]))) (put! game-state [:moving 0])))
(defn setup-components (defn setup-components
"Multiplexes the signals and sets up the components by connecting them using the signals "Multiplexes the signals and sets up the components by connecting them using the signals
tapped from the multiplexers. tapped from the multiplexers.
The signals are taken as parameters." The signals are taken as parameters."
@ -138,7 +134,7 @@
(renderer (tap ticks-m) (tap game-state-m) (tap pos-m) (tap pl-pos-m) (tap pr-pos-m)))) (renderer (tap ticks-m) (tap game-state-m) (tap pos-m) (tap pl-pos-m) (tap pr-pos-m))))
(defn ticker (defn ticker
"Ticker component. "Ticker component.
Converts `frames` signal to ticks and outputs them to the `ticks` signal Converts `frames` signal to ticks and outputs them to the `ticks` signal
as long as the `game-state` signal is not :gameover. Once the `game-state` signal is as long as the `game-state` signal is not :gameover. Once the `game-state` signal is
@ -153,7 +149,7 @@
(stop-frames) (stop-frames)
(recur)))))))) (recur))))))))
(defn ball-positioner (defn ball-positioner
"Ball Positioner component. "Ball Positioner component.
Calculates the next ball position using the current ball position (from the `pos-in` signal) Calculates the next ball position using the current ball position (from the `pos-in` signal)
and the current tick (from the `ticks` signal) and outputs it to the `pos-out` signal." and the current tick (from the `ticks` signal) and outputs it to the `pos-out` signal."
@ -163,7 +159,7 @@
pos-next (next-pos (<! pos-in) (<! vel) tick)] pos-next (next-pos (<! pos-in) (<! vel) tick)]
(>! pos-out pos-next)))) (>! pos-out pos-next))))
(defn paddle-positioner (defn paddle-positioner
"Paddle Positioner component. "Paddle Positioner component.
Captures the keydown signal for the provides keycodes and calculates the next paddle Captures the keydown signal for the provides keycodes and calculates the next paddle
position using the current paddle position (from the `pos-in` signal) and keydown signal position using the current paddle position (from the `pos-in` signal) and keydown signal
@ -177,17 +173,10 @@
:up (max (- pos paddle-step) 0) :up (max (- pos paddle-step) 0)
:down (min (+ pos paddle-step) max-paddle-y))))))) :down (min (+ pos paddle-step) max-paddle-y)))))))
(defn collision-detector [ticks pos vel-in pl-pos pr-pos game-state-in game-state vel-out] (defn in-y-range? [y paddle-y]
"Collision Detector component.
Detects the collision of the ball with the walls and the paddles and accordingly calculates
and outputs the next ball velocity and next game state to the `vel-out` and `game-state`
signals respectively.
Reads the current tick, ball position, ball velocity and left and right paddle positions from
the `ticks`, `pos`, `vel-in`, `pl-pos` and `pr-pos` signals respectively."
(defn in-y-range? [y paddle-y]
(and (> y (- paddle-y padding)) (< y (+ paddle-y paddle-size padding)))) (and (> y (- paddle-y padding)) (< y (+ paddle-y paddle-size padding))))
(defn detect-x-collision [x y lpaddle-y rpaddle-y] (defn detect-x-collision [x y lpaddle-y rpaddle-y]
(cond (cond
(< x ef-paddle-width) (< x ef-paddle-width)
(if (in-y-range? y lpaddle-y) :collision-left :gameover) (if (in-y-range? y lpaddle-y) :collision-left :gameover)
@ -195,23 +184,31 @@
(if (in-y-range? y rpaddle-y) :collision-right :gameover) (if (in-y-range? y rpaddle-y) :collision-right :gameover)
:else :moving)) :else :moving))
(defn detect-y-collision [y] (defn detect-y-collision [y]
(cond (cond
(< y padding) :collision-left (< y padding) :collision-left
(> y (- height padding)) :collision-right (> y (- height padding)) :collision-right
:else :moving)) :else :moving))
(defn collision-state? [state] (defn collision-state? [state]
(or (= state :collision-left) (= state :collision-right))) (or (= state :collision-left) (= state :collision-right)))
(defn adjust-vel [state v] (defn adjust-vel [state v]
(condp = state (condp = state
:collision-left (abs v) :collision-left (abs v)
:collision-right (- (abs v)) :collision-right (- (abs v))
:moving v :moving v
:gameover 0)) :gameover 0))
(defn perturb [v] (* v (+ 1 (/ (- (rand) 0.5) 25)))) (defn perturb [v] (* v (+ 1 (/ (- (rand) 0.5) 25))))
(defn collision-detector [ticks pos vel-in pl-pos pr-pos game-state-in game-state vel-out]
"Collision Detector component.
Detects the collision of the ball with the walls and the paddles and accordingly calculates
and outputs the next ball velocity and next game state to the `vel-out` and `game-state`
signals respectively.
Reads the current tick, ball position, ball velocity, left and right paddle positions and game state
from the `ticks`, `pos`, `vel-in`, `pl-pos`, `pr-pos` and `game-state` signals respectively."
(go-loop (go-loop
(let [;; get all current values (let [;; get all current values
@ -245,7 +242,7 @@
(>! vel-out [vel-xn vel-yn]) (>! vel-out [vel-xn vel-yn])
(>! game-state [state-n score-n])))) (>! game-state [state-n score-n]))))
(defn renderer (defn renderer
"Renderer component. "Renderer component.
Renders the ball and paddle positions on the browser. Also shows the game state and stats. Renders the ball and paddle positions on the browser. Also shows the game state and stats.
Reads the current values from the signals supplied as parameters." Reads the current values from the signals supplied as parameters."
@ -272,7 +269,7 @@
(dom/set-text! score-el score)) (dom/set-text! score-el score))
(when (= state :gameover) (when (= state :gameover)
(do (dom/set-text! state-el "press <space> to restart") (do (dom/set-text! state-el "press <space> to restart")
(ev/listen-once! :keypress start-game))) (ev/listen-once! :keypress #(when (= (:keyCode %) 32) (start-game)))))
(doto ball-el (doto ball-el
(dom/set-attr! "cx" x) (dom/set-attr! "cx" x)
(dom/set-attr! "cy" y)) (dom/set-attr! "cy" y))
@ -282,6 +279,7 @@
(go-loop (go-loop
(dom/set-attr! rpaddle-el "y" (<! pr-pos))))) (dom/set-attr! rpaddle-el "y" (<! pr-pos)))))
;; Everything is ready now. Layout the game and start it on any keypress! ;; Everything is ready now. Layout the game and start it on pressing <space>!
(defn ^:export frpong []
(layout-game) (layout-game)
(ev/listen-once! :keypress start-game))) (ev/listen-once! :keypress #(when (= (:keyCode %) 32) (start-game))))