(ns frpong.core (:require [frpong.helpers :as h] [cljs.core.async :as async :refer [! chan put! close! sliding-buffer dropping-buffer timeout]] [domina :as dom :refer [log]] [domina.events :as ev]) (:require-macros [cljs.core.async.macros :as m :refer [go]] [frpong.core :refer (go-loop)])) ;; ;; Signal Diagram ;; ;; +---------------------+ ;; | +-------------+ | ;; | | | | ;; v v | | ;; +----------+ vel-chan | | ;; +-->|c-detector+----------+ | ;; | +----------+ | | ;; | +-----------------+ | ;; | | +-----------------+ ;; | | | | ;; | v v | ;; +---------+ frame-chan +------+ tick-chan | +----------+ pos-chan | ;; |frame-gen+------------>|ticker+-----------+-->|positioner+--------------+ ;; +---------+ +------+ +----------+ | ;; +---------------------+ ;; | ;; v ;; +----------+ ;; | renderer | ;; +----------+ (defn abs [x] (.abs js/Math x)) (defn tick-chan [frames] (let [c (chan)] (go (loop [prev (! c t)) (recur t)))) c)) (defn ball-positioner [ticks vel pos-in pos-out] (go-loop (let [tick (! pos-out pos-next)))) (defn collision-detector [{:keys [width height padding]} ticks ball-state pos pl-pos pr-pos vel-in vel-out] (let [adjust-v (fn [p v size] (cond (< p padding) [(abs v) :collision] (> p (- size padding)) [(- (abs v)) :collision] :else [v :moving]))] (go-loop (let [tick (! vel-out [vel-xn vel-yn]) (>! ball-state (if (or (= bs-x :collision) (= bs-y :collision)) :collision :moving)))))) (defn paddle-positioner [keycodes max-y movement pos-in pos-out] (let [keys (h/key-chan keycodes)] (go-loop (let [dir (! pos-out (condp = dir :up (max (- pos movement) 0) :down (min (+ pos movement) max-y))))))) (defn renderer [ball-state pos vel pl-pos pr-pos] (let [pos-el (dom/by-id "pos") vel-el (dom/by-id "vel") ball-el (dom/by-id "ball") lpaddle-el (dom/by-id "lpaddle") rpaddle-el (dom/by-id "rpaddle")] (go-loop (let [[x y] (