Add game config management with keybinding for reloading

This commit is contained in:
Joseph Ferano 2026-08-16 17:17:26 +07:00
parent 5c5d158782
commit ac7385c498
6 changed files with 47 additions and 27 deletions

View File

@ -2,8 +2,9 @@
((clojure-mode ((clojure-mode
. ((cider-clojure-cli-parameters . "-M:common:dev") . ((cider-clojure-cli-parameters . "-M:common:dev")
(cider-inject-dependencies-at-jack-in . nil) (cider-inject-dependencies-at-jack-in . nil)))
(eval (nil
. ((eval
. (progn . (progn
(unless (fboundp 'clj-watch) (unless (fboundp 'clj-watch)
(load (expand-file-name (load (expand-file-name
@ -20,12 +21,18 @@
(interactive) (interactive)
(cider-interactive-eval "(engine/clear-error!)")) (cider-interactive-eval "(engine/clear-error!)"))
(defun clj-game-reload-config ()
"Re-read config-path and re-init the running game's state from it."
(interactive)
(cider-interactive-eval "(engine/reload-config!)"))
(unless (boundp 'clj-game-mode-map) (unless (boundp 'clj-game-mode-map)
(defvar clj-game-mode-map (defvar clj-game-mode-map
(let ((m (make-sparse-keymap))) (let ((m (make-sparse-keymap)))
(define-key m (kbd "C-c C-w") #'clj-watch) (define-key m (kbd "C-c g w") #'clj-watch)
(define-key m (kbd "C-c C-M-r") #'clj-game-run-main) (define-key m (kbd "C-c g r") #'clj-game-run-main)
(define-key m (kbd "C-c C-M-e") #'clj-game-clear-error) (define-key m (kbd "C-c g e") #'clj-game-clear-error)
(define-key m (kbd "C-c g c") #'clj-game-reload-config)
m))) m)))
(unless (fboundp 'clj-game-mode) (unless (fboundp 'clj-game-mode)
@ -34,4 +41,4 @@
:lighter " Game" :lighter " Game"
:keymap clj-game-mode-map)) :keymap clj-game-mode-map))
(clj-game-mode 1)))))) (clj-game-mode 1)))))))

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/.cpcache/ /.cpcache/
/.nrepl-port /.nrepl-port
/source-assets/

View File

@ -7,9 +7,10 @@
{:jvm-opts ["--enable-native-access=ALL-UNNAMED" {:jvm-opts ["--enable-native-access=ALL-UNNAMED"
"-Draylib.path=/home/joe/.local/bin/odin/vendor/raylib/linux/libraylib.so.600"]} "-Draylib.path=/home/joe/.local/bin/odin/vendor/raylib/linux/libraylib.so.600"]}
:run :run
{:jvm-opts ["--enable-native-access=ALL-UNNAMED" {:main-opts ["-m" "game"]}
"-Draylib.path=/home/joe/.local/bin/odin/vendor/raylib/linux/libraylib.so.600"]
:main-opts ["-m" "game"]} :sprite-atlas
{:main-opts ["-m" "sprite-atlas"]}
:dev :dev
{:extra-deps {nrepl/nrepl {:mvn/version "1.7.0"} {:extra-deps {nrepl/nrepl {:mvn/version "1.7.0"}

View File

@ -5,30 +5,39 @@
[watch :as w])) [watch :as w]))
(defonce ^:private last-error (atom nil)) (defonce ^:private last-error (atom nil))
(defonce ^:private game-state (atom nil))
(defonce ^:private game-config (atom nil))
(defn clear-error! (defn clear-error! []
"Call from the REPL to resume the loop after an error froze it."
[]
(reset! last-error nil)) (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! (defn run-game!
[{:keys [title width height config-path init input update draw watch-fn] [{:keys [title width height config-path init input update draw watch-fn]
:or {title "Untitled" width 1200 height 900 watch-fn (constantly nil)}}] :or {title "Untitled" width 1200 height 900 watch-fn (constantly nil)}}]
(rl/set-trace-log-level! rl/log-warning) (rl/set-trace-log-level! rl/log-warning)
(rl/init-window! width height title) (rl/init-window! width height title)
(rl/set-target-fps! 60) (rl/set-target-fps! 60)
(let [state (atom (init (edn/read-string (slurp config-path))))] (let [config (edn/read-string (slurp config-path))]
(reset! game-config {:config-path config-path :config config})
(reset! game-state (init config))
(while (not (rl/window-should-close?)) (while (not (rl/window-should-close?))
(if @last-error (if @last-error
(Thread/sleep 50) (Thread/sleep 50)
(let [config (:config @game-config)]
(rl/with-drawing! (rl/with-drawing!
(try (try
(swap! state input) (swap! game-state #(input config %))
(swap! state update) (swap! game-state #(update config %))
(draw @state) (draw config @game-state)
(w/watch! (watch-fn @state)) (w/watch! (watch-fn config @game-state))
(catch Throwable t (catch Throwable t
(println t) (println t)
(reset! last-error t) (reset! last-error t)
(w/watch! (merge (watch-fn @state) {:error t}))))))) (w/watch! (merge (watch-fn config @game-state) {:error t}))))))))
(rl/close-window!))) (rl/close-window!)))

View File

@ -9,18 +9,18 @@
(defn init-game [config] (defn init-game [config]
{:color-idx 0}) {:color-idx 0})
(defn handle-game-input [game] (defn handle-game-input [config game]
(when (rl/key-pressed? rl/key-r)) (when (rl/key-pressed? rl/key-r))
(when (rl/mouse-button-down? rl/mouse-button-left)) (when (rl/mouse-button-down? rl/mouse-button-left))
game) game)
(defn update-game [game] (defn update-game [config game]
game) game)
(defn draw-game [game] (defn draw-game [config game]
(rl/clear-background!* rl/cornflower-blue)) (rl/clear-background!* rl/cornflower-blue))
(defn watch-game [game] (defn watch-game [config game]
{:color-idx (:color-idx game)}) {:color-idx (:color-idx game)})
(defn -main [& _args] (defn -main [& _args]

2
src/user.clj Normal file
View File

@ -0,0 +1,2 @@
(ns user
(:require [game]))