                                 :opt [:shape/width :shape/height]))
 
 (s/def :input/intended-direction #{:up :left :down :right})
-(s/def :input/intended-direction-set (s/coll-of :input/intended-direction :kind set?))
-(s/def :input/intended-move-direction :input/intended-direction-set)
-(s/def :input/intended-fire-direction :input/intended-direction-set)
+(s/def :input/intended-move-direction (s/coll-of :input/intended-direction :kind set?))
+(s/def :input/intended-fire-direction (s/coll-of :input/intended-direction))
 
 (s/def :component/input (s/keys :req [:input/intended-move-direction :input/intended-fire-direction]))
 

    (swap! next-entity-id inc)
    id-to-return))

(sm/defn make-entity :- Entity
  [entity-map]
  (assoc entity-map :id (get-next-entity-id)))

(sm/defn make-input :- Input
  []
  {:intended-move-direction #{}
   :intended-fire-direction []})

(sm/defn make-weapon :- Weapon
  [fire-direction projectile-color]
  {:last-attack-timestamp 0
   ; XXXX nuke fire-direction arg, just temporary thing for testing
   :fire-direction        fire-direction
   :shots-per-second      21
   :shot-speed            5
   :projectile-color      projectile-color
   :projectile-shape      {:type   :rectangle
                           :width  10
                           :height 10}})

;; Public

(sm/defn player :- Entity
  [x y]
  (make-entity
    {:shape       {:width  25
                   :height 25
                   :type   :rectangle
                   :center {:x x :y y}}
     :motion      {:velocity             {:x 0 :y 0}
                   :affected-by-friction true
                   :direction            nil
                   :max-acceleration     2.0
                   :max-speed            11}
     :collision   {:type :good-guy}
     :render-info {:fill 0x333333}
     :weapon      (make-weapon nil 0x666666)
     :input       (make-input)}))

(sm/defn monster :- Entity
  [x y]
  (make-entity
    {:shape       {:width  25
                   :height 25
                   :type   :rectangle
                   :center {:x x :y y}}
     :motion      {:velocity             {:x 0 :y 0}
                   :affected-by-friction true
                   :direction            nil
                   :max-acceleration     1.5
                   :max-speed            4}
     :collision   {:type :bad-guy}
     :weapon      nil #_(make-weapon (- (/ Math/PI 2))
                                     0xFF0A00)
     ; xxx not schema'd / standardized yet, these are just some example values
     :ai          {:movement :basic
                   :attack   :basic}
     :render-info {:fill 0xB22822}}))

(sm/defn wall :- Entity
  [x y width height]
  (make-entity
    {:shape       {:width  width
                   :height height
                   :type   :rectangle
                   :center {:x x :y y}}
     :collision   {:type :obstacle}
     :render-info {:fill 0x333333}}))

(sm/defn projectile :- Entity
  [owner-id position collides-with projectile-shape projectile-color x-velocity y-velocity]
  (make-entity
    {:shape       (assoc projectile-shape
                         :center position)
     :owner-id    owner-id
     :collision   {:type                 :projectile
                   :collides-with        collides-with
                   :destroyed-on-contact true}
     :render-info {:fill projectile-color}
     :motion      {:velocity             {:x x-velocity
                                          :y y-velocity}
                   :direction            nil
                   :affected-by-friction false
                   :max-speed            (max x-velocity y-velocity)
                   :max-acceleration     0}}))

                                    :component/weapon
                                    :component/input]))

;; Private functions

(defonce next-entity-id (atom 0))

