siam-farmer/src/engine.clj

84 lines
2.7 KiB
Clojure

(ns engine
(:require
[clojure.edn :as edn]
[rl :as rl]
[watch :as w]))
(defonce last-error (atom nil))
(defonce game-state (atom nil))
(defonce game-config (atom nil))
(defonce texture-cache (atom {}))
;; (reset! texture-cache {})
(defn load-texture-once [id path]
(or (@texture-cache path)
(let [t (assoc (rl/load-texture path) :name id)]
(swap! texture-cache assoc path t)
t)))
(defn load-texture-once [id path]
(or (@texture-cache path)
(let [t (assoc (rl/load-texture path) :name id)]
(swap! texture-cache assoc path t)
t)))
(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 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! rl/log-warning)
(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})
(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 #(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
(doseq [[_ tex] @texture-cache]
(rl/unload-texture! tex))
(unload @game-state))
(catch Throwable t
(report-exception! t)))
(rl/close-window!)
(reset! texture-cache {})
(reset! last-error nil)
(reset! game-state nil)
(reset! game-config nil)))))