846 lines
47 KiB
Clojure
846 lines
47 KiB
Clojure
(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 Batch]
|
|
[com.badlogic.gdx.math Vector3 Matrix4]
|
|
[com.badlogic.gdx.utils.viewport FitViewport]
|
|
[com.badlogic.gdx.scenes.scene2d Actor Stage]
|
|
[java.lang Object]
|
|
[com.badlogic.gdx Gdx]
|
|
[com.badlogic.gdx.graphics Camera Color GL20 OrthographicCamera
|
|
PerspectiveCamera Pixmap Pixmap$Format PixmapIO Texture
|
|
VertexAttributes$Usage]
|
|
[com.badlogic.gdx.scenes.scene2d Actor Stage]))
|
|
|
|
(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])))
|
|
interactable-entities (if (= (doto (get-in entities [:cursor :current]) println) :main)
|
|
(vals (dissoc (get-in entities [:room :entities]) :ego))
|
|
(vals (get-in entities [:room :entities])))
|
|
interacting-entity (first (sort-by (comp - :baseline)
|
|
(filter #(and (:mouse-in? %)
|
|
(:get-script %)
|
|
((:mouse-in? %) entities x y))
|
|
interactable-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 (utils/current-sound-volume))
|
|
(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])
|
|
scared-walk (utils/make-anim "ego/scared-walk.png" [16 36] 0.05 (range 6))
|
|
sigh (utils/make-anim "ego/sigh.png" [18 36] 0.08 [0 0 0 0 1 1 1 2 3 4 5 6 7 8 8 8 8 8 8 8 8 8 0 0 0 0 ])
|
|
glad (utils/make-anim "ego/glad.png" [20 46] 0.04 (flatten [0 1 2 3 4 (repeat 8 [5 5 5]) (repeat 20 0)]))
|
|
milk (utils/make-anim "ego/squat.png" [18 36] 0.05 [0 1 2 2 3 3 3 3 3 3 6 5 6 5 6 5 6 5 6 5 6 5 6 5 6 5 6 5 6 5 3 3 3 3 3 3 3 3 3 3 3 2 1 0])
|
|
idea (utils/make-anim "ego/idea.png" [18 70] 0.3 [2 0 0 0 0 0 0 2])
|
|
throw (utils/make-anim "ego/throw.png" [18 36] 0.04 (flatten [[(repeat 5 0) (repeat 10 1)] (repeat 3 [2 2 2 3 3 3 4 4 4 5 5 5]) (repeat 5 [2 2 3 3 4 4 5 5]) (repeat 10 [2 3 4 5]) [2 3 3] (repeat 15 6)]))
|
|
swing-shovel (utils/make-anim "ego/swing-shovel.png" [70 70] 0.1 (range 9))
|
|
love (utils/make-anim "ego/love.png" [50 70] 0.1 (flatten [0 0 1 1 2 2 3 3 4 4 5 5 6 6 (repeat 10 7) (repeat 5 8) (repeat 5 7) (repeat 5 8) (repeat 5 7) (repeat 10 [23 24 25 24]) (repeat 30 9) 10 11 12 13 14 15 16 17 18 19 20 21 21 21 22 22 22 21 21 21 21 21 21 21 21 22 22 22 22 22 21 21 21 21 22 22 22 22 22 22 21 21 21 21 21 6 6 5 5 4 4 3 3 2 2 1 1 0]))
|
|
|
|
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
|
|
:scared-walk scared-walk
|
|
:sigh sigh
|
|
:glad glad
|
|
:milk milk
|
|
:throw throw
|
|
:swing-shovel swing-shovel
|
|
:love love
|
|
:idea idea
|
|
}
|
|
: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)
|
|
:sigh (utils/flip sigh)
|
|
:glad (utils/flip glad)
|
|
:milk (utils/flip milk)
|
|
:throw (utils/flip throw)
|
|
:swing-shovel (utils/flip swing-shovel)
|
|
:love (utils/flip love)
|
|
:idea (utils/flip idea)}
|
|
:baseline (- 240 (last start-pos))
|
|
:facing :right
|
|
:origin-x 9
|
|
:origin-y 0
|
|
:scaled true
|
|
:milk-sound (sound "outsidehouse/milk.ogg")
|
|
:step-sound-1 (sound "ego/step-1.ogg")
|
|
:step-sound-2 (sound "ego/step-2.ogg")
|
|
:sigh-sound (sound "ego/sigh.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 (utils/current-sound-volume))
|
|
(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]}
|
|
(get-in ego [:left :sigh]) {1 [:sigh-sound 0.4]}
|
|
(get-in ego [:right :sigh]) {1 [:sigh-sound 0.4]}
|
|
(get-in ego [:left :milk]) {8 [:milk-sound 1.0]}
|
|
(get-in ego [:right :milk]) {8 [:milk-sound 1.0]}
|
|
}
|
|
:anim-merges {(get-in ego [:right :shock]) {:origin-x 15}
|
|
(get-in ego [:left :swing-shovel]) {:origin-x 26}
|
|
(get-in ego [:right :swing-shovel]) {:origin-x 26}
|
|
: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))))
|
|
:origin-x (or (get-in entity [:anim-origins (:anim entity) 0])
|
|
(:base-origin-x entity)
|
|
(:origin-x entity))
|
|
:origin-y (or (get-in entity [:anim-origins (:anim entity) 1])
|
|
(:base-origin-y entity)
|
|
(:origin-y entity))}
|
|
(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 :dream
|
|
:time :day
|
|
:obtained-items #{}
|
|
:inventory []
|
|
:plaques-read #{}
|
|
: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 (utils/current-music-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
|
|
:finish #(if (not (get-in % [:state :seen-intro?]))
|
|
(do ((actions/get-script % (rooms.dream/do-intro %)) entities)
|
|
(assoc-in % [:actions :script-running?] true))
|
|
%))
|
|
: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 (utils/current-sound-volume 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))
|
|
|
|
(defn render-parallax [{:keys [^OrthographicCamera camera ^Stage renderer] :as screen} {:keys [parallax] :as e }]
|
|
|
|
(let [tmp (Vector3.)
|
|
tmp2 (Vector3.)
|
|
parallax-view (Matrix4.)
|
|
parallax-combined (Matrix4.)]
|
|
(.update camera)
|
|
|
|
(.set tmp (.position camera))
|
|
(set! (.x tmp) (* (.x tmp) parallax))
|
|
(set! (.y tmp) (* (.y tmp) parallax))
|
|
(.setToLookAt parallax-view tmp (-> tmp2
|
|
(.set tmp)
|
|
(.add (.direction camera)))
|
|
(.up camera))
|
|
(.set parallax-combined (.projection camera))
|
|
(Matrix4/mul (.val parallax-combined) (.val parallax-view))
|
|
|
|
|
|
(let [^Batch batch (.getBatch renderer)]
|
|
|
|
(.begin batch)
|
|
(.setProjectionMatrix batch parallax-combined)
|
|
|
|
(.setColor batch (color 1 1 1 (or (:opacity e) 1.0)))
|
|
|
|
|
|
(entities/draw! (assoc e :x (+ (/ (:x e) (.zoom camera))
|
|
(- (* 320 parallax 0.5)
|
|
(/ 160 (.zoom camera)) ))
|
|
:y (+ (/ (:y e) (.zoom camera))
|
|
(- (* 240 parallax 0.5)
|
|
(/ 120 (.zoom camera))))) screen batch)
|
|
(.setColor batch (color 1 1 1 1))
|
|
(.end batch))))
|
|
|
|
|
|
(defn shift-range-to-bounds [x1 x2 min max]
|
|
(println x1 x2 "->" (cond (and (< x1 min)
|
|
(> x2 max))
|
|
[min max]
|
|
(< x1 min)
|
|
[min (+ x2 (- min x1))]
|
|
(> x2 max)
|
|
[(- x1 (- x2 max)) max]
|
|
:else
|
|
[x1 x2]))
|
|
(cond (and (< x1 min)
|
|
(> x2 max))
|
|
[min max]
|
|
(< x1 min)
|
|
[min (+ x2 (- min x1))]
|
|
(> x2 max)
|
|
[(- x1 (- x2 max)) max]
|
|
:else
|
|
[x1 x2]))
|
|
|
|
(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
|
|
:paused? false
|
|
: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")
|
|
:love (utils/make-music "love.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
|
|
:origin-x 0
|
|
:origin-y 0)
|
|
:white-fade (assoc (texture "white.png")
|
|
:scale-x 20
|
|
:scale-y 20
|
|
:baseline 9500
|
|
:opacity 0.0
|
|
:origin-x 0
|
|
:origin-y 0)
|
|
:dawn (assoc (texture "dawn.png")
|
|
:x 0 :y 0 :baseline 240
|
|
:colorize? true
|
|
: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))
|
|
|
|
|
|
|
|
(if-let [apply-state (get-in entities [:room :apply-state])]
|
|
(apply-state entities)
|
|
entities)))))
|
|
|
|
:on-resume (fn [screen [entities]]
|
|
(doseq [[k [start time fn]] (get-in entities [:room :timers])]
|
|
(add-timer! screen k start time)))
|
|
|
|
: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 (not (get-in entities [:cam :paused?]))
|
|
(nil? (get-in entities [:tweens :cam-x]))
|
|
(= 1 (rand-int 20)))
|
|
(if (= (rand-int 2) 1)
|
|
(actions/pan-to screen entities
|
|
(get-in entities [:room :entities :ego :x])
|
|
(get-in entities [:room :entities :ego :y])
|
|
(constantly (get-in entities [:room :entities :ego :scale-x]))
|
|
tween/ease-in-out-quadratic
|
|
5.0)
|
|
(actions/pan-to screen entities
|
|
(+ (get-in entities [:cam :x] 0)
|
|
(- 10 (rand-int 20)))
|
|
(+ (get-in entities [:cam :y] 0)
|
|
(- 10 (rand-int 20)))
|
|
(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])))]
|
|
(screen! talking-screen :on-update-camera :scene-viewport (:viewport screen) :scene-camera (:camera screen))
|
|
(when (not (get-in entities [:cam :paused?]))
|
|
(set! (. camera zoom) (:zoom (:cam entities)))
|
|
(set! (.. camera position x) (:x (:cam entities) 160.0))
|
|
(set! (.. camera position y) (:y (:cam entities) 120.0)))
|
|
(let [entities (utils/update-override screen entities)]
|
|
|
|
|
|
(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 (utils/current-music-volume (get-in entities [:volume :value])))))
|
|
(doseq [e (sort-by :baseline all-entities)]
|
|
(if (:parallax e)
|
|
(render-parallax screen e)
|
|
(render! screen [e])))
|
|
|
|
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)
|
|
|
|
(utils/update-override screen (assoc-in entities [:cursor :last-pos] [input-x input-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?]))
|
|
(= 0.0 (get-in entities [:fade :opacity])))
|
|
(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 (.clear @(resolve 'advent.core/am))
|
|
(input! :set-cursor-image (utils/cursor "cursor.png" :main) 0 0)
|
|
(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 "" (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)))))
|