diff --git a/desktop/src-common/advent/actions.clj b/desktop/src-common/advent/actions.clj index b03e80b7..08f17413 100644 --- a/desktop/src-common/advent/actions.clj +++ b/desktop/src-common/advent/actions.clj @@ -5,6 +5,7 @@ [play-clj.g2d :refer :all] [clojure.pprint] [clojure.string :as s] + [clojure.zip :as zip] [advent.pathfind] [advent.actions :as actions] [advent.screens.dialogue :as dialogue] @@ -148,18 +149,48 @@ (stop screen entities target-id) entities))))) -(defn present-choices [entities & pairs] - (run-action entities - (begin [this screen entities] - (run! dialogue/choice-screen :on-present-choices :pairs pairs) - (run! @(resolve 'advent.screens.scene/scene) :on-deactivate) - entities) +(defn something-else [zipper] + (-> zipper zip/up zip/up)) - (continue [this screen entities] entities) +(defn previous-choices [zipper] + (-> zipper zip/up)) - (done? [this screen entities] true) +(defn nth-child [zipper i] + (loop [so-far 0 + zipper (zip/down zipper)] + (if (= so-far i) + zipper + (recur (inc so-far) (zip/right zipper))))) - (terminate [this screen entities] entities))) +(defn make-zipper [tree] + (zip/zipper map? (comp vals :choices) (fn [n c] nil) tree)) + +(defn present-choices [entities choices] + (loop [zipper (make-zipper choices)] + (let [selected-choice (atom nil) + node (zip/node zipper)] + (run-action entities + (begin [this screen entities] + (run! dialogue/choice-screen :on-present-choices :choices (:choices node) :callback #(reset! selected-choice %)) + (run! @(resolve 'advent.screens.scene/scene) :on-deactivate) + entities) + + (continue [this screen entities] entities) + + (done? [this screen entities] (not (nil? @selected-choice))) + + (terminate [this screen entities] + (run! @(resolve 'advent.screens.scene/scene) :on-reactivate) + entities)) + + (let [zipper (nth-child zipper (-> node :choices keys (.indexOf @selected-choice))) + node (zip/node zipper)] + (when-let [run (:run node)] + (run @selected-choice)) + (when-let [next-choices (:choices node)] + (if (fn? next-choices) + (recur (next-choices zipper)) + (recur zipper))))))) (defn give [entities target-id item] diff --git a/desktop/src-common/advent/screens/dialogue.clj b/desktop/src-common/advent/screens/dialogue.clj index 42491218..5f9e4f86 100644 --- a/desktop/src-common/advent/screens/dialogue.clj +++ b/desktop/src-common/advent/screens/dialogue.clj @@ -68,28 +68,29 @@ entities) :on-present-choices - (fn [{:keys [pairs]} [entities]] + (fn [{:keys [choices callback]} [entities]] (let [font (bitmap-font "ego/font.fnt" ) tr (bitmap-font! font :get-region) scale 1 tx (.getTexture tr) _ (texture! tx :set-filter Texture$TextureFilter/Linear Texture$TextureFilter/Linear)] - (into entities (for [[[text result-script] i] (map vector pairs (range))] - [i (assoc (label text (style :label font (color :white))) :x 30 :y (* 30 i) :result-script result-script)])))) + (-> entities + (into (for [[text i] (map vector (keys choices) (range))] + [i (assoc (label text (style :label font (color :white))) :x 30 :y (* 30 i))])) + (assoc :state {:object nil :callback callback :choices choices})))) :on-touch-down (fn [screen [entities]] (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)})] (when (seq entities) (when (< y (* 30 (count entities))) - (run! @(resolve 'advent.screens.scene/scene) :on-reactivate) - (run! @(resolve 'advent.screens.scene/scene) :on-start-script :script (:result-script (entities (int (/ y 30))))) + ((get-in entities [:state :callback]) (nth (keys (get-in entities [:state :choices])) (int (/ y 30)))) {})))) :on-mouse-moved (fn [screen [entities]] (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)}) font (bitmap-font "ego/font.fnt" )] (when (seq entities) - (doseq [index (range (count entities))] + (doseq [index (range (dec (count entities)))] (if (< (* index 30) y (* (inc index) 30)) (label! (entities index) :set-style (style :label font (color :yellow))) (label! (entities index) :set-style (style :label font (color :white)))))))) diff --git a/desktop/src-common/advent/screens/scene.clj b/desktop/src-common/advent/screens/scene.clj index 1a4611d1..0d52d95f 100644 --- a/desktop/src-common/advent/screens/scene.clj +++ b/desktop/src-common/advent/screens/scene.clj @@ -151,7 +151,7 @@ (if (= :choices subject) (apply actions/present-choices entities (for [choice (partition 2 arg)] [(first choice) (actions/get-script entities - (run-dialogue-tree entities (second choice) (first choice)))])) + (run-dialogue-tree entities (doto (second choice) println) (first choice)))])) (if (= :line arg) (actions/talk entities subject previous-line) (actions/talk entities subject arg)))))) @@ -179,28 +179,18 @@ :cursor :down} :wizard {:box [228 80 248 126] :script (actions/get-script entities - (run-dialogue-tree entities [:ego "Hello there Mr. Fangald!" - :wizard "Oh no, not you again!" - :choices ["You're not happy to see me?" [:ego :line - :wizard "Of course not!" - :wizard "Not after all the hell you've put me through." - :choices ["You mean the time I set your rabbit loose?" [:ego :line - :wizard "Fluffy was my best rabbit!"] - "You're not still sore about my stealing your magic cowboy hat." [:ego :line - :ego "Are you?" - :wizard "That cowboy hat was one of a kind!" - :wizard "Truly unique." - :wizard "It accented my unique facial physique." - :wizard "And now it's gone forever." - :wizard "Leave me to die in peace."] - "You mean the time I set your house on fire with a fire mint?" [:ego :line - :wizard "That was you? I spent a fortune cleaning up the mess you made!" - :wizard "You ruined my life work!"] - - "An old hoot like you needs a kick the pants every now and again!" [:ego :line - :wizard "Maybe so, but not from a cheating little boy like you!"]]] - "What do you mean, 'not you again'?" [:ego :line - :wizard "I mean get lost kid."]]]))}} + (actions/present-choices entities {:choices {"Hello there" {:run #(do (actions/talk entities :ego %) + (actions/talk entities :wizard "Oh, hello.")) + :choices {"How are you doing?" {:run #(do (actions/talk entities :ego %) + (actions/talk entities :wizard "I'm ok.")) + :choices actions/previous-choices} + "Any news?" {:run #(do (actions/talk entities :ego %) + (actions/talk entities :wizard "Not really")) + :choices actions/previous-choices} + "Something Else" {:choices actions/something-else}}} + "Good bye" {:run #(actions/talk entities :ego %)}}}) + + )}} :layers [(assoc (texture "inside-house/background.png") :x 0 :y 0 :baseline 0) (assoc (texture "inside-house/desk.png") :x 0 :y 0 :baseline 200) (assoc (texture "inside-house/sillhoute.png") :x 0 :y 0 :baseline 240)] @@ -356,7 +346,7 @@ (update! screen :renderer (stage) :camera (orthographic)) (let [_ (input! :set-cursor-image (utils/cursor "cursor.png" :main) 0 0) music (sound "town-music.mp3") - _ (sound! music :loop 0.20) + ;; _ (sound! music :loop 0.20) backgrounds (backgrounds screen)] {:backgrounds backgrounds :state {:object nil