(defn
create-game
"Returns a game object. You can pass an options map with the following:\n \n :parent - A DOM element in which to place the canvas\n :debug? - Whether or not to enable debug mode\n (defaults to true if :optimizations are set to :none)\n :mode - Either :2d or :webgl (defaults to :2d)"
([width height] (create-game width height {}))
([width
height
{:keys [parent debug? mode],
:or {debug? (not js/COMPILED), mode :2d},
:as opts}]
(if
debug?
(js/console.log
(str
"Debug mode is enabled. If things are slow, try passing "
"{:debug? false} to the third argument of create-game."))
(set! (.-disableFriendlyErrors js/p5) true))
(let
[*hidden-state
(atom
{:screen nil,
:renderer nil,
:canvas nil,
:listeners [],
:total-time 0,
:delta-time 0,
:pressed-keys #{},
:assets {}})
setup-finished?
(promise-chan)
parent-opts
(if debug? {:debug? true} {})]
(reify
Game
(start
[this]
(when-let [renderer (get-renderer this)] (.remove renderer))
(run! events/unlistenByKey (:listeners @*hidden-state))
(swap! *hidden-state assoc :listeners [])
(js/p5.
(fn
[renderer]
(set!
(.-setup renderer)
(fn
[]
(let
[canvas-wrapper
(cond->
(.createCanvas
renderer
width
height
(case
mode
:2d
(.-P2D renderer)
:webgl
(.-WEBGL renderer)))
parent
(.parent parent))
canvas
(.-canvas canvas-wrapper)]
(.removeAttribute canvas "style")
(swap!
*hidden-state
assoc
:renderer
renderer
:canvas
canvas))
(put! setup-finished? true)))
(set!
(.-draw renderer)
(fn
[]
(swap!
*hidden-state
(fn
[hidden-state]
(let
[time (.millis renderer)]
(assoc
hidden-state
:total-time
time
:delta-time
(- time (:total-time hidden-state))))))
(.clear renderer)
(some-> this get-screen on-render)))))
(listen
this
"keydown"
(fn
[e]
(swap! *hidden-state update :pressed-keys conj (.-keyCode e))))
(listen
this
"keyup"
(fn
[e]
(if
(contains? #{91 93} (.-keyCode e))
(swap! *hidden-state assoc :pressed-keys #{})
(swap!
*hidden-state
update
:pressed-keys
disj
(.-keyCode e)))))
(listen
this
"blur"
(fn* [] (swap! *hidden-state assoc :pressed-keys #{}))))
(listen
[this listen-type listener]
(swap!
*hidden-state
update
:listeners
conj
(events/listen js/window listen-type listener)))
(render
[this content]
(when-let
[renderer (get-renderer this)]
(draw-sketch! this renderer content parent-opts)))
(pre-render
[this image-name width height content]
(when-let
[renderer (get-renderer this)]
(let
[object (.createGraphics renderer width height)]
(draw-sketch! this object content parent-opts)
(swap! *hidden-state update :assets assoc image-name object)
object)))
(load-image
[this path]
(when-let
[renderer (get-renderer this)]
(let
[object (.loadImage renderer path (fn []))]
(swap! *hidden-state update :assets assoc path object)
object)))
(load-tiled-map
[this map-name]
(when-let
[renderer (get-renderer this)]
(let
[object (.loadTiledMap renderer map-name (fn []))]
(swap! *hidden-state update :assets assoc map-name object)
object)))
(load-model
[this path]
(when-let
[renderer (get-renderer this)]
(let
[object (.loadModel renderer path (fn []))]
(swap! *hidden-state update :assets assoc path object)
object)))
(get-screen [this] (:screen @*hidden-state))
(set-screen
[this screen]
(go
(<! setup-finished?)
(some-> this get-screen on-hide)
(swap! *hidden-state assoc :screen screen)
(on-show screen)))
(get-renderer [this] (:renderer @*hidden-state))
(get-canvas [this] (:canvas @*hidden-state))
(get-total-time [this] (:total-time @*hidden-state))
(get-delta-time [this] (:delta-time @*hidden-state))
(get-pressed-keys [this] (:pressed-keys @*hidden-state))
(get-width
[this]
(when-let [renderer (get-renderer this)] (.-width renderer)))
(get-height
[this]
(when-let [renderer (get-renderer this)] (.-height renderer)))
(set-size
[this width height]
(when-let
[renderer (get-renderer this)]
(.resizeCanvas renderer width height)))
(get-asset [game name] (get-in @*hidden-state [:assets name]))))))