siam-farmer/src/engine.clj

70 lines
2.4 KiB
Clojure

(ns engine
(:require
[clojure.edn :as edn]
[rl :as rl]
[watch :as w]))
(defonce ^:private last-error (atom nil))
(defonce ^:private game-state (atom nil))
(defonce ^:private game-config (atom nil))
(defn report-exception!
"Stash the exception and print a marker line. Emacs watches the REPL output
for the marker and rethrows the stashed exception over nREPL, so it lands in
cider's stacktrace buffer instead of as an unreadable println. See
cider-error.el."
[^Throwable t]
(reset! last-error t)
(println "SIAM-REPORT-EXCEPTION"))
(defn clear-error! []
(reset! last-error nil))
(defn reload-config! []
(try
(swap! game-config #(assoc % :config (edn/read-string (slurp (:config-path %)))))
(catch Exception e
(println e))))
(defn run-game!
[{:keys [title width height config-path init input update draw unload watch-fn]
:or {title "Untitled" width 1200 height 900 watch-fn (constantly nil)}}]
(if (rl/window-ready?)
(println "Warning: Existing raylib window open, ignoring!")
(do
(rl/set-trace-log-level! 0)
(rl/init-window! width height title)
(rl/set-target-fps! 30)
(let [config (if config-path
(edn/read-string (slurp config-path))
{})]
(reset! game-config {:config-path config-path :config config})
;; TODO: We should actually not commit until the frame is complete, because if not we will re-enter
;; input and call it several times if update or draw throw
(try
(reset! game-state (init config))
(catch Throwable t
(report-exception! t)))
(while (not (rl/window-should-close?))
(if @last-error
(Thread/sleep 50)
(let [config (:config @game-config)]
(rl/with-drawing!
(try
(swap! game-state #(input config %))
(swap! game-state #(update config %))
(draw config @game-state)
(w/watch! (watch-fn config @game-state))
(catch Throwable t
(report-exception! t)
(w/watch! (merge (watch-fn config @game-state) {:error t}))))))))
(try
(when unload
(unload @game-state))
(catch Throwable t
(report-exception! t)))
(rl/close-window!)
(reset! last-error nil)
(reset! game-state nil)
(reset! game-config nil)))))