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
. ((cider-clojure-cli-parameters . "-M:common:dev")
(cider-inject-dependencies-at-jack-in . nil)
(eval
(cider-inject-dependencies-at-jack-in . nil)))
(nil
. ((eval
. (progn
(unless (fboundp 'clj-watch)
(load (expand-file-name
@ -20,12 +21,18 @@
(interactive)
(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)
(defvar clj-game-mode-map
(let ((m (make-sparse-keymap)))
(define-key m (kbd "C-c C-w") #'clj-watch)
(define-key m (kbd "C-c C-M-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 w") #'clj-watch)
(define-key m (kbd "C-c g r") #'clj-game-run-main)
(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)))
(unless (fboundp 'clj-game-mode)
@ -34,4 +41,4 @@
:lighter " Game"
:keymap clj-game-mode-map))
(clj-game-mode 1))))))
(clj-game-mode 1)))))))

1
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

2
src/user.clj Normal file
View File

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