diff --git a/project.clj b/project.clj
index 126bf71..3948798 100644
--- a/project.clj
+++ b/project.clj
@@ -7,7 +7,7 @@
:source-paths ["src/clj"]
:dependencies [[org.clojure/clojure "1.5.1"]
[domina "1.0.2-SNAPSHOT"]
- [org.clojure/clojurescript "0.0-1878"]
+ [org.clojure/clojurescript "0.0-1844"]
[org.clojure/core.async "0.1.222.0-83d0c2-alpha"]]
:plugins [[lein-cljsbuild "0.3.3"]]
diff --git a/resources/public/index.html b/resources/public/index.html
index 9c3a54d..8d18882 100644
--- a/resources/public/index.html
+++ b/resources/public/index.html
@@ -8,6 +8,9 @@
+ FPS:
+ Position:
+ O
diff --git a/src/clj/frpong/core.clj b/src/clj/frpong/core.clj
index e58c1fc..568c47b 100644
--- a/src/clj/frpong/core.clj
+++ b/src/clj/frpong/core.clj
@@ -1,6 +1,6 @@
(ns frpong.core)
-(defn foo
- "I don't do a whole lot."
- [x]
- (println x "Hello, World!"))
+(defmacro go-loop [& body]
+ `(cljs.core.async.macros/go
+ (while true
+ ~@body)))
diff --git a/src/cljs/frpong/core.cljs b/src/cljs/frpong/core.cljs
index 924c138..af45b90 100644
--- a/src/cljs/frpong/core.cljs
+++ b/src/cljs/frpong/core.cljs
@@ -1,20 +1,61 @@
(ns frpong.core
- (:require [cljs.core.async :as async
- :refer [! chan put!]]
- [domina :as dom]
+ (: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]]))
+ (:require-macros [cljs.core.async.macros :as m :refer [go]]
+ [frpong.core :refer (go-loop)]))
+(defn positioner [tick-chan vel-chan pos-chan-in pos-chan-out]
+ (go-loop
+ (let [tick (! pos-chan-out pos-next))))
-(defn event-chan [event-type]
- (let [c (chan)]
- (ev/listen! js/document event-type
- (fn [e] (put! c e)))
- c))
+(defn collision-detector [width height tick-chan pos-chan vel-chan-in vel-chan-out]
+ (go-loop
+ (let [tick (! vel-chan-out
+ (cond
+ (< xn 0) [(- vel-x) vel-y]
+ (< yn 0) [vel-x (- vel-y)]
+ (> xn width) [(- vel-x) vel-y]
+ (> yn height) [vel-x (- vel-y)]
+ :else [vel-x vel-y])))))
(defn ^:export init []
- (let [mm-chan (event-chan :mousemove)]
- (go
- (while true
- (let [e (! pos-chan init-pos))
+ (go (>! vel-chan init-vel))
+
+ (go-loop
+ (let [[x y] (map int (! 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)]))
+
+(defn now []
+ (.valueOf (js/Date.)))
+
+(defn put-all! [cs x]
+ (doseq [c cs]
+ (put! c x)))
+
+(defn cconj [v c1]
+ (let [c2 (chan)]
+ (go
+ (>! c2 v)
+ (while true
+ (>! c2 (! c (f (! c v))))
+ c))
+
+(defn interval-chan
+ ([msecs]
+ (interval-chan msecs :leading))
+ ([msecs type]
+ (interval-chan (chan (dropping-buffer 1)) msecs type))
+ ([c msecs type]
+ (condp = type
+ :leading (go-loop
+ (>! c (now))
+ (! c (now))))
+ c))
+
+(defn throttle
+ ([source control]
+ (throttle (chan) source control))
+ ([c source control]
+ (go
+ (loop [state ::init last nil cs [source]]
+ (let [[_ sync] cs]
+ (let [[v sc] (alts! cs)]
+ (condp = sc
+ source (condp = state
+ ::init (do (>! c v)
+ (recur ::throttling last
+ (conj cs control)))
+ ::throttling (recur state v cs))
+ sync (if last
+ (do (>! c last)
+ (recur state nil
+ (conj (pop cs) control)))
+ (recur ::init last (pop cs))))))))
+ c))
+
+(defn debounce
+ ([source msecs]
+ (debounce (chan) source msecs))
+ ([c source msecs]
+ (go
+ (loop [state ::init cs [source]]
+ (let [[_ threshold] cs]
+ (let [[v sc] (alts! cs)]
+ (condp = sc
+ source (condp = state
+ ::init
+ (do (>! c v)
+ (recur ::debouncing
+ (conj cs (timeout msecs))))
+ ::debouncing
+ (recur state
+ (conj (pop cs) (timeout msecs))))
+ threshold (recur ::init (pop cs)))))))
+ c))
+
+(defn after-last
+ ([source msecs]
+ (after-last (chan) source msecs))
+ ([c source msecs]
+ (go
+ (loop [cs [source]]
+ (let [[_ toc] cs]
+ (let [[v sc] (alts! cs :priority true)]
+ (recur
+ (condp = sc
+ source (conj (if toc (pop cs) cs)
+ (timeout msecs))
+ toc (do (>! c (now)) (pop cs))))))))
+ c))
+
+(defn fan-in
+ ([ins] (fan-in (chan) ins))
+ ([c ins]
+ (go (while true
+ (let [[x] (alts! ins)]
+ (>! c x))))
+ c))
+
+(defn distinct-chan
+ ([source] (distinct-chan (chan) source))
+ ([c source]
+ (go
+ (loop [last ::init]
+ (let [v (! c v))
+ (recur v))))
+ c))
+
+(defn event-chan [event-type]
+ (let [c (chan)]
+ (ev/listen! js/document event-type #(put! c %))
+ c))
+
+(defn frame-chan []
+ (let [c (chan (sliding-buffer 1000))
+ step (fn step [ts] (do (put! c ts) (.requestAnimationFrame js/window step)))]
+ (.requestAnimationFrame js/window step)
+ c))
+
+(defn counting-chan [source]
+ (let [c (chan)]
+ (go
+ (loop [count 0]
+ (! c count)
+ (recur (inc count))))
+ c))
+
+(defn diff-chan [source]
+ (let [c (chan)]
+ (go
+ (let [start (! c (- ts start))
+ (recur ts)))))
+ c))