 
 (defn animate-loop!
   [state ctx]
-  ;; if start-mode:
-  ;; ...
-  ;; if play-mode:
-  (swap! state #(-> % move-phase! collision-phase! score-phase!))
-  ;; if win-mode:
-  ;; ...
-  (draw-phase! state ctx)
+  (when-not (:pause? @state)
+    (when (= (:mode @state) :playing)
+      (swap! state #(-> % move-phase! collision-phase! score-phase!)))
+    (draw-phase! state ctx))
   (.requestAnimationFrame js/window (partial animate-loop! state ctx)))
 
 ;;-----------------------------------------------------------------------------

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

(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 oob?])
(defrecord Score [score x y font color])

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

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

(extend-type GameStartScreen
  IDrawable
  (draw! [_ ctx]
    (.save ctx)
    (aset ctx "textAlign" "center")
    ;;
    (aset ctx "font" "60px Helvetica")
    (aset ctx "fillStyle" "peru")
    (.fillText ctx "Welcome to Pong!" (/ SCALE-W 2) 100)
    ;;
    (aset ctx "font" "italic 14px Helvetica")
    (aset ctx "fillStyle" "slategray")
    (.fillText ctx "single player" (/ SCALE-W 2) 150)
    ;;
    (aset ctx "font" "20px Helvetica")
    (aset ctx "fillStyle" "dodgerblue")
    (.fillText ctx "Press the spacebar to start." (/ SCALE-W 2) 300)
    ;;
    (aset ctx "font" "italic 12px Helvetica")
    (aset ctx "fillStyle" "slategray")
    (.fillText ctx "[ Right ] and [ Left ] arrows to switch paddles." (/ SCALE-W 2) 370)
    (.fillText ctx "[ Up ] and [ Down ] arrows to move paddles." (/ SCALE-W 2) 390)
    (.fillText ctx "[ Spacebar ] to pause ." (/ SCALE-W 2) 410)
    (.fillText ctx "[ Escape ] to quit." (/ SCALE-W 2) 430)
    (.restore ctx)))

(extend-type Line
  IDrawable
  (draw! [{:keys [x1 y1 x2 y2 color] :as line} ctx]
    (.save ctx)
    (aset ctx "lineWidth" "1")
    (aset ctx "strokeStyle" color)
    (.setLineDash ctx (array 1 2))
    (.beginPath ctx)
    (.moveTo ctx x1 y1)
    (.lineTo ctx x2 y2)
    (.stroke ctx)
    (.closePath ctx)
    (.restore ctx)))

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

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

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

(extend-type Rect
  IDrawable
  (draw! [{:keys [color x y width height]} ctx]
    (.save ctx)
    (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)
    (.restore ctx)))

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

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