diff --git a/src/hottub/core.clj b/src/hottub/core.clj index b942d67..7198979 100644 --- a/src/hottub/core.clj +++ b/src/hottub/core.clj @@ -1,34 +1,25 @@ (ns hottub.core (:require [hottub.slick :as slick] [hottub.gs :as gs] - [hottub.resource :as res])) + [hottub.resource :as res] + [hottub.timeline :as tln])) (defn -main [& args] (res/start-resource-expiry-thread) (slick/start-game "Test game" {:state :game - :gs (gs/with-gs gs/gs-empty + :gs (gs/update-gs gs/gs-empty (gs/add-index :name) (gs/add-index :type) (gs/set-entity (gs/gen-id) {:type :sprite :x 50 :y 50 :image "res/man.png" :name :man}))})) -(defmethod slick/update-game :game [state input delta] - (let [gsnew - (gs/with-gs (:gs state) - (let [idman (first (gs/q :name :man)) - man (gs/entity idman)] - (loop [timeline (slick/input-timeline input)] - (let [[ts events] (first timeline) - timelinenext (next timeline)] - (doseq [{:keys [type action x y]} events] - (if (and (= type :mouse) (= action :move)) - (gs/set-entity idman (assoc man :x x :y y)))) - (if timelinenext - (recur timelinenext) - (slick/input-clear input ts))))) - (gs/get-gs))] - (assoc state :gs gsnew))) +(defmethod slick/update-game :game [state inputtln delta] + (assoc state :gs (gs/update-gs (:gs state) + (let [idman (first (gs/q :name :man)) + man (gs/entity idman)] + (if-let [input (tln/timeline-last-value inputtln)] + (gs/set-entity idman (assoc man :x (:mousex input) :y (:mousey input)))))))) (defmethod slick/render-game :game [state graphics] (gs/with-gs (:gs state) @@ -42,5 +33,5 @@ (defmethod slick/eval-with-bindings :default [state game f] (binding [g game s state] (let [gsnew (gs/with-gs (:gs state) (f) (gs/get-gs))] - (slick/game-setstate game (assoc state :gs gsnew))))) + (slick/game-setstate! game (assoc state :gs gsnew))))) diff --git a/src/hottub/slick.clj b/src/hottub/slick.clj index ca83568..76cc429 100644 --- a/src/hottub/slick.clj +++ b/src/hottub/slick.clj @@ -66,25 +66,30 @@ ; input (defprotocol InputTimeline (input-timeline [this]) - (input-clear [this tsfirst])) + (input-timeline-clear! [this])) -(defn- add-event [atln event] - (swap! atln tln/timeline-insert (u/timestamp) event)) - -(defn- add-key-event [atln skey action] - (if-let [key (get slick-key-to-key skey)] - (add-event atln {:type :key :action action :key key}))) - -(defn- add-mousebutton-event [atln sbutton action x y] - (if-let [button (get slick-mouse-to-mouse sbutton)] - (add-event atln {:type :mouse :action action :button button :x x :y y}))) (defn input-create [] - (let [atln (atom (timeline-create))] + (let [atln (atom (timeline-create)) + ainput (atom {:keys #{} :mousebuttons #{} :mousex 0 :mousey 0}) + add-input (fn [& swapargs] + (let [input (apply swap! ainput swapargs)] + (swap! atln tln/timeline-insert (u/timestamp) input))) + key-event (fn [skey pressed] + (if-let [key (get slick-key-to-key skey)] + (add-input update-in [:keys] (if pressed conj disj) key))) + mouse-event (fn [x y & [smouse pressed]] + (if-not x + (println x y smouse pressed)) + (add-input (fn [input] + (let [inputxy (assoc input :mousex x :mousey y)] + (if-let [mouse (get slick-mouse-to-mouse smouse)] + (update-in inputxy [:mousebuttons] (if pressed conj disj) mouse) + inputxy)))))] (reify InputTimeline (input-timeline [this] @atln) - (input-clear [this tsafter] (swap! atln timeline-after tsafter)) + (input-timeline-clear! [this] (u/reset-returning-old! atln (timeline-create))) ControlledInputReciever (inputEnded [this]) @@ -93,22 +98,16 @@ (setInput [this input]) KeyListener - (keyPressed [this skey c] (add-key-event atln skey :pressed)) - (keyReleased [this skey c] (add-key-event atln skey :released)) + (keyPressed [this skey c] (key-event skey true)) + (keyReleased [this skey c] (key-event skey false)) MouseListener - (mouseClicked [this sbutton x y count] - (add-mousebutton-event atln sbutton (if (= count 2) :double-click :click) x y)) - (mouseDragged [this oldx oldy newx newy]) - (mouseMoved [this oldx oldy newx newy] (add-event atln {:type :mouse - :action :move - :x newx - :y newy - :dx (- oldx newx) - :dy (- oldy newy)})) - (mousePressed [this sbutton x y] (add-mousebutton-event atln sbutton :down x y)) - (mouseReleased [this sbutton x y] (add-mousebutton-event atln sbutton :up x y)) - (mouseWheelMoved [this dy] (add-event atln {:type :mouse :action :wheel :distance dy}))))) + (mouseClicked [this sbutton x y count]) + (mouseDragged [this oldx oldy newx newy] (mouse-event newx newy)) + (mouseMoved [this oldx oldy newx newy] (mouse-event newx newy)) + (mousePressed [this sbutton x y] (mouse-event x y sbutton true)) + (mouseReleased [this sbutton x y] (mouse-event x y sbutton false)) + (mouseWheelMoved [this dy])))) (def modified-namespaces (ns-tracker ["src" "test"])) @@ -118,17 +117,16 @@ :init create :constructors {[String clojure.lang.PersistentArrayMap] [String]} :state state - :extends org.newdawn.slick.BasicGame - :implements [hottub.slick.InputTimeline]) + :extends org.newdawn.slick.BasicGame) (defn game-create [title state] [[title] - {:state (ref state) + {:state (atom state) :repl (repl/repl-create 9999) :container (atom nil) :input (input-create)}]) -(defn game-state-ref [this] (:state (.state this))) +(defn game-state-atom [this] (:state (.state this))) (defn game-container [this] @(:container (.state this))) (defn game-install-input [this] @@ -149,34 +147,33 @@ (game-install-input this) (repl/repl-start (:repl (.state this)) - (fn [f] (eval-with-bindings @(game-state-ref this) this f)))) + (fn [f] (eval-with-bindings @(game-state-atom this) this f)))) (defn game-update [this container delta] (doseq [ns-sym (modified-namespaces)] (try (require ns-sym :reload) - (catch Exception e (println "Couldn't load" ns-sym (.getMessage e))))) + (catch Exception e + (println "Couldn't load" ns-sym) + (.printStackTrace e)))) (repl/repl-update (:repl (.state this))) - (dosync - (try - (if-let [statenew (update-game @(game-state-ref this) (:input (.state this)) delta)] - (ref-set (game-state-ref this) statenew)) - (catch Exception e (println "Couldn't update" (:state @(game-state-ref this)) (.getMessage e)))))) + (try + (if-let [statenew (update-game @(game-state-atom this) (input-timeline-clear! (:input (.state this))) delta)] + (reset! (game-state-atom this) statenew)) + (catch Exception e + (println "Couldn't update" (:state @(game-state-atom this))) + (.printStackTrace e)))) (defn game-render [this container graphics] (try (res/gc-expired-resources) - (render-game @(game-state-ref this) graphics) - (catch Exception e (prn "Couldn't render" (:state @(game-state-ref this)) (.getMessage e))))) + (render-game @(game-state-atom this) graphics) + (catch Exception e + (println "Couldn't render" (:state @(game-state-atom this))) + (.printStackTrace e)))) -(defn game-setstate [this statenew] - (dosync (ref-set (game-state-ref this) statenew))) - -(defn game-input_timeline [this] - (input-timeline (:input (.state this)))) - -(defn game-input_clear [this tsafter] - (input-clear (:input (.state this)) tsafter)) +(defn game-setstate! [this statenew] + (reset! (game-state-atom this) statenew)) (defmethod update-game :default [state input delta]) (defmethod render-game :default [state graphics])