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 |
;; +----------+
(defn rand [] (.random js/Math))
(defn abs [x] (.abs js/Math x))
(def PI 3.141592653589793)
@ -53,22 +51,20 @@
(defn next-pos [[x y] [vel-x vel-y] tick]
[(+ x (* vel-x tick)) (+ y (* vel-y tick))])
(defn ^:export frpong []
(let [body-el (.-body js/document)
width (- (.-scrollWidth body-el) 20)
height (- (.-scrollHeight body-el) 125)
padding 5
paddle-size 100
paddle-width 10
ball-radius 8
ball-speed 0.33
init-pos [(/ width 2) (/ height 2)]
paddle-step 20
max-paddle-y (- height paddle-size)
ef-paddle-width (+ paddle-width padding)
init-paddle-pos (/ (- height paddle-size) 2)]
(def width (- (.-scrollWidth (.-body js/document)) 20))
(def height (- (.-scrollHeight (.-body js/document)) 125))
(def padding 5)
(def paddle-size 100)
(def paddle-width 10)
(def ball-radius 8)
(def ball-speed 0.33)
(def init-pos [(/ width 2) (/ height 2)])
(def paddle-step 20)
(def max-paddle-y (- height paddle-size))
(def ef-paddle-width (+ paddle-width padding))
(def init-paddle-pos (/ (- height paddle-size) 2))
(defn layout-game
(defn layout-game
"Lays out the game screen."
[]
(doto (dom/by-id "canvas")
@ -86,7 +82,7 @@
(dom/set-attr! (dom/by-id "lpaddle") "x" 0)
(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."
[]
(let [frames (frame-chan) ;; frames signal
@ -109,7 +105,7 @@
(put! pr-pos init-paddle-pos)
(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
tapped from the multiplexers.
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))))
(defn ticker
(defn ticker
"Ticker component.
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
@ -153,7 +149,7 @@
(stop-frames)
(recur))))))))
(defn ball-positioner
(defn ball-positioner
"Ball Positioner component.
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."
@ -163,7 +159,7 @@
pos-next (next-pos (<! pos-in) (<! vel) tick)]
(>! pos-out pos-next))))
(defn paddle-positioner
(defn paddle-positioner
"Paddle Positioner component.
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
@ -177,17 +173,10 @@
:up (max (- pos paddle-step) 0)
: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]
"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]
(defn in-y-range? [y paddle-y]
(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
(< x ef-paddle-width)
(if (in-y-range? y lpaddle-y) :collision-left :gameover)
@ -195,23 +184,31 @@
(if (in-y-range? y rpaddle-y) :collision-right :gameover)
:else :moving))
(defn detect-y-collision [y]
(defn detect-y-collision [y]
(cond
(< y padding) :collision-left
(> y (- height padding)) :collision-right
:else :moving))
(defn collision-state? [state]
(defn collision-state? [state]
(or (= state :collision-left) (= state :collision-right)))
(defn adjust-vel [state v]
(defn adjust-vel [state v]
(condp = state
:collision-left (abs v)
:collision-right (- (abs v))
:moving v
: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
(let [;; get all current values
@ -245,7 +242,7 @@
(>! vel-out [vel-xn vel-yn])
(>! game-state [state-n score-n]))))
(defn renderer
(defn renderer
"Renderer component.
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."
@ -272,7 +269,7 @@
(dom/set-text! score-el score))
(when (= state :gameover)
(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
(dom/set-attr! "cx" x)
(dom/set-attr! "cy" y))
@ -282,6 +279,7 @@
(go-loop
(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)
(ev/listen-once! :keypress start-game)))
(ev/listen-once! :keypress #(when (= (:keyCode %) 32) (start-game))))