                               (>= radius (dist x y1 x y)))))))
 
 (defn collision-phase!
-  [{:keys [ball paddle-1 paddle-2] :as state}]
+  [{:keys [ball paddle-1 paddle-2 mode] :as state}]
   (if (or (hit? ball paddle-1)
           (hit? ball paddle-2))
     (assoc state :ball (assoc ball :vx (* -1 (:vx ball))))

(defprotocol IDrawable
  (draw! [_ ctx]))

(extend-type Score
  IDrawable
  (draw! [{:keys [score x y font color] :as Score} ctx]
    (aset ctx "font" font)
    (aset ctx "fillStyle" color)
    (aset ctx "textAlign" "center")
    (.fillText ctx (str score) x y)
    ctx))

(extend-type Paddle
  IDrawable
  (draw! [paddle ctx]
    (let [{:keys [color x y width height]} paddle]
      (aset ctx "fillStyle" color)
      (.fillRect ctx x y width height))
    ctx))

(extend-type Ball
  IDrawable
  (draw! [{:keys [x y radius fill-color] :as ball} ctx]
    (aset ctx "fillStyle" fill-color)
    (.beginPath ctx)
    (.arc ctx x y radius 0 (* 2 js/Math.PI) false)
    (.fill ctx)
    (.closePath ctx)
    ctx))

(extend-type Rect
  IDrawable
  (draw! [rect ctx]
    (let [{:keys [color x y width height]} rect]
      (aset ctx "lineWidth" "0.5")
      (aset ctx "fillStyle" color)
      (aset ctx "strokeStyle" "black")
      (.fillRect ctx x y width height)
      (.strokeRect ctx x y width height))
    ctx))

(extend-type Frame
  IDrawable
  (draw! [frame ctx]
    (let [{:keys [color x y width height frame-width]} frame]
      (aset ctx "lineWidth" (str frame-width))
      (aset ctx "strokeStyle" color)
      (.strokeRect ctx x y width height))
    ctx))

;;-----------------------------------------------------------------------------
;; Moveable Objects

    (when-let [event (<! ch)]
      (cond
        (contains? #{:up :down} event)
        (when-not (:pause? @state)
          (swap! state (fn [{id :current-paddle :as state}]
                         (assoc state id (control! (id state) event)))))

        (contains? #{:paddle-1 :paddle-2} event)
        (when-not (:pause? @state)
          (swap! state assoc :current-paddle event))

        (= :abort event)
        (swap! state #(if (:pause? %)
                        (assoc % :pause? false)
                        (assoc % :mode :game-start)))

        (= :space event)
        (swap! state #(if (= (:mode %) :game-start)
                        (merge % resets {:mode :playing})
                        (assoc % :pause? (not (:pause? %)))))

        :else
        (println "Unhandled event:" event))
