From 91d03855d5a5028112faf1524501f3e60ba7d3ee Mon Sep 17 00:00:00 2001 From: = Date: Sun, 7 Sep 2014 17:25:07 -0700 Subject: [PATCH] organization. --- desktop/src-common/advent/actions.clj | 54 +++++ desktop/src-common/advent/core.clj | 229 +----------------- .../src-common/advent/screens/dialogue.clj | 32 +++ desktop/src-common/advent/screens/scene.clj | 164 +++++++++++++ desktop/src-common/advent/zone.clj | 7 + 5 files changed, 261 insertions(+), 225 deletions(-) create mode 100644 desktop/src-common/advent/actions.clj create mode 100644 desktop/src-common/advent/screens/dialogue.clj create mode 100644 desktop/src-common/advent/screens/scene.clj create mode 100644 desktop/src-common/advent/zone.clj diff --git a/desktop/src-common/advent/actions.clj b/desktop/src-common/advent/actions.clj new file mode 100644 index 00000000..95a69182 --- /dev/null +++ b/desktop/src-common/advent/actions.clj @@ -0,0 +1,54 @@ +(ns advent.actions + (:require [play-clj.core :refer :all] + [play-clj.ui :refer :all] + [play-clj.utils :refer :all] + [play-clj.g2d :refer :all] + [clojure.pprint] + [advent.pathfind] + [advent.actions :as actions]) + (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] + [com.badlogic.gdx.graphics.g2d TextureRegion] )) + +(defn jump-to [screen entities entity [x y]] + (let [scale-fn (-> entities :background :scale-fn) + entity (assoc entity :x x + :y y + :baseline (- 240 y))] + (if (:scaled entity) + (assoc entity :scale-x (scale-fn y) :scale-y (scale-fn y)) + entity))) + +(defn walk-to-fn [[target-x target-y] target-id] + (fn [screen entities] + (let [{from-x :x from-y :y :keys [left right anim] :as target-entity} (entities target-id)] + (let [delta-x (- target-x from-x) + delta-y (- target-y from-y) + mag (Math/sqrt (+ (* delta-x delta-x) (* delta-y delta-y))) + moved-x (* 1.5 (/ delta-x mag)) + moved-y (* 1.5 (/ delta-y mag))] + (if (< mag 1) + (assoc entities target-id (assoc target-entity :actions (rest (:actions target-entity)) :anim nil)) + (assoc entities target-id + (assoc (jump-to screen entities target-entity [(+ moved-x from-x) (+ moved-y from-y)]) + :anim (if (< moved-x 0) left right)))))))) + +(defn stop-fn [target-id] + (fn [screen entities] + (let [target (target-id entities)] + (assoc-in entities [target-id] (merge target + {:anim nil + :actions (rest (:actions target))} + (when (:anim target) + (texture (animation! (:anim target) :get-key-frame 0.25)))))))) + +(defn from-path [screen entities target-id [x y]] + (let [entity (target-id entities) + path (vec (take-nth 2 (advent.pathfind/visit-all + (:collision (:background entities)) + [(int (:x entity)) (int (:y entity))] + [(int x) (int y)]))) + actions (when (seq path) + (conj + (vec (map #(walk-to-fn % target-id) (conj path [x y]))) + (stop-fn target-id)))] + actions)) diff --git a/desktop/src-common/advent/core.clj b/desktop/src-common/advent/core.clj index 7e6790a3..e2146423 100644 --- a/desktop/src-common/advent/core.clj +++ b/desktop/src-common/advent/core.clj @@ -3,237 +3,16 @@ [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.g2d :refer :all] + [advent.screens.scene :as scene] + [advent.screens.dialogue :as dialogue] [clojure.pprint] [advent.pathfind]) (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] [com.badlogic.gdx.graphics.g2d TextureRegion] )) -(def scale 2) -(def +screen-width+ 320) -(def +screen-height+ 240) -(def +num-cursors+ 4) -(def +next-cursor+ (into {} (map vector (range +num-cursors+) (drop 1 (cycle (range +num-cursors+)))))) - -(defn +next-cursor+ [x] - (first (drop 1 (drop-while #(not= x %) (cycle (range +num-cursors+)))))) - -(defn cursor [filename index] - (let [base-cursor (pixmap filename) - target-width (* 16 scale) - target-height (* 16 scale) - resized (Pixmap. target-width target-height (.getFormat base-cursor))] - (Pixmap/setFilter Pixmap$Filter/NearestNeighbour) - (pixmap! resized :draw-pixmap base-cursor (* index 16) 0 16 16 - 0 0 target-width target-height) - resized )) - -(defn right-click [screen entities] - (let [entities (update-in entities [:cursor] #(assoc % :cursor-index (+next-cursor+ (:cursor-index %))))] - (input! :set-cursor-image (cursor "cursor.png" (get-in entities [:cursor :cursor-index])) 0 0) - entities)) - -(defn move-to [screen entities entity [x y]] - (let [scale-fn (-> entities :background :scale-fn) - entity (assoc entity :x x - :y y - :baseline (- 240 y))] - (if (:scaled entity) - (assoc entity :scale-x (scale-fn y) :scale-y (scale-fn y)) - entity))) - -(defn walk-to-fn [[target-x target-y] target-id] - (fn [screen entities] - (let [{from-x :x from-y :y :keys [left right anim] :as target-entity} (entities target-id)] - (let [delta-x (- target-x from-x) - delta-y (- target-y from-y) - mag (Math/sqrt (+ (* delta-x delta-x) (* delta-y delta-y))) - moved-x (* 1.5 (/ delta-x mag)) - moved-y (* 1.5 (/ delta-y mag))] - (if (< mag 1) - (assoc entities target-id (assoc target-entity :actions (rest (:actions target-entity)) :anim nil)) - (assoc entities target-id - (assoc (move-to screen entities target-entity [(+ moved-x from-x) (+ moved-y from-y)]) - :anim (if (< moved-x 0) left right)))))))) - -(defn stop-fn [target-id] - (fn [screen entities] - (let [target (target-id entities)] - (assoc-in entities [target-id] (merge target - {:anim nil - :actions (rest (:actions target))} - (when (:anim target) - (texture (animation! (:anim target) :get-key-frame 0.25)))))))) - -(defn path-to-actions [screen entities target-id [x y]] - (let [entity (target-id entities) - path (vec (take-nth 2 (advent.pathfind/visit-all - (:collision (:background entities)) - [(int (:x entity)) (int (:y entity))] - [(int x) (int y)]))) - actions (when (seq path) - (conj - (vec (map #(walk-to-fn % target-id) (conj path [x y]))) - (stop-fn target-id)))] - actions)) - -(defn walk-click [screen entities [x y]] - (assoc-in entities [:ego :actions] (path-to-actions screen entities :ego [x y]))) - -(defn walk-override-click [screen entities [x y]] - (let [target-location (->> (get-in entities [:background :mouse-overrides]) - (filter #((:mouse-in? %) x y)) - first - :go-to)] - (assoc-in entities [:ego :actions] (path-to-actions screen entities :ego target-location)))) - -(defn left-click [screen entities] - (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)}) - interaction (first (filter #((:mouse-in? %) x y) (get-in entities [:background :interactions])))] - (cond (get-in entities [:cursor :override]) (walk-override-click screen entities [x y]) - interaction ((:click-fn interaction) screen entities [x y]) - - :else (walk-click screen entities [x y])))) - -(defn get-ego [screen] - (let [player-sheet (texture! (texture "player.png") :split 18 36) - ego {:right (animation 0.075 (for [i (range 8)] - (texture (aget player-sheet 0 i)))) - :left (animation 0.075 (for [i (range 8)] - (texture (aget player-sheet 1 i)))) - - :baseline 95 - :origin-x 9 - :origin-y 0 - :scaled true - :actions [] - :x 150 :y 95 - :id "ego"}] - (merge (texture (animation! (:right ego) :get-key-frame 0.25)) ego))) - -(defn update-ego [screen entities ego] - (if-let [action (first (:actions ego))] - (action screen entities) - entities)) - -(defn scaler-fn-with-baseline [baseline minimum-size & [maximum-size]] - (let [maximum-size (or maximum-size 1.0)] - (fn [y] - (if (< y baseline) maximum-size - (let [percent-complete (- 1.0 (/ (- y baseline) (- +screen-height+ baseline))) - range (+ (* percent-complete (- maximum-size minimum-size)) minimum-size)] - range))))) - -(defn box-maker-fn [x1 y1 x2 y2] - (fn [x y] - (and - (< x1 x x2) - (< y1 y y2)))) - -(defscreen talking-screen - :on-show - (fn [screen entities] - (update! screen :renderer (stage) :camera (orthographic)) []) - :on-render - (fn [screen entities] - (render! screen entities) - entities) - - :on-talk - (fn [{:keys [create-talk text x y]} entities] - [(let [font (bitmap-font "mainfont.fnt" ) - tr (bitmap-font! font :get-region) - tx (.getTexture tr) - _ (texture! tx :set-filter Texture$TextureFilter/Linear Texture$TextureFilter/Linear) - talk (assoc (label text (style :label font (color :white)) ) :x (* 4 x) :y (* 4 y))] - (label! talk :set-font-scale 1) - talk)]) - - - :on-resize (fn [screen entities] - (height! screen (game :height))) - - ) - -(defscreen main-screen - :on-show - (fn [screen entities] - (update! screen :renderer (stage) :camera (orthographic)) - (let [ - _ (input! :set-cursor-image (cursor "cursor.png" 0) 0 0) - background (texture "bg5.png") - background-trees (texture "background-trees.png") - house (texture "house.png") - overdirt (texture "overdirt.png") - music (sound "outside-house.mp3") - ;; _ (sound! music :loop) - ] - { - :cursor {:id "cursor" :cursor-index 0 } - :background (assoc background - :id "background" :x 0 :y 0 - :collision (advent.pathfind/map-from-resource "pathfind-test-big.png") - :baseline 0 - :mouse-overrides [{:mouse-in? (box-maker-fn 290 131 320 224) - :cursor-override 4 - :go-to [319 160]} - {:mouse-in? (box-maker-fn 60 180 224 240) - :cursor-override 7 - :go-to [137 204]} - {:mouse-in? (box-maker-fn 0 40 30 140) - :cursor-override 6 - :go-to [0 80]}] - :interactions [{:mouse-in? (box-maker-fn 258 100 281 160) - :click-fn (fn [screen entities [x y]] - (assoc-in entities [:ego :actions] [(fn [screen entities] - (run! talking-screen :on-talk :text "It's the door to Merlin's house." - :x (get-in entities [:ego :x]) :y (+ (get-in entities [:ego :y]) 25) ) - (-> entities - (update-in [:ego :actions] rest)))]))}] - :scale-fn (scaler-fn-with-baseline 110 0.10 1.00)) - :house (assoc house - :x 0 :y 0 - :baseline 122) - :overdirt (assoc overdirt - :x 0 :y 0 - :baseline 240) - :background-trees (assoc background-trees - :x 0 :y 0 - :baseline 44) - :ego (get-ego screen) - :fps (assoc (label "0" (color :white) ) :x 5 :baseline 9000) - })) - - :on-render - (fn [screen [entities]] - (let [entities (update-ego screen entities (:ego entities)) - _ (label! (:fps entities) :set-text (str (game :fps))) - entities (if (get-in entities [:ego :anim]) - (update-in entities [:ego] #(merge % (animation->texture screen (:anim %)))) - entities)] - (render! screen (sort-by :baseline (vals entities))) - entities)) - - :on-resize (fn [screen entities] - (size! screen 320 240)) - - :on-mouse-moved - (fn [screen [entities]] - (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)})] - (if-let [mouse-override (first (filter #((:mouse-in? %) x y) (get-in entities [:background :mouse-overrides])))] - (when (not (get-in entities [:cursor :override])) - (do (input! :set-cursor-image (cursor "cursor.png" (:cursor-override mouse-override)) 0 0) - (assoc-in entities [:cursor :override] true))) - - (when (get-in entities [:cursor :override]) - (do (input! :set-cursor-image (cursor "cursor.png" (get-in entities [:cursor :cursor-index])) 0 0) - (assoc-in entities [:cursor :override] false)))))) - - :on-touch-down (fn [screen [entities]] - (if (= (button-code :right) (:button screen)) - (right-click screen entities) - (left-click screen entities)))) + (defgame advent :on-create (fn [this] - (set-screen! this main-screen talking-screen))) + (set-screen! this scene/scene dialogue/talking-screen))) diff --git a/desktop/src-common/advent/screens/dialogue.clj b/desktop/src-common/advent/screens/dialogue.clj new file mode 100644 index 00000000..a5407026 --- /dev/null +++ b/desktop/src-common/advent/screens/dialogue.clj @@ -0,0 +1,32 @@ +(ns advent.screens.dialogue + (:require [play-clj.core :refer :all] + [play-clj.ui :refer :all] + [play-clj.utils :refer :all] + [play-clj.g2d :refer :all] + [clojure.pprint] + [advent.pathfind]) + (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] + [com.badlogic.gdx.graphics.g2d TextureRegion])) + +(defscreen talking-screen + :on-show + (fn [screen entities] + (update! screen :renderer (stage) :camera (orthographic)) []) + :on-render + (fn [screen entities] + (render! screen entities) + entities) + + :on-talk + (fn [{:keys [create-talk text x y]} entities] + [(let [font (bitmap-font "mainfont.fnt" ) + tr (bitmap-font! font :get-region) + tx (.getTexture tr) + _ (texture! tx :set-filter Texture$TextureFilter/Linear Texture$TextureFilter/Linear) + talk (assoc (label text (style :label font (color :white)) ) :x (* 4 x) :y (* 4 y))] + (label! talk :set-font-scale 1) + talk)]) + + + :on-resize (fn [screen entities] + (height! screen (game :height)))) diff --git a/desktop/src-common/advent/screens/scene.clj b/desktop/src-common/advent/screens/scene.clj new file mode 100644 index 00000000..acc6d4bb --- /dev/null +++ b/desktop/src-common/advent/screens/scene.clj @@ -0,0 +1,164 @@ +(ns advent.screens.scene + (:require [play-clj.core :refer :all] + [play-clj.ui :refer :all] + [play-clj.utils :refer :all] + [play-clj.g2d :refer :all] + [clojure.pprint] + [advent.pathfind] + [advent.actions :as actions] + [advent.zone :as zone] + [advent.screens.dialogue :refer [talking-screen]]) + (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] + [com.badlogic.gdx.graphics.g2d TextureRegion] )) + +(def +screen-width+ 320) +(def +screen-height+ 240) +(def +num-cursors+ 4) +(def +next-cursor+ (into {} (map vector (range +num-cursors+) (drop 1 (cycle (range +num-cursors+)))))) + +(defn +next-cursor+ [x] + (first (drop 1 (drop-while #(not= x %) (cycle (range +num-cursors+)))))) + +(defn cursor [filename index] + (let [scale 2 + base-cursor (pixmap filename) + target-width (* 16 scale) + target-height (* 16 scale) + resized (Pixmap. target-width target-height (.getFormat base-cursor))] + (Pixmap/setFilter Pixmap$Filter/NearestNeighbour) + (pixmap! resized :draw-pixmap base-cursor (* index 16) 0 16 16 + 0 0 target-width target-height) + resized )) + +(defn right-click [screen entities] + (let [entities (update-in entities [:cursor] #(assoc % :cursor-index (+next-cursor+ (:cursor-index %))))] + (input! :set-cursor-image (cursor "cursor.png" (get-in entities [:cursor :cursor-index])) 0 0) + entities)) + + +(defn walk-click [screen entities [x y]] + (assoc-in entities [:ego :actions] (actions/from-path screen entities :ego [x y]))) + +(defn walk-override-click [screen entities [x y]] + (let [target-location (->> (get-in entities [:background :mouse-overrides]) + (filter #((:mouse-in? %) x y)) + first + :go-to)] + (assoc-in entities [:ego :actions] (actions/from-path screen entities :ego target-location)))) + +(defn left-click [screen entities] + (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)}) + interaction (first (filter #((:mouse-in? %) x y) (get-in entities [:background :interactions])))] + (cond (get-in entities [:cursor :override]) (walk-override-click screen entities [x y]) + interaction ((:click-fn interaction) screen entities [x y]) + + :else (walk-click screen entities [x y])))) + +(defn get-ego [screen] + (let [player-sheet (texture! (texture "player.png") :split 18 36) + ego {:right (animation 0.075 (for [i (range 8)] + (texture (aget player-sheet 0 i)))) + :left (animation 0.075 (for [i (range 8)] + (texture (aget player-sheet 1 i)))) + + :baseline 95 + :origin-x 9 + :origin-y 0 + :scaled true + :actions [] + :x 150 :y 95 + :id "ego"}] + (merge (texture (animation! (:right ego) :get-key-frame 0.25)) ego))) + +(defn update-ego [screen entities ego] + (if-let [action (first (:actions ego))] + (action screen entities) + entities)) + +(defn scaler-fn-with-baseline [baseline minimum-size & [maximum-size]] + (let [maximum-size (or maximum-size 1.0)] + (fn [y] + (if (< y baseline) maximum-size + (let [percent-complete (- 1.0 (/ (- y baseline) (- +screen-height+ baseline))) + range (+ (* percent-complete (- maximum-size minimum-size)) minimum-size)] + range))))) + + +(defscreen scene + :on-show + (fn [screen entities] + (update! screen :renderer (stage) :camera (orthographic)) + (let [ + _ (input! :set-cursor-image (cursor "cursor.png" 0) 0 0) + background (texture "bg5.png") + background-trees (texture "background-trees.png") + house (texture "house.png") + overdirt (texture "overdirt.png") + music (sound "outside-house.mp3") + ;; _ (sound! music :loop) + ] + { + :cursor {:id "cursor" :cursor-index 0 } + :background (assoc background + :id "background" :x 0 :y 0 + :collision (advent.pathfind/map-from-resource "pathfind-test-big.png") + :baseline 0 + :mouse-overrides [{:mouse-in? (zone/box 290 131 320 224) + :cursor-override 4 + :go-to [319 160]} + {:mouse-in? (zone/box 60 180 224 240) + :cursor-override 7 + :go-to [137 204]} + {:mouse-in? (zone/box 0 40 30 140) + :cursor-override 6 + :go-to [0 80]}] + :interactions [{:mouse-in? (zone/box 258 100 281 160) + :click-fn (fn [screen entities [x y]] + (assoc-in entities [:ego :actions] [(fn [screen entities] + (run! talking-screen :on-talk :text "It's the door to Merlin's house." + :x (get-in entities [:ego :x]) :y (+ (get-in entities [:ego :y]) 25) ) + (-> entities + (update-in [:ego :actions] rest)))]))}] + :scale-fn (scaler-fn-with-baseline 110 0.10 1.00)) + :house (assoc house + :x 0 :y 0 + :baseline 122) + :overdirt (assoc overdirt + :x 0 :y 0 + :baseline 240) + :background-trees (assoc background-trees + :x 0 :y 0 + :baseline 44) + :ego (get-ego screen) + :fps (assoc (label "0" (color :white) ) :x 5 :baseline 9000) + })) + + :on-render + (fn [screen [entities]] + (let [entities (update-ego screen entities (:ego entities)) + _ (label! (:fps entities) :set-text (str (game :fps))) + entities (if (get-in entities [:ego :anim]) + (update-in entities [:ego] #(merge % (animation->texture screen (:anim %)))) + entities)] + (render! screen (sort-by :baseline (vals entities))) + entities)) + + :on-resize (fn [screen entities] + (size! screen 320 240)) + + :on-mouse-moved + (fn [screen [entities]] + (let [{:keys [x y]} (input->screen screen {:x (:input-x screen) :y (:input-y screen)})] + (if-let [mouse-override (first (filter #((:mouse-in? %) x y) (get-in entities [:background :mouse-overrides])))] + (when (not (get-in entities [:cursor :override])) + (do (input! :set-cursor-image (cursor "cursor.png" (:cursor-override mouse-override)) 0 0) + (assoc-in entities [:cursor :override] true))) + + (when (get-in entities [:cursor :override]) + (do (input! :set-cursor-image (cursor "cursor.png" (get-in entities [:cursor :cursor-index])) 0 0) + (assoc-in entities [:cursor :override] false)))))) + + :on-touch-down (fn [screen [entities]] + (if (= (button-code :right) (:button screen)) + (right-click screen entities) + (left-click screen entities)))) diff --git a/desktop/src-common/advent/zone.clj b/desktop/src-common/advent/zone.clj new file mode 100644 index 00000000..f2ec071e --- /dev/null +++ b/desktop/src-common/advent/zone.clj @@ -0,0 +1,7 @@ +(ns advent.zone) + +(defn box [x1 y1 x2 y2] + (fn [x y] + (and + (< x1 x x2) + (< y1 y y2))))