diff --git a/resources/public/index.html b/resources/public/index.html index 95f5b57..9044477 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -2,13 +2,12 @@ - Simple CLJS + Functional Reactive Pong in Clojure using core.async -
Frame:
FPS:
State:
@@ -19,6 +18,6 @@ - + \ No newline at end of file diff --git a/src/cljs/frpong/core.cljs b/src/cljs/frpong/core.cljs index f15c6cc..e1f3c41 100644 --- a/src/cljs/frpong/core.cljs +++ b/src/cljs/frpong/core.cljs @@ -1,6 +1,6 @@ (ns frpong.core - (:require [frpong.helpers :as h] - [cljs.core.async :refer [! chan put!]] + (:require [frpong.helpers :as h :refer (mult tap)] + [cljs.core.async :refer [! chan put! close! sliding-buffer]] [domina :as dom :refer [log]]) (:require-macros [cljs.core.async.macros :as m :refer [go]] [frpong.core :refer (go-loop)])) @@ -34,163 +34,173 @@ (let [c (chan)] (go (loop [prev (! c t)) - (recur t)))) + (if-let [t (! c t)) + (recur t)) + (close! c)))) c)) -(defn ticker [[frames stop-frames] ticks game-state] - (let [ticks-in (tick-chan (h/diff-chan frames))] - (go-loop - (if-not (= :gameover (! ticks (! pos-out pos-next)))) - -(defn paddle-positioner [keycodes max-y movement pos-in pos-out] - (let [keys (h/key-chan keycodes)] - (go-loop - (let [pos (! pos-out - (condp = ( y (+ p-pos padding)) - (< y (- (+ p-pos paddle-size) padding)))) - detect-x-collision (fn [x y pl-pos pr-pos] - (cond - (< x ef-paddle-width) - (if (in-y-range? y pl-pos) :collision-left :gameover) - (> x (- width ef-paddle-width)) - (if (in-y-range? y pr-pos) :collision-right :gameover) - :else :moving)) - detect-y-collision (fn [y] (cond - (< y padding) :collision-left - (> y (- height padding)) :collision-right - :else :moving))] - (go-loop - (let [tick (! vel-out [vel-xn vel-yn]) - (>! game-state - (cond - (= bs-x :gameover) :gameover - (or (= bs-x :collision-left) (= bs-x :collision-right) - (= bs-y :collision-left) (= bs-y :collision-right)) :collision - :else :moving)))))) - -(defn renderer [game-state pos pl-pos pr-pos] - (let [ball-el (dom/by-id "ball") - state-el (dom/by-id "state") - lpaddle-el (dom/by-id "lpaddle") - rpaddle-el (dom/by-id "rpaddle")] - (go-loop - (let [[x y] (! ticks (! pos-out pos-next)))) + + (defn paddle-positioner [keycodes pos-in pos-out] + (let [keys (h/key-chan keycodes)] + (go-loop + (let [pos (! pos-out + (condp = ( y (+ paddle-y padding)) (< y (- (+ paddle-y paddle-size) padding)))) + + (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) + (> x (- width ef-paddle-width)) + (if (in-y-range? y rpaddle-y) :collision-right :gameover) + :else :moving)) + + (defn detect-y-collision [y] + (cond + (< y padding) :collision-left + (> y (- height padding)) :collision-right + :else :moving)) + + (defn collision? [x-state y-state] + (or (= x-state :collision-left) (= x-state :collision-right) + (= y-state :collision-left) (= y-state :collision-right))) + + (defn adjust-vel [state v] + (condp = state + :collision-left (abs v) + :collision-right (- (abs v)) + :moving v + :gameover 0)) + + (go-loop + (let [tick (! vel-out [vel-xn vel-yn]) + (>! game-state + (cond + (= x-state :gameover) :gameover + (collision? x-state y-state) :collision + :else :moving))))) + + (defn renderer [ticks game-state pos pl-pos pr-pos] + (let [ball-el (dom/by-id "ball") + state-el (dom/by-id "state") + lpaddle-el (dom/by-id "lpaddle") + rpaddle-el (dom/by-id "rpaddle") + fps-el (dom/by-id "fps")] + (go-loop + (let [fps (/ 1000 (close? + m (reify + Mux + (muxch* [_] ch) + + Mult + (tap* [_ ch close?] (swap! cs assoc ch close?) nil) + (untap* [_ ch] (swap! cs dissoc ch) nil) + (untap-all* [_] (reset! cs {}) nil)) + dchan (chan 1) + dctr (atom nil) + done #(when (zero? (swap! dctr dec)) + (put! dchan true))] + (go (loop [] + (let [val (