     (.closePath ctx)
     (.restore ctx)))
 
-;;-----------------------------------------------------------------------------
 ;; Moveable Objects
-;;-----------------------------------------------------------------------------
 
 (defprotocol IMovable
   (move [_]))

  [{:keys [ball] :as state}]
  (merge state {:ball (move ball)}))

(defn hit?
  [{x :x y :y vx :vx radius :radius :as ball}
   {x1 :x y1 :y w :width h :height :as paddle}
   dir]
  (let [x2 (+ x1 w)
        y2 (+ y1 h)]
    (or (and (= dir :right)
             (<= y1 y y2)
             (< vx 0)
             (>= radius (dist x2 y x y)))
        (and (= dir :left)
             (<= y1 y y2)
             (> vx 0)
             (>= radius (dist x1 y x y)))
        false)))

(defn collision-phase!
  [{:keys [ball paddle-1 paddle-2 mode] :as state}]
  (if (or (hit? ball paddle-1 :right)
          (hit? ball paddle-2 :left))
    (let [{:keys [vx vy]} ball
          delta (rand-nth [0.3 0.5 0.7])
          vxf (if (< vx 0) dec inc)

(def SCORE_FONT "60px Helvetica")
(def SCORE_COLOR "slategray")

(def KEYBOARD {27 :abort 32 :space})

;; Math

(defn sqr
  [x]
