(ns advent.screens.scene (:refer-clojure :exclude [load]) (:require [play-clj.core :refer :all] [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.math :refer :all] [play-clj.entities :as entities] [play-clj.g2d :refer :all] [clojure.zip :as zip] [clojure.pprint] [clojure.java.io :as io] [advent.pathfind] [advent.actions :as actions] [advent.zone :as zone] [advent.utils :as utils] [advent.tween :as tween] [advent.screens.rooms :as rooms] [advent.screens.rooms.common :as common] [advent.screens.items :as items] [advent.screens.rooms.dream :as rooms.dream] [advent.screens.rooms.castle-gate :as rooms.castle-gate] [advent.screens.rooms.outside-house :as rooms.outside-house] [advent.screens.rooms.inside-house :as rooms.inside-house] [advent.screens.rooms.inside-stash :as rooms.inside-stash] [advent.screens.rooms.inside-castle :as rooms.inside-castle] [advent.screens.rooms.inside-jail :as rooms.inside-jail] [advent.screens.rooms.outside-jail :as rooms.outside-jail] [advent.screens.rooms.inside-cafeteria :as rooms.inside-cafeteria] [advent.screens.rooms.inside-antique :as rooms.inside-antique] [advent.screens.rooms.behind-house :as rooms.behind-house] [advent.screens.rooms.outside-castle :as rooms.outside-castle] [advent.screens.rooms.space :as rooms.space] [advent.screens.rooms.cat-tree :as rooms.cat-tree] [advent.screens.dialogue :refer [talking-screen]] [advent.screens.inventory :refer [inventory-screen]] [clojure.core.async :refer [put! ! chan go thread take! alts!!]]) (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter GL20 GL30] [com.badlogic.gdx.graphics.g2d TextureRegion Animation] [com.badlogic.gdx.utils.viewport FitViewport] [com.badlogic.gdx.scenes.scene2d Actor Stage] [java.lang Object] [com.badlogic.gdx Gdx])) (declare hud) (def default-interaction {:get-script (fn [cursor [x y]] (if (= :main cursor) (actions/get-script entities (actions/walk-to entities :ego [x y] :can-skip? true)) (actions/get-script entities (actions/talk entities :ego "I don't know what to do with that."))))}) (defn click-inventory [screen entities] (when (not (get-in entities [:actions :script-running?])) (if (= (get-in entities [:cursor :current] ) :main) (do (screen! inventory-screen :show-screen :items (map (entities :all-items) (get-in entities [:state :inventory]))) (-> entities (assoc-in [:state :active?] false) (assoc-in [:cursor :override] nil))) (assoc-in entities [:cursor :current] :main)))) (defn left-click [screen entities] (let [[x y] (utils/unproject screen)] (println "clicked " x y) (let [interaction (first (filter #((:mouse-in? %) entities x y) (get-in entities [:room :interactions]))) interacting-entity (first (sort-by (comp - :baseline) (filter #(and (:mouse-in? %) (:get-script %) ((:mouse-in? %) entities x y)) (vals (get-in entities [:room :entities]))))) current-action (get-in entities [:actions :current]) ;; TODO - hacky way of resetting queue entities (if (and current-action (actions/can-skip? current-action screen entities)) (let [terminated-entities (actions/terminate current-action screen entities)] (do (put! (actions/get-channel current-action) terminated-entities) (-> terminated-entities (assoc-in [:actions :current] nil) (assoc-in [:actions :started?] false)))) entities)] (if (get-in entities [:actions :script-running?]) entities ((or (when interacting-entity ((:get-script interacting-entity) (get-in entities [:cursor :current]) [x y])) (when interaction ((:get-script interaction) (or (when (:cursor interaction) :main) (get-in entities [:cursor :current])) [x y])) ((:get-script default-interaction) (get-in entities [:cursor :current]) [x y])) entities)) entities))) (defn drink-blergh [entities] (actions/walk-straight-to entities :ego [205 45]) (sound! (sound "ego/potion.ogg") :play) (actions/play-animation entities :ego :grow :stop? false) (actions/do-dialogue entities :blergh "What this? A potion of strength?" :blergh "You're still no match for me." :blergh "Give it to me, or I'll make you regret it!") (actions/present-choices entities {:choices ["Ok." {:run (fn [_] (actions/talk entities :ego "Ok." :anim :grow-talk :stop? false) (actions/talk entities :ego "Here you go." :anim :grow-talk) (actions/do-dialogue entities :blergh "Yes! Now I can drink this whole thing and can become powerful enough to rule the world!" :blergh "[#AAFFAAFF]*gulp*[]" :blergh "What's this? What's happening?") (actions/talk entities :ego "Uh oh." :anim :grow-talk :stop? false) (actions/walk-straight-to entities :ego [100 45] :face :right) (actions/play-animation entities :blergh :grow :stop? false) (actions/do-dialogue entities :ego "'Not more than that do drink,\nOr you'll push your body to the brink.'" :ego "Brilliant! I win!") (actions/walk-straight-to entities :ego [800 75] :face :right) (actions/update-state entities (fn [s] (assoc s :blergh-dead? true))))} "No way!" {:run (fn [_] (actions/talk entities :ego "No way!" :anim :grow-talk) (actions/talk entities :blergh "Then take this!") (actions/play-animation entities :blergh :swing) (actions/walk-straight-to entities :ego [100 45] :anim :squat :override-dir :right :speed 3.0) (actions/do-dialogue entities :ego "Yeow!!" :ego "Even with that potion, I'm not strong enough."))}]})) (defn get-ego [screen start-pos start-scale] (let [player-sheet (texture! (texture "player.png") :split 18 36) talk-sheet (texture! (texture "ego/talk.png") :split 18 36) stand-sheet (texture! (texture "ego/stand.png") :split 18 36) squat-sheet (texture! (texture "ego/squat.png") :split 18 36) reach-sheet (texture! (texture "ego/reach.png") :split 18 36) grow-sheet (texture! (texture "ego/grow.png") :split 18 36) cat-toy-sheet (texture! (texture "ego/cat-toy.png") :split 41 50) fire-sheet (texture! (texture "ego/fire.png") :split 18 36) walk-right (animation 0.075 (for [i (range 8)] (texture (aget player-sheet 0 i)))) stand-anim (animation 0.1 (for [i (flatten [(repeat 6 [(repeat 10 0) (repeat 3 1) (repeat 20 0)]) 3 4 5 5 5 6 5 6 5 6 5 4 3 ])] (texture (aget stand-sheet 0 i)))) reach-up (animation 0.1 (for [i [0 3 4 5]] (texture (aget stand-sheet 0 i)))) reach-down (animation 0.1 (for [i [5 4 3 0]] (texture (aget stand-sheet 0 i)))) talk-anim (animation 0.2 (for [i (range 8)] (texture (aget talk-sheet 0 i)))) start-squat (animation 0.05 (for [i [0 1 2 3 4]] (texture (aget squat-sheet 0 i)))) end-squat (animation 0.05 (for [i [4 3 2 1 0]] (texture (aget squat-sheet 0 i)))) squat-anim (animation 0.05 (for [i [0 1 2 3 3 3 3 3 3 3 3 3 3 3 3 2 1] ] (texture (aget squat-sheet 0 i)))) reach-anim (animation 0.1 (for [i [0 1 2 3 3 3 3 3 3 2 1 0]] (texture (aget reach-sheet 0 i)))) reach-start (animation 0.1 (for [i [0 1 2 3 ]] (texture (aget reach-sheet 0 i)))) reach-stop (animation 0.1 (for [i [3 2 1 0]] (texture (aget reach-sheet 0 i)))) cat-toy-anim (animation 0.1 (for [i [0 0 1 1 2 2 3 4 3 2 3 4 3 2 3 4 3 2 3 4 3 2 2 1 1 0 0]] (texture (aget cat-toy-sheet 0 i)))) cat-toy-first-half (animation 0.1 (for [i [0 0 1 1 2 2 3]] (texture (aget cat-toy-sheet 0 i)))) cat-toy-last-half (animation 0.1 (for [i [3 3 3 2 1 1 0 0]] (texture (aget cat-toy-sheet 0 i)))) fire-1-anim (animation 0.1 (for [i [0 1 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 1 0]] (texture (aget fire-sheet 0 i)))) fire-2-anim (animation 0.1 (for [i [0 1 2 2 2 3 2 3 2 2 2 2 2 2 2 4 4 4 5 6 7 4 4 4 2 2 2 2 2 2 2 2 1 0]] (texture (aget fire-sheet 0 i)))) fire-3-anim (animation 0.1 (for [i [0 1 2 2 2 3 2 3 2 2 2 2 2 2 4 4 4 4 4 4 5 6 7 4 4 4 4 4 8 9 10 11 4 4 4 2 2 2 2 2 2 2 2 0]] (texture (aget fire-sheet 0 i)))) grow (animation 0.1 (for [i [0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 3 0 0 0 0 3 0 0 0 3 3 0 0 0 2 2 0 0 2 0 0 2 0 2 0 2 0 2 0 2 0 2 3 2 3 2 3 2 3 2 4 3 4 3 4 3 4]] (texture (aget grow-sheet 0 i)))) hold-up-to-window (utils/make-anim "ego/hold-up-to-window.png" [18 36] 0.1 [0 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 1 0 0 0 0 0 0]) jump (utils/make-anim "ego/swing.png" [36 75] 0.2 (flatten [[1 2]])) swing (utils/make-anim "ego/swing.png" [36 75] 0.145 (flatten [[3 4 5 6 7 ]])) grow-talk (utils/make-anim "ego/grow-talk.png" [18 36] 0.2 (range 2)) get-sick (animation 0.3 (map (partial get [(aget talk-sheet 0 0 ) (texture "ego/get-sick.png")]) [0 1 1 1 1 1 1 1 1 1 1 1]) ) spear (utils/make-anim "ego/spear.png" [18 100] 0.2 [0 1 2 3 2 3 2 3 2 3 2 1 0]) crowbar (utils/make-anim "ego/crowbar.png" [36 36] 0.1 [0 0 0 1 1 2 2 2 2 2 3 2 3 2 3 2 3 2 3 3 3 1 1 0 0 0]) shoot (utils/make-anim "ego/shoot.png" [24 36] 0.075 [0 0 0 1 1 2 2 2 2 2 2 2 2 3 4 5 4]) pant (utils/make-anim "ego/pant.png" [31 36] 0.5 [0 1]) shock (utils/make-anim "ego/shock.png" [40 48] 0.075 (flatten (repeat 2 [(repeat 5 [0 1 2]) (repeat 5 [3 4 5]) (repeat 5 [6 7 8])]))) burnt (utils/make-anim "ego/burnt.png" [40 46] 0.12 [1 2 3 2 1 2 3 2 1 0 2 0 4 5 6 7 8 9 10 11 10 9 10 11]) passed-out (utils/make-anim "ego/burnt.png" [40 46] 0.12 [9 10 11 10]) scared (utils/make-anim "ego/scared.png" [18 36] 0.05 [0 1]) scared-talk (utils/make-anim "ego/scared.png" [18 36] 0.05 [0 1 0 1 0 1 0 1 2 3 2 3 2 3 2 3]) ego {:right {:walk walk-right :stand stand-anim :talk talk-anim :squat squat-anim :start-squat start-squat :end-squat end-squat :reach reach-anim :cat-toy cat-toy-anim :cat-toy-first-half cat-toy-first-half :cat-toy-last-half cat-toy-last-half :grow grow :crowbar crowbar :get-sick get-sick :hold-up-to-window hold-up-to-window :swing swing :grow-talk grow-talk :reach-up reach-up :reach-down reach-down :reach-start reach-start :jump jump :reach-stop reach-stop :shoot shoot [:fire 1] fire-1-anim [:fire 2] fire-2-anim [:fire 3] fire-3-anim :spear spear :pant pant :shock shock :burnt burnt :passed-out passed-out :scared scared :scared-talk scared-talk} :left {:walk (utils/flip walk-right) :stand (utils/flip stand-anim) :talk (utils/flip talk-anim) :start-squat (utils/flip start-squat) :end-squat (utils/flip end-squat) :squat (utils/flip squat-anim) :reach (utils/flip reach-anim) :cat-toy (utils/flip cat-toy-anim) :get-sick (utils/flip get-sick) :cat-toy-first-half (utils/flip cat-toy-first-half) :cat-toy-last-half (utils/flip cat-toy-last-half) :grow (utils/flip grow) :hold-up-to-window (utils/flip hold-up-to-window) :grow-talk (utils/flip grow-talk) :reach-up (utils/flip reach-up) :reach-down (utils/flip reach-down) :reach-start (utils/flip reach-start) :reach-stop (utils/flip reach-stop) :shoot (utils/flip shoot) [:fire 1] (utils/flip fire-1-anim) [:fire 2] (utils/flip fire-2-anim) [:fire 3] (utils/flip fire-3-anim) :spear (utils/flip spear) :pant (utils/flip pant)} :baseline (- 240 (last start-pos)) :facing :right :origin-x 9 :origin-y 0 :scaled true :step-sound-1 (sound "ego/step-1.ogg") :step-sound-2 (sound "ego/step-2.ogg") :blink (sound "blink.ogg") :scale-x start-scale :scale-y start-scale :talk-color (color 0.6 1.0 1.0 1.0) :mouse-in? (fn [entities x y] (let [{entity-x :x entity-y :y region :object scale :scale-x} (get-in entities [:room :entities :ego]) half-width (/ (* (.getRegionWidth region) (or scale 1.0)) 2) height (* (.getRegionHeight region) (or scale 1.0))] #_(clojure.pprint/pprint [["point" x y] ["entity " (- entity-x half-width) entity-y (+ entity-x half-width) (+ entity-y height)]]) ((zone/box (- entity-x half-width) entity-y (+ entity-x half-width) (+ entity-y height)) x y))) :get-script (fn [cursor [x y]] (condp = (:value cursor) :flask-1-with-cream-of-mushroom (actions/get-script entities (actions/talk entities :ego "Blegh! Gross!")) :flask-1-strength (actions/get-script entities (cond (and (actions/has-item? entities :magic-slingshot) (get-in @entities [:room :blergh])) (drink-blergh entities) (get-in @entities [:room :blergh]) (actions/talk entities :ego "There's no time!") :else (do (actions/talk entities :ego "I'll just take a sip!") (sound! (sound "ego/potion.ogg") :play) (actions/play-animation entities :ego :grow :stop? false)))) :recipe (actions/get-script entities (actions/do-dialogue entities :ego "The recipe says:" :ego "'For strength beyond measure,\nyou must mix, at your leisure:'" :ego "'1. Cream of mushroom soup.'" :ego "'2. Saliva of the creature whose strength you want to match.'" :ego "'3. Mandrake root.'" :ego "'A word of warning, before you go.\nA sip is all it takes to grow.'" :ego "'Not more than that do drink,\nOr you'll push your body to the brink.'" :ego "Hmm. I wonder what that last part means?")) :note-1 (actions/get-script entities (common/read-note-1 entities)) :note-2 (actions/get-script entities (common/read-note-2 entities)) :camera (actions/get-script entities (actions/talk entities :ego "It's some sort of magical device that captures images.")) :alarm-clock (actions/get-script entities (actions/talk entities :ego "It's a magic device that tells the time.")) :walkie-talkies (actions/get-script entities (actions/do-dialogue entities :ego "If I talk in one of these devices, I can hear it in the other one!")) :walkie-talkie (actions/get-script entities (common/listen-to-frankie entities)) nil)) :x (first start-pos) :y (last start-pos) :id "ego"} ego (assoc ego :anim-sound-frames {(get-in ego [:left :walk]) {2 [:step-sound-1 1.0] 6 [:step-sound-2 0.8]} (get-in ego [:right :walk]) {2 [:step-sound-1 1.0] 6 [:step-sound-2 0.8]} (get-in ego [:left :talk] ) {2 [:blink 0.15]} (get-in ego [:right :talk] ) {2 [:blink 0.15]} (get-in ego [:left :stand]) {11 [:blink 0.15] 44 [:blink 0.15] 77 [:blink 0.15] 110 [:blink 0.15] 143 [:blink 0.15] 176 [:blink 0.15]} (get-in ego [:right :stand]) {11 [:blink 0.15] 44 [:blink 0.15] 77 [:blink 0.15] 110 [:blink 0.15] 143 [:blink 0.15] 176 [:blink 0.15]}} :anim-merges {(get-in ego [:right :shock]) {:origin-x 15} :default {:origin-x 9}})] (actions/start-animation screen (merge (animation->texture screen (:stand (:right ego))) ego) :stand))) (defn update-from-script [screen {{:keys [current started? channel]} :actions :as entities}] (if current (let [entities (if started? entities (actions/begin current screen entities)) entities (actions/continue current screen entities)] (if (actions/done? current screen entities) (let [terminated (actions/terminate current screen entities)] (put! (actions/get-channel current) terminated) (recur screen (assoc terminated :actions {:channel channel :current nil :started? false :script-running? (get-in entities [:actions :script-running?])}))) (assoc-in entities [:actions :started?] true))) (let [[current _] (alts!! [channel] :default nil)] (assoc entities :actions {:channel channel :current current :started? false :script-running? (get-in entities [:actions :script-running?])})))) (defn update-from-hotspots [screen entities] (if-let [hot-spots (get-in entities [:room :hotspots])] (if-let [hotspot-hit (first (filter #((apply zone/box (:box %)) (get-in entities [:room :entities :ego :x]) (get-in entities [:room :entities :ego :y])) hot-spots))] ((:fn hotspot-hit) screen entities) entities) entities)) (defn update-cursor [screen {{:keys [current override last]} :cursor :as entities}] (let [new-current (or override current)] (when-not (= new-current last) (input! :set-cursor-image (utils/cursor "cursor.png" (or (:cursor new-current) new-current)) 0 0)) (assoc-in entities [:cursor :last] new-current))) (defn get-animation-point [^Animation animation total-time] (loop [time total-time] (if (> (- time (animation! animation :get-animation-duration)) 0) (recur (- time (animation! animation :get-animation-duration))) time))) (defn animate [entity screen] (merge entity (animation->texture (update-in screen [:total-time] #(- % (:anim-start entity))) (:anim entity)) {:current-frame-index (texture! (:anim entity) :get-key-frame-index (get-animation-point (:anim entity) (- (:total-time screen) (:anim-start entity)))) :previous-frame-index (texture! (:anim entity) :get-key-frame-index (get-animation-point (:anim entity) (- (:total-time screen) (:anim-start entity) (or (:delta-time screen) 0))))} (or (get-in entity [:anim-merges (:anim entity)]) (get-in entity [:anim-merges :default])))) (defn get-layers [entities] (let [layers (get-in entities [:room :layers])] (if (map? layers) ((get-in entities [:state :time]) layers) layers))) (defn get-state [] (if (.exists (io/file "save.edn")) (utils/load) {:object nil :active? true :last-room :outside-house :time :day :obtained-items #{} :inventory [] :clues #{} :mints-eaten 0 :seen-intro? false})) (defn fade-in-first-time-if-necessary [screen entities] (if (not (get-in entities [:started? :value])) (do (music! (utils/get-current-music entities) :set-volume (get-in entities [:volume :value])) (utils/play-sound (get-in entities [:musics (actions/get-music (get-in entities [:room :music]) (get-in entities [:state :time]))])) (assoc entities :tweens {:fade-in (tween/tween :fade-in screen [:fade :opacity] 1.0 0.0 1.0 :ease tween/ease-in-cubic) :fade-in-music (tween/tween :fade-in-music screen [:volume :value] 0.0 1.0 1.0 :ease tween/ease-in-cubic)} :started? {:value true :object nil})) entities)) (defn play-key-sounds [entities] (doseq [[target {:keys [previous-frame-index current-frame-index anim-sound-frames anim x y] :as e}] (get-in entities [:room :entities])] (when (and (not= previous-frame-index current-frame-index) ((set (keys anim-sound-frames)) anim)) (when-let [[snd vol-scale] (get-in anim-sound-frames [anim current-frame-index])] (let [vol (if (= target :ego) (* (/ (get-in entities [:room :entities :ego :scale-x]) 1.5) 0.75) (max 0.0 (- 1.0 (/ (utils/dist x y (get-in entities [:room :entities :ego :x]) (get-in entities [:room :entities :ego :y]) :y-sign 2.0 :x-sign (/ 1.0 (get-in entities [:room :entities :ego :scale-x]))) 175.0)))) pan (/ (- (:x e) 160 ) 160) vol (* vol vol-scale) vol (max vol 0.005)] (sound! (or (snd e) (snd (:sounds entities))) :play vol 1.0 pan)))))) (defn update-from-room [screen entities] (if-let [update-fn (get-in entities [:room :update-fn])] (update-fn screen entities) entities)) (defscreen scene :on-timer (fn [screen [entities]] ((get-in entities [:room :timers (:id screen) 2]) screen entities)) :on-show (fn [screen entities] (let [screen (assoc screen :total-time 0)] (let [[cam] (utils/setup-viewport screen 320 240)] (set! (. cam zoom) 0.95) (let [_ (input! :set-cursor-image (utils/cursor "cursor.png" :main) 0 0) rooms {:inside-house (rooms.inside-house/make screen) :inside-stash (rooms.inside-stash/make screen) :outside-house (rooms.outside-house/make screen) :behind-house (rooms.behind-house/make screen) :cat-tree (rooms.cat-tree/make screen) :inside-castle (rooms.inside-castle/make screen) :space (rooms.space/make screen) :inside-cafeteria (rooms.inside-cafeteria/make screen) :inside-antique (rooms.inside-antique/make screen) :inside-jail (rooms.inside-jail/make screen) :dream (rooms.dream/make screen) :castle-gate (rooms.castle-gate/make screen) :outside-jail (rooms.outside-jail/make screen) :outside-castle (rooms.outside-castle/make screen)} entities {:rooms rooms :step-particles (assoc (particle-effect "ego/step") :x 100 :y 100 :baseline 241) :cam {:zoom 0.95 :object nil} :musics {:object nil :inside-antique (utils/make-music "inside-antique.ogg") :town-1 (utils/make-music "town-music-1.ogg") :town-2 (utils/make-music "town-music-2.ogg") :inside-fangald (utils/make-music "inside-fangald.ogg") :fight (utils/make-music "megaboss.mp3") :pull-sword (utils/make-music "pull-sword.ogg") :night (utils/make-music "night.ogg")} :state (get-state) :sounds {:blink (sound "blink-other.ogg") :object nil} :fade (assoc (texture "black.png") :scale-x 20 :scale-y 20 :baseline 9500 :opacity 0.0) :white-fade (assoc (texture "white.png") :scale-x 20 :scale-y 20 :baseline 9500 :opacity 0.0) :actions {:object nil :channel (chan) :current nil :script-running? false :started? false} :volume {:object nil :value 0.0} :music-override {:object nil :value nil} :cursor {:id "cursor" :current :main :last :main :override nil :last-pos [0 0]} :all-items (assoc items/items :object nil) :started? {:value false :object nil} :room (as-> (get rooms (:last-room (get-state))) room (assoc-in room [:entities :ego] (get-ego screen (:start-pos room) ((:scale-fn room) (:start-pos room)))))}] (doseq [[k [start time fn]] (get-in entities [:room :timers])] (add-timer! screen k start time)) #_(when (not (get-in entities [:state :seen-intro?])) ((actions/get-script entities (rooms.dream/do-intro entities)) entities)) (if-let [apply-state (get-in entities [:room :apply-state])] (apply-state entities) entities))))) :on-render (fn [{:keys [camera] :as screen} [entities]] (clear!) (let [entities (fade-in-first-time-if-necessary screen entities) entities (utils/apply-tweens screen entities (:tweens entities)) entities (update-cursor screen entities) entities (update-from-script screen entities) entities (update-from-room screen entities) entities (update-from-hotspots screen entities) entities (assoc-in entities [:room :entities :ego :last-frame] (get-in entities [:room :entities :ego :object])) entities (update-in entities [:room :entities] (fn [entities] (into entities (for [[id entity] entities] (if (:anim entity) [id (animate entity screen)] [id entity]))))) entities (update-in entities [:room :entities] (fn [entities] (into entities (for [[id entity] entities] (if (:update-fn entity) [id ((:update-fn entity) screen entities entity)] [id entity]))))) entities (if (and (nil? (get-in entities [:tweens :cam-x])) (= 1 (rand-int 40))) (actions/pan-to screen entities (+ (get-in entities [:room :entities :ego :x]) (- (rand-int 20) 10)) (+ (get-in entities [:room :entities :ego :y]) (- (rand-int 20) 10)) (constantly (get-in entities [:room :entities :ego :scale-x])) tween/ease-in-out-quadratic 5.0) entities) layers (get-layers entities) all-entities (concat (vals entities) layers (vals (get-in entities [:room :entities])))] (when (nil? (:zoom (:cam entities))) (println entities)) (set! (. camera zoom) (:zoom (:cam entities))) (set! (.. camera position x) (:x (:cam entities) 160.0)) (set! (.. camera position y) (:y (:cam entities) 120.0)) (when (= (get-in entities [:fade :opacity]) 0.0) (play-key-sounds entities)) (doseq [m (vals (get-in entities [:musics]))] (when m (music! m :set-volume (get-in entities [:volume :value])))) (render! screen (sort-by :baseline all-entities)) entities)) :on-resize (fn [{:keys [viewport width height]} [entities]] (.update viewport width height)) :on-hide (fn [screen [entities]] (doseq [snd (->> (get-in entities [:musics]) vals (filter identity))] (utils/stop-sound snd))) :on-mouse-moved (fn [{:keys [input-x input-y viewport] :as screen} [entities]] (if (utils/contains-point? (.getScreenX viewport) (.getScreenY viewport) (.getScreenWidth viewport) (.getScreenHeight viewport) input-x input-y) (let [[x y] (utils/unproject screen)] (utils/update-override (assoc-in entities [:cursor :last-pos] [x y]))) (assoc-in entities [:cursor :override] nil))) :on-touch-up (fn [{:keys [input-x input-y viewport] :as screen} [entities]] (when (utils/contains-point? (.getScreenX viewport) (.getScreenY viewport) (.getScreenWidth viewport) (.getScreenHeight viewport) input-x input-y) (if (= (button-code :right) (:button screen)) (assoc-in entities [:cursor :current] :main) (when (and (get-in entities [:state :active?]) (not (get-in entities [:state :hud-active?]))) (left-click screen entities))))) :on-deactivate (fn [screen [entities]] (assoc-in entities [:state :active?] false)) :on-reactivate (fn [screen [entities]] (-> entities (assoc-in [:state :active?] true) (assoc-in [:cursor :override] nil))) :on-chose-item (fn [{:keys [item]} [entities]] (assoc-in entities [:cursor :current] item)) :on-show-inventory (fn [screen [entities]] (click-inventory screen entities)) :on-menu (fn [screen [entities]] (-> entities (assoc-in [:cursor :override] nil) (assoc-in [:tweens :fade-out-music] (tween/tween :fade-out-music screen [:volume :value] 1.0 0.0 1.0)) (assoc-in [:tweens :fade-out] (tween/tween :fade-out screen [:fade :opacity] 0.0 1.0 1.0 :finish #(do (set-screen! @(resolve 'advent.core/advent) @(resolve 'advent.screens.title/title-screen)) %))))) :on-start-script (fn [{:keys [script]} [entities]] (script entities) entities) :hud-active? (fn [{:keys [hud-active?]} [entities]] (assoc-in entities [:state :hud-active?] hud-active?))) (defn grow-hud [screen entities target up?] (let [grow-or-shrink (if up? :grow :shrink) scale-from (if up? 1.0 1.1) scale-to (if up? 1.1 1.0) opacity-from (if up? 0.8 1.0) opacity-to (if up? 1.0 0.8)] (if (and (not (get-in entities [:tweens [target grow-or-shrink :x]])) (not= scale-to (get-in entities [target :scale-y] 1.0))) (-> entities (assoc-in [:tweens [target grow-or-shrink :y]] (tween/tween [target grow-or-shrink :y] screen [target :scale-y] scale-from scale-to 0.15 :ease tween/ease-in-out-quadratic)) (assoc-in [:tweens [target grow-or-shrink :x]] (tween/tween [target grow-or-shrink :x] screen [target :scale-x] scale-from scale-to 0.15 :ease tween/ease-in-out-quadratic)) (assoc-in [:tweens [target grow-or-shrink :opacity]] (tween/tween [target grow-or-shrink :opacity] screen [target :opacity] opacity-from opacity-to 0.15 :ease tween/ease-in-out-quadratic))) entities))) (defscreen hud :on-show (fn [screen entities] (let [screen (assoc screen :total-time 0)] (utils/setup-viewport screen 320 240) {:close (assoc (texture "close.png") :x 304 :y 224 :width 16 :height 16 :baseline 9000 :opacity 0.8) :inventory (assoc (texture "inventory.png") :x 278 :y 0 :baseline 9000 :mouse-in? (zone/box 278 0 320 42) :opacity 0.8) :fps (assoc (label "0" (color :white) ) :x 5 :baseline 0 :opacity 0.3)})) :on-render (fn [screen [entities]] (let [entities (utils/apply-tweens screen entities (:tweens entities))] (label! (:fps entities) :set-text (str (game :fps))) (render! screen [(:fps entities) (:inventory entities) (:close entities)]) entities)) :on-resize (fn [screen entities] (.update (:viewport screen) (:width screen) (:height screen) true)) :on-mouse-moved (fn [screen [entities]] (let [[x y] (utils/unproject screen) hovered-inventory? ((:mouse-in? (:inventory entities)) x y) hovered-close? (utils/intersects? (:close entities) [x y])] (screen! scene :hud-active? :hud-active? (or hovered-close? hovered-inventory?)) (cond hovered-inventory? (grow-hud screen entities :inventory true) hovered-close? (grow-hud screen entities :close true) :else (let [entities (update-in entities [:tweens] dissoc :inventory-grow-x :inventory-grow-y) entities (grow-hud screen entities :inventory false) entities (grow-hud screen entities :close false)] entities )))) :on-touch-up (fn [screen [entities]] (if (= (button-code :left) (:button screen)) (let [[x y] (utils/unproject screen)] (cond ((:mouse-in? (:inventory entities)) x y) (screen! scene :on-show-inventory) (utils/intersects? (:close entities) [x y]) (screen! scene :on-menu) :else nil)))))