     ctx))
 
 ;;-----------------------------------------------------------------------------
+;; Moveable Objects
+;;-----------------------------------------------------------------------------
 
-(def ctx (.getContext (by-id "canvas") "2d"))
-(def scale-w 800)
-(def scale-h 450)
+(defprotocol IMovable
+  (move [_]))
 
-(def objects
+(extend-type Ball
+  IMovable
+  (move [{:keys [x y vx vy radius] :as ball}]
+    (let [low radius
+          vx (if (< low x (- SCALE-W radius)) vx (* -1 vx))
+          vy (if (< low y (- SCALE-H radius)) vy (* -1 vy))]
+      (assoc ball :x (+ x vx) :y (+ y vy) :vx vx :vy vy))))
+
+;;-----------------------------------------------------------------------------
+;; Controllable Objects
+;;-----------------------------------------------------------------------------
+
+(defprotocol IControllable
+  (control! [_ event]))
+
+(extend-type Paddle
+  IControllable
+  (control! [{:keys [y vy] :as paddle} event]
+    (case event
+      :up (assoc paddle :y (- y vy))
+      :down (assoc paddle :y (+ y vy))
+      paddle)))
+
+;;-----------------------------------------------------------------------------
+;; Game State
+;;-----------------------------------------------------------------------------
+
+(def state
   ;; Order matters
-  {:background (Rect. 0 0 scale-w scale-h "black")
-   :s1         (Rect. 10 10 110 100 "rgb(200, 0, 0)")
-   :s2         (Rect. 60 60 110 100 "rgba(0,0,200,0.5)")
-   :paddle-1   (Paddle. 20 (- scale-h 120) 20 100 "dodgerblue")
-   :paddle-2   (Paddle. (- scale-w 40) 20 20 100 "dodgerblue")
-   :border     (Frame. 0 0 scale-w scale-h "dodgerblue" 2)})
+  (atom {:background (Rect. 0 0 SCALE-W SCALE-H "black")   ;; use div behind canvas
+         :border     (Frame. 0 0 SCALE-W SCALE-H "#333" 2) ;; use div behind canvas
+         :paddle-1   (Paddle. 20 (- SCALE-H 120) 20 100 2 "dodgerblue")
+         :paddle-2   (Paddle. (- SCALE-W 40) 20 20 100 2 "peru")
+         :ball       (Ball. 400 225 13 3 2 "lime")}))
 
+;;-----------------------------------------------------------------------------
+;; Animation
 ;;-----------------------------------------------------------------------------
 
 (defn draw-phase!
   [ctx]
-  (.clearRect ctx 0 0 scale-w scale-h)
-  (doseq [o (vals objects)]
+  (.clearRect ctx 0 0 SCALE-W SCALE-H)
+  (doseq [o (vals @state)]
     (when (satisfies? IDrawable o)
       (draw! o ctx))))
 
+(defn move-phase!
+  []
+  (swap! state #(assoc % :ball (move (:ball %)))))
+
+(defn animate!
+  []
+  (move-phase!)
+  (draw-phase! ctx)
+  (.requestAnimationFrame js/window animate!))
+
+;;-----------------------------------------------------------------------------
+;; Control
+;;-----------------------------------------------------------------------------
+
 (defn resize!
   [e]
-  ;; Maintains 16x9
   (let [w (- (.-innerWidth js/window) 40)
         h (- (int (/ (* w 9) 16)) 40)]
     (-> (by-id "canvas")
-        ;; (style! "width" (str w "px"))
-        ;; (style! "height" (str h "px"))
         (attr! "width" w)
         (attr! "height" h))
-    (.scale ctx (/ w scale-w) (/ h scale-h))
+    (.scale ctx (/ w SCALE-W) (/ h SCALE-H))
     (draw-phase! ctx)))
 
 (defn- main
   []
   (println "Welcome to the Canvas Scratch App.")
   (listen! js/window "resize" resize!)
-  (draw-phase! ctx)
   (resize! nil)
-  (draw-phase! ctx))
+  (animate!))
 
 (set! (.-onload js/window) main)

      (aset ctx "fillStyle" color)
      (.fillRect ctx x y width height))
    ctx))

(extend-type Rect
  IDrawable

;; Canvas Context
;;-----------------------------------------------------------------------------

(def ctx (.getContext (by-id "canvas") "2d"))
(def SCALE-W 800)
(def SCALE-H 450)

;;-----------------------------------------------------------------------------

(defrecord Rect [x y width height color])
(defrecord Frame [x y width height color frame-width])
(defrecord Paddle [x y width height vy color])
(defrecord Ball [x y radius vx vy fill-color])

;;-----------------------------------------------------------------------------
;; Drawable Objects
;;-----------------------------------------------------------------------------

(defprotocol IDrawable
