2085 lines
99 KiB
Clojure
2085 lines
99 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]
|
|
[clojure.tools.logging :as log]
|
|
[advent.pathfind]
|
|
[advent.actions :as actions]
|
|
[advent.zone :as zone]
|
|
[advent.utils :as utils]
|
|
[advent.saves :as saves]
|
|
[advent.tween :as tween]
|
|
[advent.steam :as steam]
|
|
[advent.screens.rooms :as rooms]
|
|
[advent.screens.fade :refer [fade-screen]]
|
|
[advent.screens.items :as items]
|
|
[advent.screens.rooms.dream :as rooms.dream]
|
|
[advent.screens.rooms.ending :as rooms.ending]
|
|
[advent.screens.rooms.castle-gate :as rooms.castle-gate]
|
|
[advent.screens.rooms.common :as common]
|
|
[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.held :as rooms.held]
|
|
[advent.screens.rooms.cat-tree :as rooms.cat-tree]
|
|
[advent.screens.dialogue :refer [talking-screen toast-screen tooltip-screen]]
|
|
[advent.screens.inventory :refer [inventory-screen]]
|
|
[clojure.core.async :refer [put! <! <!! >! chan go thread take! alts!! poll! dropping-buffer]])
|
|
(:import [com.badlogic.gdx.graphics Pixmap$Format 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.utils Align]
|
|
[com.badlogic.gdx.scenes.scene2d Actor Stage]
|
|
[com.badlogic.gdx.graphics.glutils ShaderProgram]
|
|
[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]))
|
|
|
|
#_(set! *unchecked-math* :warn-on-boxed)
|
|
|
|
(declare hud)
|
|
|
|
(declare get-selected-inventory-item)
|
|
|
|
(def v-shader "attribute vec4 a_position;
|
|
attribute vec4 a_color;
|
|
attribute vec2 a_texCoord0;
|
|
|
|
uniform mat4 u_projTrans;
|
|
|
|
varying vec4 v_color;
|
|
varying vec2 v_texCoords;
|
|
|
|
void main() {
|
|
v_color = a_color;
|
|
v_texCoords = a_texCoord0;
|
|
gl_Position = u_projTrans * a_position;
|
|
}")
|
|
|
|
|
|
|
|
(def pix-shader "
|
|
#ifdef GL_ES
|
|
#define LOWP lowp
|
|
precision mediump float;
|
|
#else
|
|
#define LOWP
|
|
#endif
|
|
|
|
varying LOWP vec4 v_color;
|
|
varying vec2 v_texCoords;
|
|
uniform float multiply_amount;
|
|
uniform float hue_amount;
|
|
|
|
uniform sampler2D u_texture;
|
|
|
|
float Epsilon = 1e-10;
|
|
|
|
vec3 RGBtoHCV (vec3 RGB)
|
|
{
|
|
// Based on work by Sam Hocevar and Emil Persson
|
|
vec4 P = (RGB.g < RGB.b) ? vec4 (RGB.bg, -1.0, 2.0/3.0) : vec4 (RGB.gb, 0.0, -1.0/3.0);
|
|
vec4 Q = (RGB.r < P.x) ? vec4 (P.xyw, RGB.r) : vec4 (RGB.r, P.yzx);
|
|
float C = Q.x - min (Q.w, Q.y);
|
|
float H = abs ((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);
|
|
return vec3 (H, C, Q.x);
|
|
}
|
|
|
|
vec3 HUEtoRGB(float H)
|
|
{
|
|
float R = abs(H * 6.0 - 3.0) - 1.0;
|
|
float G = 2.0 - abs(H * 6.0 - 2.0);
|
|
float B = 2.0 - abs(H * 6.0 - 4.0);
|
|
return clamp(vec3(R,G,B), 0.0, 1.0);
|
|
}
|
|
|
|
vec3 HSLtoRGB(vec3 HSL)
|
|
{
|
|
vec3 RGB = HUEtoRGB(HSL.x);
|
|
float C = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y;
|
|
return (RGB - 0.5) * C + HSL.z;
|
|
}
|
|
|
|
|
|
vec3 RGBtoHSL(vec3 RGB)
|
|
{
|
|
vec3 HCV = RGBtoHCV(RGB);
|
|
float L = HCV.z - HCV.y * 0.5;
|
|
float S = HCV.y / (1.0 - abs(L * 2.0 - 1.0) + Epsilon);
|
|
return vec3(HCV.x, S, L);
|
|
}
|
|
|
|
vec3 BlendHue(vec3 base, vec3 blend)
|
|
{
|
|
if (blend.r == blend.g && blend.g == blend.b) {
|
|
return base;
|
|
}
|
|
else {
|
|
vec3 baseHSL = RGBtoHSL(base);
|
|
return HSLtoRGB(vec3(RGBtoHSL(blend).r, baseHSL.g, baseHSL.b));
|
|
}
|
|
}
|
|
|
|
#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O))
|
|
|
|
|
|
|
|
void main ()
|
|
{
|
|
|
|
vec2 sz = vec2 (2048.0, 2048.0);
|
|
vec3 step = vec3 (1.0 / 4.0, 1.0 / 4.0, 0.0);
|
|
vec2 tex_pixel = sz * v_texCoords - step.xy / 2.0;
|
|
|
|
vec2 corner = floor (tex_pixel) + 1.0;
|
|
vec2 frac = min ((corner - tex_pixel) * vec2 (4.0, 4.0), vec2 (1.0, 1.0));
|
|
|
|
vec4 c1 = texture2D (u_texture, (floor (tex_pixel + step.zz) + 0.5) / sz);
|
|
vec4 c2 = texture2D (u_texture, (floor (tex_pixel + step.xz) + 0.5) / sz);
|
|
vec4 c3 = texture2D (u_texture, (floor (tex_pixel + step.zy) + 0.5) / sz);
|
|
vec4 c4 = texture2D (u_texture, (floor (tex_pixel + step.xy) + 0.5) / sz);
|
|
|
|
c1 *= frac.x * frac.y;
|
|
c2 *= (1.0 - frac.x) * frac.y;
|
|
c3 *= frac.x * (1.0 - frac.y);
|
|
c4 *= (1.0 - frac.x) * (1.0 - frac.y);
|
|
|
|
vec4 scaledColor = (c1 + c2 + c3 + c4);
|
|
|
|
vec3 multiplied = mix(scaledColor.rgb, v_color.rgb * scaledColor.rgb, multiply_amount * 0.67 );
|
|
vec3 hued = mix(multiplied, BlendHue(multiplied.rgb, v_color.rgb), hue_amount * 0.67);
|
|
vec3 final = hued;
|
|
|
|
gl_FragColor = vec4(final[0], final[1], final[2], scaledColor.a * v_color.a);
|
|
|
|
}
|
|
")
|
|
;
|
|
|
|
(defn ensure-on-screen [l]
|
|
(let [margin-width (* 0.05 320)
|
|
minimum-x margin-width
|
|
maximum-x (- 320 margin-width)
|
|
label-width (label! l :get-width)
|
|
label-right (+ (:x l) (/ label-width 2))
|
|
l (cond (> label-right maximum-x) (assoc l :x (- maximum-x label-width))
|
|
(< (:x l) minimum-x) (assoc l :x minimum-x)
|
|
:else l)]
|
|
l))
|
|
|
|
|
|
|
|
(defn get-script-selector [entities]
|
|
(or (get-selected-inventory-item) :main))
|
|
|
|
(def default-interaction
|
|
{:get-script (fn [cursor [x y]] (if (= :main cursor)
|
|
(actions/get-script entities
|
|
(actions/walk-to entities :ego [x y] :skip-type :end))
|
|
(actions/get-script entities
|
|
(actions/talk entities :ego "There's nothing to do with that."))))})
|
|
|
|
|
|
|
|
|
|
|
|
(defn skip-action [screen entities]
|
|
(let [current-action (get-in entities [:fg-actions :current])]
|
|
(cond (= :skip (actions/skip-type 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 [:fg-actions :current] nil)
|
|
(assoc-in [:fg-actions :started?] false))))
|
|
|
|
(= :end (actions/skip-type current-action screen entities))
|
|
(let [terminated-entities (actions/terminate current-action screen entities)]
|
|
(log/info "Attempting to end action")
|
|
(actions/force-end terminated-entities current-action :fg-actions)
|
|
)
|
|
:else
|
|
entities)))
|
|
|
|
(defn click-inventory [screen entities]
|
|
(if (get-in entities [:fg-actions :script-running?])
|
|
(skip-action screen entities)
|
|
(assoc-in entities [:state :active?] false)))
|
|
|
|
(defn open-inventory [screen entities]
|
|
(screen! inventory-screen :show-screen { :items (map (entities :all-items) (get-in entities [:state :inventory]))})
|
|
(assoc-in entities [:state :active?] false))
|
|
|
|
|
|
|
|
(defn get-interaction [entities x y]
|
|
(first (filter #((:mouse-in? %) entities x y)
|
|
(get-in entities [:room :interactions]))) )
|
|
|
|
(defn get-interacting-entity [entities x y]
|
|
(let [interactable-entities (if (= (doto (get-selected-inventory-item)
|
|
(#(log/info "clicked with " %)) ) :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)))]
|
|
interacting-entity))
|
|
|
|
(defn left-click [screen entities options]
|
|
(println "x y" (:input-x options) (:input-y options))
|
|
(let [[x y] (utils/unproject screen options)
|
|
_ (log/info (str "clicked " x y))
|
|
interaction (get-interaction entities x y)
|
|
interacting-entity (get-interacting-entity entities x y)
|
|
current-action (get-in entities [:fg-actions :current])
|
|
;; TODO - hacky way of resetting queue
|
|
|
|
entities (if current-action
|
|
(skip-action screen entities)
|
|
entities)]
|
|
|
|
|
|
(when (and (not (get-in entities [:fg-actions :script-running?]))
|
|
(or (= (get-in entities [:cursor :down-target])
|
|
(or (:id interacting-entity) (:id interaction) nil))
|
|
(get-in entities [:cursor :came-from-inventory?])))
|
|
((or (when (and (not (:override-cursor interaction))
|
|
interacting-entity)
|
|
(do (screen! hud :on-start-script {})
|
|
((:get-script interacting-entity) (get-script-selector entities) [x y])))
|
|
(when interaction
|
|
(do (screen! hud :on-start-script {})
|
|
((:get-script interaction) (get-script-selector entities)
|
|
[x y])))
|
|
|
|
((:get-script default-interaction) (get-script-selector entities) [x y])) entities))
|
|
(assoc-in entities [:cursor :down-target] nil)))
|
|
|
|
(defn handle-touch-up [{:keys [^FitViewport viewport] :as screen} entities {:keys [input-x input-y] :as options}]
|
|
(let [entities (assoc-in entities [:cursor :depressed?] false)]
|
|
(cond
|
|
(not (utils/contains-point? (.getScreenX viewport) (.getScreenY viewport)
|
|
(.getScreenWidth viewport) (.getScreenHeight viewport)
|
|
input-x input-y))
|
|
entities
|
|
|
|
(= (button-code :right)
|
|
(:button options))
|
|
(do (screen! hud :on-return-item {})
|
|
entities)
|
|
|
|
(and (get-in entities [:state :active?])
|
|
(or (not (get-in entities [:state :hud-active?]))
|
|
(get-in entities [:fg-actions :script-running?]))
|
|
(= 0.0 (get-in entities [:fade :opacity])))
|
|
(left-click screen entities options)
|
|
|
|
:else
|
|
entities)))
|
|
|
|
(defn get-ego-script [cursor [x y]]
|
|
|
|
(condp = (:value cursor)
|
|
:charcoal
|
|
(common/one-liner "Just a dark piece of charcoal.")
|
|
|
|
:flask-1-with-cream-of-mushroom
|
|
(actions/get-script entities (actions/talk entities :ego "Blegh! Gross!"))
|
|
|
|
:flask-1-strength
|
|
(actions/get-script entities
|
|
(cond (= :held
|
|
(get-in @entities [:state :last-room]))
|
|
(common/do-win entities)
|
|
|
|
(= :space
|
|
(get-in @entities [:state :last-room]))
|
|
(actions/talk entities :ego "No time for that!")
|
|
|
|
(= :inside-jail
|
|
(get-in @entities [:state :last-room]))
|
|
(do
|
|
(actions/talk entities :ego "I'll just take a sip!")
|
|
(actions/play-animation entities :ego :grow :stop? false)
|
|
(actions/talk entities :warden "Huh? What was that?!")
|
|
(Thread/sleep 1000)
|
|
(actions/talk entities :warden "Hey, get back in jail!")
|
|
(common/go-to-jail entities))
|
|
|
|
:else
|
|
(do
|
|
(actions/talk entities :ego "I'd better save this strength potion for just the right moment!"))))
|
|
|
|
: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 "- A bowl of soup, shroom cream will do"
|
|
:ego "- Spit of beast whose strength will imbue"
|
|
:ego "- Mandrake root completes the brew"
|
|
:ego "A word of warning, before you go.\nA sip is all it takes to grow."
|
|
:ego "Not more than that do drink,\nOr risk your body pushed to brink.\""
|
|
:ego "Hmm. I wonder what that last part means?"))
|
|
|
|
:portrait
|
|
(actions/get-script entities
|
|
(actions/do-dialogue entities
|
|
:ego "It's a portrait of a young man."
|
|
:ego "It has something written on it, but it's very dim."))
|
|
|
|
:note-1
|
|
(actions/get-script entities (common/read-note-1 entities))
|
|
|
|
:note-2
|
|
(actions/get-script entities (common/read-note-2 entities))
|
|
|
|
:camera
|
|
(common/one-liner "It's some sort of magical device that captures images.")
|
|
|
|
:tune
|
|
(actions/get-script entities
|
|
(cond
|
|
(get-in @entities [:room :entities :wizard])
|
|
(do
|
|
(actions/talk entities :ego "Better not hum it with Gandarf around!")
|
|
(actions/talk entities :wizard "What's that, boy?")
|
|
(actions/talk entities :ego "Oh... Erm... Nothing."))
|
|
|
|
(= :space
|
|
(get-in @entities [:state :last-room]))
|
|
(actions/talk entities :ego "No time for that!")
|
|
|
|
(= :inside-jail
|
|
(get-in @entities [:state :last-room]))
|
|
|
|
(do
|
|
(actions/talk entities :ego "I'll whistle it really quietly.")
|
|
(actions/play-safe entities)
|
|
(actions/do-dialogue entities :warden "Huh? What was that?"
|
|
:warden "Get back in yer cell!")
|
|
(common/go-to-jail entities)
|
|
(Thread/sleep 500)
|
|
(actions/play-animation entities :ego :sigh)
|
|
(actions/talk entities :ego "You really are a sucker for punishment, aren't you?")
|
|
(steam/set-achievement "FOOLISH_LULLABY"))
|
|
:else
|
|
(do
|
|
(actions/talk entities :ego "Ugh! I have Gandarf's MagiSafe 2000 tune stuck in my head.")
|
|
(actions/play-safe entities))))
|
|
|
|
:alarm-clock
|
|
(common/one-liner "It's a magic device that tells the time.")
|
|
|
|
:walkie-talkies
|
|
(common/one-liner "If I talk in one of these devices, I can hear it in the other one!")
|
|
|
|
:mushrooms
|
|
(actions/get-script entities
|
|
(actions/do-dialogue entities
|
|
:ego "I don't really care for mushrooms."
|
|
:ego "... but I'll give it a shot.")
|
|
(actions/play-animation entities :ego :get-sick)
|
|
(actions/do-dialogue entities :ego "Yuck!"))
|
|
|
|
:stick
|
|
(common/one-liner "It's a huge stick.")
|
|
|
|
:wool
|
|
(common/one-liner "Better not wash it in hot water.")
|
|
|
|
:spell-component
|
|
(common/one-liner "It needs to go into the cauldron.")
|
|
|
|
:feather
|
|
(common/one-liner "An owl feather. Smells like puke.")
|
|
|
|
:ball-n-chain
|
|
(common/one-liner "Why am I lugging this around? It's so heavy.")
|
|
|
|
:flask-water
|
|
(common/one-liner "Gandarf knows what to do next with this.")
|
|
|
|
:broom
|
|
(common/one-liner "A janitor's broom.")
|
|
|
|
:glass-eye
|
|
(common/one-liner "It's a glass eye.")
|
|
|
|
:flask-1-slobber
|
|
(common/one-liner "It's got some bull slobber in it.")
|
|
|
|
:crowbar
|
|
(common/one-liner "It can probably bend steel!")
|
|
|
|
:monocle
|
|
(common/one-liner "It's a monocle.")
|
|
|
|
:used-earplugs
|
|
(common/one-liner "They've got earwax all over them. No thanks.")
|
|
|
|
:broken-clock
|
|
(common/one-liner "Split right down the middle.")
|
|
|
|
:trophy
|
|
(common/one-liner "I've proven myself in wisdom!")
|
|
|
|
:carrot
|
|
(common/one-liner "I'm not that hungry.")
|
|
|
|
:ladder
|
|
(common/one-liner "It's the Duke's ladder.")
|
|
|
|
:motivational-tapes
|
|
(common/one-liner "If only I had a VCR. I'd get my life back together.")
|
|
|
|
:sack-lunch
|
|
(common/one-liner "Ugh, gross! The blue cheese smells really strong.")
|
|
|
|
:grass
|
|
(common/one-liner "This is top quality, high protein stuff!")
|
|
|
|
:cat-toy
|
|
(common/one-liner "It's a little cat toy!")
|
|
|
|
:ash
|
|
(common/one-liner "A spell's ashes.")
|
|
|
|
:shovel
|
|
(common/one-liner "A grave-digger's shovel.")
|
|
|
|
:mandrake
|
|
(common/one-liner "It's some kind of root.")
|
|
|
|
:flask-water-flies
|
|
(common/one-liner "Looks like I need to add the ashes of magic.")
|
|
|
|
:flask-1
|
|
(common/one-liner "An empty flask.")
|
|
|
|
:flask-flies-ash
|
|
(common/one-liner "Looks like I need to stir it with the gift of flight.")
|
|
|
|
:magic-slingshot
|
|
(common/one-liner "The Slinger's Shot, fully restored.")
|
|
|
|
:frog-legs
|
|
(common/one-liner "I wonder where the head is...")
|
|
|
|
:sword
|
|
(common/one-liner "Yowza! The Sword of Blergh's sharp as a razor.")
|
|
|
|
:medal
|
|
(common/one-liner "I've proven myself worthy in strength!")
|
|
|
|
:spear
|
|
(common/one-liner "A knight's spear.")
|
|
|
|
:slobber
|
|
(common/one-liner "I wonder why I am carrying this drool around.")
|
|
|
|
:kiss
|
|
(common/one-liner "Yuck! A kiss for my bravery.")
|
|
|
|
:flask-1-with-milk
|
|
(common/one-liner "I've got some sheep's milk in my flask.")
|
|
|
|
:flask-1-with-mushrooms
|
|
(common/one-liner "I've got some mushrooms in my flask. It still needs some cream.")
|
|
|
|
:balloon
|
|
(common/one-liner "My choicest balloon would be blue. But he didn't give me a choice.")
|
|
|
|
:money
|
|
(common/one-liner "It's got the Duke of Remington's face on it.")
|
|
|
|
:flask-2
|
|
(common/one-liner "I need to fill it with fountain water.")
|
|
|
|
:key
|
|
(common/one-liner "It's the key to the jail.")
|
|
|
|
:flask-water-ash
|
|
(common/one-liner "Looks like I need the sound of buzzing.")
|
|
|
|
:slingshot
|
|
(common/one-liner "The Slinger's Shot.")
|
|
|
|
:teddy
|
|
(common/one-liner "It's the choicest teddy.")
|
|
|
|
:flies
|
|
(common/one-liner "I don't want any of them to buzz off.")
|
|
|
|
:rope
|
|
(common/one-liner "A nice, sturdy, rope.")
|
|
|
|
nil))
|
|
|
|
(defn get-ego [screen start-pos start-scale]
|
|
(let [player-sheet (texture! (utils/get-texture "player.png") :split 18 36)
|
|
talk-sheet (texture! (utils/get-texture "ego/talk.png") :split 18 36)
|
|
stand-sheet (texture! (utils/get-texture "ego/stand.png") :split 18 36)
|
|
squat-sheet (texture! (utils/get-texture "ego/squat.png") :split 18 36)
|
|
reach-sheet (texture! (utils/get-texture "ego/reach.png") :split 18 36)
|
|
grow-sheet (texture! (utils/get-texture "ego/grow.png") :split 18 36)
|
|
cat-toy-sheet (texture! (utils/get-texture "ego/cat-toy.png") :split 41 50)
|
|
fire-sheet (texture! (utils/get-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))))
|
|
start-squat-2 (animation 0.05 (for [i [0 1 2 3]]
|
|
(texture (aget squat-sheet 0 i))))
|
|
|
|
|
|
end-squat (animation 0.05 (for [i [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))))
|
|
shy (animation 0.2 (for [i [0 1 2 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0]]
|
|
(texture (aget fire-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))))
|
|
squat-talk (utils/make-anim "ego/squat-talk.png" [18 36] 0.2 [0 1 0 2 1 0 3])
|
|
frog (utils/make-anim "ego/frog.png" [16 36] 0.1 [0])
|
|
frog-nod (utils/make-anim "ego/frog.png" [16 36] 0.2 [0 1 0 1 0 1 0 1])
|
|
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]]))
|
|
jump-straight (utils/make-anim "ego/jump-straight.png" [18 48] 0.075 [0 1 1 1 1 1 1 2 3])
|
|
climb (utils/make-anim "ego/climb.png" [22 46] 0.3 [0 1 3 2 4 3 2 4 3 5 6 5 6 5 6 5 6 5 6 7 8 7 8 9 10 9 10 10 10 10 10 8 8 6 6 1 0])
|
|
poke (utils/make-anim "ego/poke.png" [20 50] 0.2 [0 1 2 3 2 3 2 3 2 3 1 0])
|
|
jumping-straight (utils/make-anim "ego/jump-straight.png" [18 48] 0.075 (repeat 30 4))
|
|
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 (utils/make-anim "ego/get-sick.png" [18 36] 0.1 (flatten [(range 6) (repeat 10 5) (reverse (range 6) ) 0 0 0 0 0 0]))
|
|
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 33 6)]))
|
|
frustrated-talk (utils/make-anim "ego/frustrated-talk.png" [16 36] 0.2 (flatten (range 6)))
|
|
swing-shovel (utils/make-anim "ego/swing-shovel.png" [70 70] 0.1 (range 9))
|
|
love (utils/make-anim-seq "ego/love" [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]))
|
|
whistle (utils/make-anim-seq "ego/whistle" [18 36] 0.2 (flatten [0 1 1 (repeat 200 [2 3])]))
|
|
axe (utils/make-anim "ego/axe.png" [60 70] 0.10 (flatten [1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 (range 7)]))
|
|
axe-wood (utils/make-anim "ego/axe-wood.png" [60 70] 0.10 (flatten [1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 (range 11)]))
|
|
suspended (utils/make-anim "ego/suspended.png" [20 36] 0.10 [0])
|
|
suspended-talk (utils/make-anim "ego/suspended.png" [20 36] 0.20 (range 7))
|
|
crawl (utils/make-anim "ego/crawl.png" [39 25] 0.2 (range 4))
|
|
crawl-stand (utils/make-anim "ego/crawl.png" [39 25] 0.2 [0])
|
|
crawl-hide (utils/make-anim "ego/crawl.png" [39 25] 0.1 (flatten [(repeat 10 3) (range 4 7) (repeat 50 6) (reverse (range 4 7) ) (repeat 20 3)]))
|
|
standup (utils/make-anim "ego/standup.png" [45 55] 0.2 (range 5))
|
|
hand-hold (utils/make-anim "ego/hand-hold.png" [18 36] 0.2 [0 1])
|
|
choose-step-sound (fn [entities]
|
|
(if (#{:inside-house :inside-stash :inside-cafeteria :inside-antique :inside-jail}
|
|
(get-in entities [:state :last-room]))
|
|
(rand-nth [:inside-step-sound-1 :inside-step-sound-2 :inside-step-sound-3 :inside-step-sound-4])
|
|
(rand-nth [:step-sound-1 :step-sound-2 :step-sound-3 :step-sound-4])))
|
|
|
|
|
|
|
|
ego {:right {:walk walk-right
|
|
:stand stand-anim
|
|
:talk talk-anim
|
|
:squat squat-anim
|
|
:squat-talk squat-talk
|
|
:start-squat start-squat
|
|
:start-squat-2 start-squat-2
|
|
: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
|
|
:jump-straight jump-straight
|
|
:jumping-straight jumping-straight
|
|
: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
|
|
:frog frog
|
|
:frog-nod frog-nod
|
|
:scared-talk scared-talk
|
|
:scared-walk scared-walk
|
|
:sigh sigh
|
|
:glad glad
|
|
:milk milk
|
|
:throw throw
|
|
:swing-shovel swing-shovel
|
|
:love love
|
|
:idea idea
|
|
:axe axe
|
|
:axe-wood axe-wood
|
|
:suspended suspended
|
|
:suspended-talk suspended-talk
|
|
:crawl crawl
|
|
:crawl-stand crawl-stand
|
|
:crawl-hide crawl-hide
|
|
:standup standup
|
|
:frustrated-talk frustrated-talk
|
|
:hand-hold hand-hold
|
|
:shy shy
|
|
:climb climb
|
|
:poke poke
|
|
:whistle whistle
|
|
}
|
|
:left {:walk (utils/flip walk-right)
|
|
:stand (utils/flip stand-anim)
|
|
:talk (utils/flip talk-anim)
|
|
:squat-talk (utils/flip squat-talk)
|
|
:start-squat (utils/flip start-squat)
|
|
:start-squat-2 (utils/flip start-squat-2)
|
|
: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)
|
|
:jump-straight (utils/flip jump-straight)
|
|
:jumping-straight (utils/flip jumping-straight)
|
|
: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)
|
|
:frog (utils/flip frog)
|
|
:frog-nod (utils/flip frog-nod)
|
|
:love (utils/flip love)
|
|
:idea (utils/flip idea)
|
|
:axe (utils/flip axe)
|
|
:axe-wood (utils/flip axe-wood)
|
|
:suspended (utils/flip suspended)
|
|
:suspended-talk (utils/flip suspended-talk)
|
|
:crawl (utils/flip crawl)
|
|
:crawl-stand (utils/flip crawl-stand)
|
|
:crawl-hide (utils/flip crawl-hide)
|
|
:standup (utils/flip standup)
|
|
:frustrated-talk (utils/flip frustrated-talk)
|
|
:hand-hold (utils/flip hand-hold)
|
|
:shy (utils/flip shy)
|
|
:climb (utils/flip climb)
|
|
:poke (utils/flip poke)
|
|
:whistle (utils/flip whistle)
|
|
}
|
|
:baseline (- 240 (double (last start-pos)))
|
|
:facing :right
|
|
:night-profile :sprite
|
|
:origin-x 9
|
|
:origin-y 0
|
|
:scaled true
|
|
:drop-sound (utils/load-sound "ego/drop.ogg")
|
|
:milk-sound (utils/load-sound "outsidehouse/milk.ogg")
|
|
:step-sound-1 (utils/load-sound "ego/step-1.ogg")
|
|
:step-sound-2 (utils/load-sound "ego/step-2.ogg")
|
|
:step-sound-3 (utils/load-sound "ego/step-3.ogg")
|
|
:step-sound-4 (utils/load-sound "ego/step-4.ogg")
|
|
:shoot-sound (utils/load-sound "ego/slingshot.ogg")
|
|
:glad-sound (utils/load-sound "ego/glad.ogg")
|
|
|
|
:get-sick-sound (utils/load-sound "ego/get-sick.ogg")
|
|
:scratch-sound (utils/load-sound "ego/scratch.ogg")
|
|
:scared-step-sound (utils/load-sound "ego/scared-step.ogg")
|
|
|
|
:inside-step-sound-1 (utils/load-sound "ego/inside-step-1.ogg")
|
|
:inside-step-sound-2 (utils/load-sound "ego/inside-step-2.ogg")
|
|
:inside-step-sound-3 (utils/load-sound "ego/inside-step-3.ogg")
|
|
:inside-step-sound-4 (utils/load-sound "ego/inside-step-4.ogg")
|
|
:crowbar-sound (utils/load-sound "ego/crowbar.ogg")
|
|
:sigh-sound (utils/load-sound "ego/sigh.ogg")
|
|
:axe-sound (utils/load-sound "ego/axe.ogg")
|
|
:breakglass-sound (utils/load-sound "ego/breakglass.ogg")
|
|
:idea-sound (utils/load-sound "ego/idea.ogg")
|
|
:scale-x start-scale
|
|
:scale-y start-scale
|
|
:talk-color (color 0.6 1.0 1.0 1.0)
|
|
:stand-override nil
|
|
:mouse-in? (fn [entities x y]
|
|
(let [{^double entity-x :x ^double entity-y :y ^TextureRegion region :object scale :scale-x} (get-in entities [:room :entities :ego])
|
|
half-width (double (/ (* (.getRegionWidth region) (double (or scale 1.0))) 2))
|
|
height (double (* (.getRegionHeight region) (double (or scale 1.0))))]
|
|
|
|
((zone/box (- entity-x half-width) entity-y (+ entity-x half-width) (+ entity-y height)) x y)))
|
|
:get-script get-ego-script
|
|
:x (first start-pos) :y (last start-pos)
|
|
:id "ego"}
|
|
|
|
ego (assoc ego :anim-sound-frames {(get-in ego [:left :walk]) {2 [choose-step-sound 0.5]
|
|
6 [choose-step-sound 0.5]}
|
|
(get-in ego [:right :walk]) {2 [choose-step-sound 0.5]
|
|
6 [choose-step-sound 0.5]}
|
|
|
|
(get-in ego [:left :talk] ) {2 [:blink 0.15]}
|
|
(get-in ego [:right :talk] ) {2 [:blink 0.15]}
|
|
(get-in ego [:left :grow] ) {1 [:grow-sound 0.75]}
|
|
(get-in ego [:right :grow] ) {1 [:grow-sound 0.75]}
|
|
(get-in ego [:left :crowbar] ) {3 [:crowbar-sound 0.5]}
|
|
(get-in ego [:right :crowbar] ) {3 [:crowbar-sound 0.5]}
|
|
(get-in ego [:right :shoot] ) {14 [:shoot-sound 0.75]}
|
|
(get-in ego [:left :shoot] ) {14 [:shoot-sound 0.75]}
|
|
|
|
(get-in ego [:left :get-sick] ) {1 [:get-sick-sound 0.55]}
|
|
(get-in ego [:right :get-sick] ) {1 [:get-sick-sound 0.55]}
|
|
(get-in ego [:right :scared-walk] ) {0 [:scared-step-sound 0.15 1.5]
|
|
4 [:scared-step-sound 0.15 1.9]}
|
|
(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]
|
|
200 [:scratch-sound 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]
|
|
200 [:scratch-sound 0.15]
|
|
}
|
|
(get-in ego [:left :sigh]) {3 [:sigh-sound 0.4]}
|
|
(get-in ego [:right :sigh]) {3 [:sigh-sound 0.4]}
|
|
(get-in ego [:left :milk]) {8 [:milk-sound 1.0]}
|
|
(get-in ego [:left :glad]) {1 [:glad-sound 0.5]}
|
|
(get-in ego [:right :glad]) {1 [:glad-sound 0.5]}
|
|
(get-in ego [:right :milk]) {8 [:milk-sound 1.0]}
|
|
(get-in ego [:left :idea]) {1 [:idea-sound 1.0]}
|
|
(get-in ego [:right :idea]) {1 [:idea-sound 1.0]}
|
|
(get-in ego [:right :axe-wood]) {20 [:axe-sound 1.0]}
|
|
(get-in ego [:right :axe]) {20 [:axe-sound 1.0]}
|
|
(get-in ego [:left :swing-shovel]) {3 [:breakglass-sound 1.0]}
|
|
(get-in ego [:right :swing-shovel]) {3 [:breakglass-sound 1.0]}}
|
|
:anim-merges {(get-in ego [:right :shock]) {:origin-x 15}
|
|
(get-in ego [:left :frustrated-talk]) {:origin-x 7}
|
|
(get-in ego [:left :jump-straight]) {:origin-x 9}
|
|
(get-in ego [:right :jump-straight]) {:origin-x 9}
|
|
(get-in ego [:left :poke]) {:origin-x 10}
|
|
(get-in ego [:right :poke]) {:origin-x 10}
|
|
(get-in ego [:left :jumping-straight]) {:origin-x 9}
|
|
(get-in ego [:left :cat-toy]) {:origin-x 32}
|
|
(get-in ego [:right :jumping-straight]) {:origin-x 9}
|
|
(get-in ego [:left :swing-shovel]) {:origin-x 26}
|
|
(get-in ego [:right :swing-shovel]) {:origin-x 26}
|
|
(get-in ego [:left :glad]) {:origin-x 11}
|
|
(get-in ego [:right :glad]) {:origin-x 11}
|
|
(get-in ego [:left :climb]) {:origin-x 11}
|
|
(get-in ego [:right :climb]) {:origin-x 11}
|
|
(get-in ego [:left :whistle]) {:origin-x 7}
|
|
(get-in ego [:right :standup]) {:origin-x 32}
|
|
(get-in ego [:right :crawl]) {:origin-x 32}
|
|
(get-in ego [:right :crawl-hide]) {:origin-x 32}
|
|
(get-in ego [:right :crawl-stand]) {:origin-x 32}
|
|
(get-in ego [:right :axe]) {:origin-x 17}
|
|
(get-in ego [:right :axe-wood]) {:origin-x 17}
|
|
(get-in ego [:left :love]) {:origin-x 41}
|
|
(get-in ego [:left :suspended]) {:origin-x 0 :origin-y 0}
|
|
(get-in ego [:right :suspended]) {:origin-x 0 :origin-y 0}
|
|
(get-in ego [:left :suspended-talk]) {:origin-x 0 :origin-y 0}
|
|
(get-in ego [:right :suspended-talk]) {:origin-x 0 :origin-y 0}
|
|
:default {:origin-x 9}})]
|
|
(actions/start-animation screen
|
|
(merge (animation->texture screen (:stand (:right ego))) ego)
|
|
:stand)))
|
|
|
|
(defn start-script-if-necessary [screen entities key]
|
|
(let [{{:keys [script-running? script-chan]} key} entities]
|
|
(if script-running?
|
|
entities
|
|
(let [next-script (poll! script-chan)]
|
|
(if next-script
|
|
(do
|
|
(next-script entities)
|
|
(log/info "starting script")
|
|
|
|
(assoc-in entities [key :script-running?] true))
|
|
entities)))))
|
|
|
|
(defn update-from-script [screen entities key]
|
|
(let [{{:keys [current started? channel script-chan script-running?]} key} 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
|
|
(update-in terminated [key] assoc :current nil :started? false)
|
|
key))
|
|
(assoc-in entities [key :started?] true)))
|
|
(let [current (poll! channel)]
|
|
|
|
(-> entities
|
|
(assoc-in [key :started?] false)
|
|
(assoc-in [key :last-skip-type] (if current
|
|
(actions/skip-type current screen entities)
|
|
(get-in entities [key :last-skip-type])))
|
|
(assoc-in [key :current] current))))))
|
|
|
|
|
|
(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 [{:keys [total-time] :as screen} {{:keys [override last depressed? time-changed] :or {time-changed 0}} :cursor :as entities}]
|
|
(let [new-current (or override (get-selected-inventory-item) :main)
|
|
time-changed (double time-changed)
|
|
total-time (double total-time)]
|
|
(cond
|
|
(not= 0.0 (get-in entities [:fade :opacity]))
|
|
entities
|
|
|
|
(< (unchecked-subtract total-time time-changed) 0.15)
|
|
entities
|
|
|
|
(= [new-current depressed?] last)
|
|
entities
|
|
|
|
:else
|
|
(do
|
|
(graphics! :set-cursor (utils/cursor "cursor.png"
|
|
(utils/translate-depressed (or (:cursor new-current) new-current)
|
|
depressed?)))
|
|
(update-in entities [:cursor ] assoc
|
|
:last [new-current depressed?]
|
|
:time-changed total-time
|
|
:offset (utils/+cursor-hotspots+ (or (:cursor new-current) new-current) [0 0]))))))
|
|
|
|
|
|
(defn get-looped-animation-point ^double [^Animation animation ^double total-time]
|
|
(let [t (double total-time)]
|
|
(rem t (animation! animation :get-animation-duration))))
|
|
|
|
(defn animate [{:keys [anim anim-loop? anim-merges anim-start] :or {anim-loop? true anim-start 0} :as entity} {:keys [delta-time total-time] :or {delta-time 0} :as screen}]
|
|
(let [delta-time (double delta-time)
|
|
total-time (double total-time)
|
|
anim-start (double anim-start)
|
|
animated-time (unchecked-subtract total-time anim-start)
|
|
last-animated-time (unchecked-subtract animated-time delta-time)
|
|
current-frame-index (animation! ^Animation anim :get-key-frame-index
|
|
(if anim-loop?
|
|
(get-looped-animation-point anim animated-time)
|
|
animated-time))
|
|
|
|
previous-frame-index (animation! ^Animation anim :get-key-frame-index
|
|
(if anim-loop?
|
|
(get-looped-animation-point anim last-animated-time)
|
|
last-animated-time))]
|
|
(if (= current-frame-index (:current-frame-index entity) (:previous-frame-index entity))
|
|
entity
|
|
(merge (assoc entity
|
|
:object (.getKeyFrame ^Animation anim (- total-time anim-start) anim-loop?)
|
|
:current-frame-index current-frame-index
|
|
:previous-frame-index previous-frame-index
|
|
:origin-x (or (-> entity :anim-origins (get anim) (nth 0))
|
|
(:base-origin-x entity)
|
|
(:origin-x entity))
|
|
:origin-y (or (-> entity :anim-origins (get anim) (nth 1))
|
|
(:base-origin-y entity)
|
|
(:origin-y entity)))
|
|
(or (-> entity :anim-merges (get anim))
|
|
(-> 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 [selected-save]
|
|
(if selected-save
|
|
(assoc (:state selected-save) :active? true)
|
|
{:object nil
|
|
:active? true
|
|
:last-room :dream
|
|
:time :intro
|
|
: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-music (get-in entities [:musics (actions/get-music (get-in entities [:room :music]) (get-in entities [:state :time]))]))
|
|
(-> entities
|
|
(assoc
|
|
: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)
|
|
%)
|
|
%))
|
|
: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})
|
|
(assoc-in [:fade :opacity] 1.0)))
|
|
entities))
|
|
|
|
(defn play-sound-if-necessary [screen entities target {:keys [previous-frame-index current-frame-index anim-sound-frames anim x y] :as e :or {anim-sound-frames {}}}]
|
|
|
|
|
|
|
|
(if (and (not= previous-frame-index current-frame-index)
|
|
(anim-sound-frames anim))
|
|
(if-let [[snd vol-scale pitch] (get-in anim-sound-frames [anim current-frame-index])]
|
|
(let [snd (if (fn? snd)
|
|
(snd entities)
|
|
snd)
|
|
vol-scale (if (fn? vol-scale)
|
|
vol-scale
|
|
(utils/sourced-volume-fn target vol-scale [x y]))]
|
|
(utils/play-sound! screen entities
|
|
(or (snd e) snd)
|
|
vol-scale
|
|
(utils/get-sound-pan x)
|
|
:once
|
|
pitch))
|
|
entities)
|
|
entities))
|
|
|
|
(defn play-key-sounds [screen entities]
|
|
(if (= (get-in entities [:fade :opacity]) 0.0)
|
|
(loop [entities entities
|
|
[[target e] & rest] (seq (get-in entities [:room :entities]))]
|
|
(if e
|
|
(recur (play-sound-if-necessary screen entities target e) rest)
|
|
entities))
|
|
entities))
|
|
|
|
(defn update-current-sound-vols! [entities]
|
|
(loop [entities entities
|
|
[{:keys [id sound volume-fn]} & rest] (get-in entities [:current-sounds :value])]
|
|
(if id
|
|
(do
|
|
(sound! sound :set-volume id (utils/scale-vol-from-fade entities (utils/current-sound-volume (volume-fn entities))))
|
|
(recur entities rest))
|
|
entities)))
|
|
|
|
(defn remove-ended-sounds [screen entities]
|
|
(update-in entities [:current-sounds :value]
|
|
(fn [sounds]
|
|
(filter #(or (= :loop (:type %))
|
|
(> ^double (:ends-at %) ^double (:total-time screen)))
|
|
sounds))))
|
|
|
|
(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 ^ShaderProgram shader] :as screen} {:keys [parallax ^float multiply-amount ^float hue-amount] :as e :or {parallax 1.0}}]
|
|
|
|
(let [tmp (Vector3.)
|
|
tmp2 (Vector3.)
|
|
parallax-view (Matrix4.)
|
|
parallax-combined (Matrix4.)
|
|
p (float parallax)]
|
|
(.update camera)
|
|
|
|
(.set tmp (.position camera))
|
|
(set! (.x tmp) (float (* (.x tmp) p)))
|
|
(set! (.y tmp) (float (* (.y tmp) p)))
|
|
(.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)]
|
|
|
|
|
|
(.setProjectionMatrix batch parallax-combined)
|
|
(.setShader batch shader)
|
|
(when shader
|
|
(.setUniformf shader "multiply_amount" (float (or multiply-amount 1.0)))
|
|
(.setUniformf shader "hue_amount" (float (or hue-amount 1.0))))
|
|
|
|
(.setColor batch (color (:r e 1.0) (:g e 1.0) (:b e 1.0) (:opacity e 1.0)))
|
|
|
|
|
|
(entities/draw! (assoc e :x (+ (/ ^double (:x e) (.zoom camera))
|
|
(- (* 320 p 0.5)
|
|
(/ 160 (.zoom camera)) ))
|
|
:y (+ (/ ^double (:y e) (.zoom camera))
|
|
(- (* 240 p 0.5)
|
|
(/ 120 (.zoom camera))))) screen batch)
|
|
(.setColor batch (color 1 1 1 1))
|
|
)))
|
|
|
|
(def nighttime-times #{:night :sunrise})
|
|
(defn get-rendered [entities {:keys [time ^double y ^double offset-y night-profile] :or {night-profile :default} :as e}]
|
|
(as-> e e
|
|
(if (and (not= time (-> entities :state :time))
|
|
(nighttime-times (-> entities :state :time)))
|
|
(-> e
|
|
(merge (-> entities :time-profiles night-profile))
|
|
(assoc :time (-> entities :state :time)))
|
|
e)
|
|
#_(if offset-y
|
|
(assoc e :y (+ y offset-y))
|
|
e)))
|
|
|
|
(defn mouse-moved [screen entities {:keys [input-x input-y] :as options}]
|
|
(if utils/mobile?
|
|
(-> entities
|
|
(assoc-in [:cursor :last-pos] [0 0])
|
|
(assoc-in [:cursor :last] [:main nil])
|
|
(assoc-in [:cursor :override] nil)
|
|
(assoc-in [:cursor :down-target] nil)
|
|
(assoc-in [:label :text] ""))
|
|
(utils/update-override screen (assoc-in entities [:cursor :last-pos] [input-x input-y]) options)))
|
|
|
|
(defn grab-layers [entities]
|
|
(update-in entities [:room]
|
|
(fn [{:keys [layers current-layers] :as room}]
|
|
(cond current-layers
|
|
room
|
|
|
|
(map? layers)
|
|
(assoc room :current-layers (map (partial get-rendered entities) ((get-in entities [:state :time]) layers)))
|
|
|
|
:else
|
|
(assoc room :current-layers (map (partial get-rendered entities) layers))
|
|
))))
|
|
|
|
(defn add-georgia-to-all-rooms [screen rooms]
|
|
(let [georgia-talk (utils/make-anim "ego/georgia.png" [30 30] 0.15 [0 1 0 1 0 0 1 0 1 2])
|
|
georgia-stand (utils/make-anim "ego/georgia.png" [30 30] 0.3 [0 0 0 0 0 0 0 2 0 0 0 0 2])
|
|
georgia-love (utils/make-anim "ego/in-love.png" [30 30] 0.1 [0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 16 17 18 17 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 5 6 7 8 9 10 11 12 13 14 14 14 15 15 15 14 14 14 14 14 14 14 14 15 15 15 15 15 14 14 14 14 15 15 15 15 15 15 14 14 14 14 14])
|
|
|
|
georgia-face (rooms/make-entity :georgia-face
|
|
(assoc (animation->texture screen georgia-stand)
|
|
:talk georgia-talk
|
|
:anim georgia-stand
|
|
:stand georgia-stand
|
|
:love georgia-love
|
|
:night-profile :none
|
|
:talk-color (Color/valueOf "ffabe0ff")
|
|
:anim-start 0
|
|
:x 100 :y 100 :baseline 242 :origin-x 15 :origin-y 15
|
|
:opacity 0.0))
|
|
georgia-cloud (assoc (particle-effect "particles/cloud-georgia") :x 100 :y 100 :baseline 241 :opacity 0.0)]
|
|
(reduce (fn [rooms room-key]
|
|
(update-in rooms [room-key :entities]
|
|
assoc
|
|
:georgia-face georgia-face
|
|
:georgia-cloud georgia-cloud))
|
|
rooms
|
|
(keys rooms))))
|
|
|
|
(defn remove-cam-tweens [entities]
|
|
(update-in entities [:tweens] dissoc :cam-x :cam-y :cam-zoom))
|
|
|
|
|
|
(defscreen scene
|
|
:on-timer
|
|
(fn [screen entities options]
|
|
(when-let [timer-fn (get-in entities [:room :timers (:id screen) 2])]
|
|
(timer-fn screen entities)))
|
|
|
|
:on-show
|
|
(fn [screen entities options]
|
|
(log/info "Initializing scene.")
|
|
(let [{cam :camera :as screen} (utils/setup-viewport screen 320 240)
|
|
screen (assoc screen :total-time 0)]
|
|
(set! (. cam zoom) utils/min-zoom)
|
|
(let [shader (ShaderProgram. ^String v-shader ^String pix-shader)
|
|
_ (log/info "shader log:" (.getLog shader))
|
|
state (get-state @utils/selected-save)
|
|
start-pos [(:x state) (:y state)]
|
|
has-start-pos? (:x state)
|
|
|
|
_ (update! screen :shader shader)
|
|
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)
|
|
:held (rooms.held/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)
|
|
:ending (rooms.ending/make screen)
|
|
:castle-gate (rooms.castle-gate/make screen)
|
|
:outside-jail (rooms.outside-jail/make screen)
|
|
:outside-castle (rooms.outside-castle/make screen)}
|
|
rooms (add-georgia-to-all-rooms screen rooms)
|
|
entities {:rooms rooms
|
|
:step-particles (assoc (particle-effect "particles/step") :x 100 :y 100 :baseline 241)
|
|
:cam {:zoom utils/min-zoom
|
|
:ideal-x 160
|
|
:ideal-y 120
|
|
:x 160
|
|
:y 120
|
|
:paused? false
|
|
:object nil}
|
|
|
|
:current-sounds {:object nil
|
|
:value []}
|
|
:action-icon {}
|
|
:musics {:object nil
|
|
:inside-antique (utils/make-music "music/inside-antique.ogg")
|
|
:town-1 (utils/make-music "music/town-music-1.ogg")
|
|
:town-2 (utils/make-music "music/town-music-2.ogg")
|
|
:love (utils/make-music "music/love.ogg")
|
|
:inside-fangald (utils/make-music "music/inside-fangald.ogg")
|
|
:fight (utils/make-music "music/megaboss.mp3")
|
|
:pull-sword (utils/make-music "music/pull-sword.ogg")
|
|
:night (utils/make-music "music/night.ogg")
|
|
:dream (utils/make-music "dream/music.ogg")
|
|
:secret-hideout (utils/make-music "music/secret-hideout.ogg")
|
|
:wind (utils/make-music "music/wind.ogg")}
|
|
:state state
|
|
:time-profiles {:object nil
|
|
:default utils/default-night-merge
|
|
:sprite utils/default-night-merge-sprite
|
|
:none {}}
|
|
|
|
:closing? {:object nil
|
|
:value false}
|
|
:sounds {:blink (utils/load-sound "ego/blink2.ogg")
|
|
:pickup (utils/load-sound "pickup.ogg")
|
|
:disappear (utils/load-sound "inside-house/disappear.ogg")
|
|
:grow-sound (utils/load-sound "ego/potion.ogg")
|
|
:object nil}
|
|
:fade {:object nil
|
|
:opacity 0.0}
|
|
:white-fade (assoc (utils/get-texture "white.png")
|
|
:scale-x 30
|
|
:scale-y 30
|
|
:baseline 9500
|
|
:opacity 0.0
|
|
:origin-x 0
|
|
:origin-y 0
|
|
:x -20
|
|
:y -20)
|
|
:fg-actions {:object nil
|
|
:channel (chan)
|
|
:current nil
|
|
:script-running? false
|
|
:started? false
|
|
:script-chan (chan (dropping-buffer 1))}
|
|
:bg-actions {:object nil
|
|
:channel (chan)
|
|
:current nil
|
|
:script-running? false
|
|
:started? false
|
|
:script-chan (chan (dropping-buffer 1))}
|
|
:volume {:object nil
|
|
:value 0.0}
|
|
:music-override {:object nil
|
|
:value nil}
|
|
:cursor {:id "cursor"
|
|
:last nil
|
|
:override :hourglass
|
|
:last-pos [0 0]
|
|
:offset [0 0 ]
|
|
:down-target nil}
|
|
|
|
:all-items (assoc items/items :object nil)
|
|
:started? {:value false
|
|
:object nil}
|
|
:room (as-> (get rooms (:last-room state)) room
|
|
(assoc-in room [:entities :ego] (get-ego screen (if has-start-pos?
|
|
start-pos
|
|
(:start-pos room))
|
|
((:scale-fn room)
|
|
(if has-start-pos?
|
|
start-pos
|
|
(:start-pos room))))))}]
|
|
|
|
(doseq [[k [start time fn]] (get-in entities [:room :timers])]
|
|
(add-timer! screen k start time))
|
|
|
|
(log/info "[done] Initializing scene.")
|
|
|
|
(if-let [apply-state (get-in entities [:room :apply-state])]
|
|
(apply-state screen entities)
|
|
entities))))
|
|
|
|
:on-resume (fn [screen {{:keys [current override last active was-active]} :cursor :as entities} options]
|
|
(let [current (or override (get-selected-inventory-item) :main)
|
|
image-path "cursor.png"]
|
|
(graphics! :set-cursor (utils/cursor image-path (or (:cursor current) current))))
|
|
(doseq [[k [start time fn]] (get-in entities [:room :timers])]
|
|
(add-timer! screen k start time)))
|
|
|
|
|
|
:on-key-up
|
|
(fn [screen entities options]
|
|
(when (= (key-code :escape) (:key options))
|
|
(utils/toggle-fullscreen!))
|
|
nil)
|
|
|
|
:on-pan
|
|
(fn [screen entities {:keys [input-x input-y delta-x delta-y]}]
|
|
(when (get-in entities [:state :active?])
|
|
(let [ideal-x (+ (get-in entities [:cam :x]) (- (/ delta-x 4)))
|
|
ideal-y (+ (get-in entities [:cam :y]) (/ delta-y 4))]
|
|
(-> entities
|
|
(remove-cam-tweens)
|
|
(assoc-in [:cursor :last-pos] [0 0])
|
|
(assoc-in [:cam :ideal-x] ideal-x)
|
|
(assoc-in [:cam :ideal-y] ideal-y)
|
|
(assoc-in [:cam :x] (utils/bound-to-camera ideal-x 320 (get-in entities [:cam :zoom])) )
|
|
(assoc-in [:cam :y] (utils/bound-to-camera ideal-y 240 (get-in entities [:cam :zoom])) )))))
|
|
|
|
:pinch-stop
|
|
(fn [screen entities options]
|
|
(when (get-in entities [:state :active?])
|
|
(-> entities
|
|
(remove-cam-tweens)
|
|
(update-in [:cam] dissoc :start-zoom))))
|
|
|
|
:on-pinch
|
|
(fn [screen entities {:keys [initial-pointer-1 initial-pointer-2]}]
|
|
(when (get-in entities [:state :active?])
|
|
(let [[pointer-1-x pointer-1-y] (utils/unproject screen nil [(.x initial-pointer-1) (.y initial-pointer-1)])
|
|
[pointer-2-x pointer-2-y] (utils/unproject screen nil [(.x initial-pointer-2) (.y initial-pointer-2)])]
|
|
(-> entities
|
|
(remove-cam-tweens)
|
|
(assoc-in [:cursor :last-pos] [0 0])
|
|
(assoc-in [:cam :ideal-x] (* 0.5 (+ pointer-1-x pointer-2-x)))
|
|
(assoc-in [:cam :ideal-y] (* 0.5 (+ pointer-1-y pointer-2-y)))))))
|
|
|
|
:on-zoom
|
|
(fn [{:keys [^OrthographicCamera camera ^FitViewport viewport ^Stage renderer] :as screen} entities {:keys [initial-distance distance]}]
|
|
(when (get-in entities [:state :active?])
|
|
(let [start-zoom (get-in entities [:cam :start-zoom])
|
|
zoom (get-in entities [:cam :zoom])
|
|
entities (as-> entities entities
|
|
(if (not start-zoom)
|
|
(assoc-in entities [:cam :start-zoom] zoom)
|
|
entities)
|
|
(remove-cam-tweens entities)
|
|
(assoc-in entities [:cam :zoom] (max utils/max-zoom (min utils/min-zoom (* (or start-zoom zoom) (/ initial-distance distance)))))
|
|
(assoc-in entities [:cam :x] (utils/bound-to-camera (get-in entities [:cam :ideal-x]) 320 (get-in entities [:cam :zoom])) )
|
|
(assoc-in entities [:cam :y] (utils/bound-to-camera (get-in entities [:cam :ideal-y]) 240 (get-in entities [:cam :zoom])) ))]
|
|
entities
|
|
)))
|
|
|
|
#_#_:on-scrolled
|
|
(fn [{:keys [^OrthographicCamera camera ^FitViewport viewport ^Stage renderer] :as screen} entities options]
|
|
|
|
(update-in entities [:cam :zoom] #(* % (+ 1 (/ (double (:amount options)) 100.0 )))))
|
|
|
|
:on-render
|
|
(fn [{:keys [^OrthographicCamera camera ^FitViewport viewport ^Stage renderer] :as screen} {{:keys [last-pos ] [cursor-offset-x cursor-offset-y] :offset} :cursor :keys [tweens] :as entities} options]
|
|
(steam/update)
|
|
(.apply viewport)
|
|
|
|
(if (get-in entities [:closing? :value])
|
|
|
|
(let [entities (utils/apply-tweens screen entities tweens)
|
|
entities (update-current-sound-vols! entities)
|
|
entities (remove-ended-sounds screen entities)
|
|
get-rendered (partial get-rendered entities)
|
|
entities (loop [entities entities
|
|
[[k e] & rest] (seq (get-in entities [:room :entities]))]
|
|
(if k
|
|
(recur (update-in entities [:room :entities k] get-rendered) rest)
|
|
entities))
|
|
entities (grab-layers entities)
|
|
layers (get-in entities [:room :current-layers])
|
|
all-entities (concat layers (vals (get-in entities [:room :entities])))]
|
|
(screen! fade-screen :update-fade {:opacity (get-in entities [:fade :opacity])})
|
|
(doseq [m (vals (get-in entities [:musics]))]
|
|
(when m
|
|
(music! m :set-volume (utils/current-music-volume (get-in entities [:volume :value])))))
|
|
|
|
(clear!)
|
|
(doseq [e (sort-by :baseline all-entities)]
|
|
(if (:parallax e)
|
|
(render-parallax screen e)
|
|
(render! screen [e])))
|
|
entities)
|
|
(let [entities (fade-in-first-time-if-necessary screen entities)
|
|
entities (utils/apply-tweens screen entities tweens)
|
|
entities (update-cursor screen entities)
|
|
entities (start-script-if-necessary screen entities :fg-actions)
|
|
entities (update-from-script screen entities :fg-actions)
|
|
entities (start-script-if-necessary screen entities :bg-actions)
|
|
entities (update-from-script screen entities :bg-actions)
|
|
entities (update-from-room screen entities)
|
|
entities (update-from-hotspots screen entities)
|
|
[last-pos-x last-pos-y] (utils/unproject screen nil last-pos)
|
|
last-pos-x (double last-pos-x)
|
|
last-pos-y (double last-pos-y)
|
|
#_#_entities (if (and (@utils/settings :camera-man? true)
|
|
(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
|
|
(+ ^double (get-in entities [:cam :x] 0)
|
|
(- 10 ^double (rand-int 20)))
|
|
(+ ^double (get-in entities [:cam :y] 0)
|
|
(- 10 ^double (rand-int 20)))
|
|
(constantly (get-in entities [:room :entities :ego :scale-x]))
|
|
tween/ease-in-out-quadratic
|
|
5.0))
|
|
entities)
|
|
|
|
|
|
entities (grab-layers entities)
|
|
update-room (fn [{:keys [anim update-fn] :as e}]
|
|
(let [e (if (:anim e)
|
|
(animate e screen)
|
|
e)
|
|
|
|
e (if update-fn
|
|
(update-fn screen (get-in entities [:room :entities]) e)
|
|
e)
|
|
e (get-rendered entities e)]
|
|
e))
|
|
entities (loop [room (transient (get-in entities [:room :entities]))
|
|
[[k e] & rest] (doall (seq (get-in entities [:room :entities])))]
|
|
(if k
|
|
(recur (assoc! room k (update-room e))
|
|
rest)
|
|
(assoc-in entities [:room :entities] (persistent! room))))
|
|
layers (get-in entities [:room :current-layers])
|
|
all-entities (concat layers (vals (get-in entities [:room :entities])))]
|
|
|
|
(screen! tooltip-screen :on-hover-start {:hover-text (get-in entities [:label :text])
|
|
:scene-viewport (:viewport screen)
|
|
:cursor (:cursor entities)
|
|
:x (unchecked-subtract last-pos-x
|
|
cursor-offset-x)
|
|
:y (unchecked-add (unchecked-subtract last-pos-y 16 )
|
|
cursor-offset-y)})
|
|
|
|
(clear!)
|
|
(screen! talking-screen :on-update-camera { :scene-viewport (:viewport screen) :scene-camera (:camera screen)})
|
|
(screen! fade-screen :update-fade { :opacity (get-in entities [:fade :opacity])})
|
|
(when true #_(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 (if utils/mobile?
|
|
(utils/update-override screen entities options)
|
|
(utils/update-override screen entities options))
|
|
entities (play-key-sounds screen entities)
|
|
entities (update-current-sound-vols! entities)
|
|
entities (remove-ended-sounds screen 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 (doall (sort-by :baseline all-entities))]
|
|
(if (:parallax e)
|
|
(render-parallax screen e)
|
|
(render! screen [e])))
|
|
|
|
entities))))
|
|
|
|
:on-resize (fn [{:keys [^FitViewport viewport]} entities {:keys [width height]}]
|
|
(.update viewport width height true))
|
|
|
|
:on-hide (fn [screen entities options]
|
|
(doseq [snd (->> (get-in entities [:musics])
|
|
vals
|
|
(filter identity))]
|
|
(utils/stop-music snd)))
|
|
|
|
#_#_:on-mouse-moved
|
|
mouse-moved
|
|
|
|
:on-touch-dragged
|
|
mouse-moved
|
|
|
|
:on-touch-down
|
|
(fn [{:keys [^FitViewport viewport] :as screen} entities {:keys [input-x input-y] :as options}]
|
|
|
|
(when (utils/contains-point? (.getScreenX viewport) (.getScreenY viewport)
|
|
(.getScreenWidth viewport) (.getScreenHeight viewport)
|
|
input-x input-y)
|
|
; TODO: override cursor when started in black
|
|
(when (and (= (button-code :left)
|
|
(:button options))
|
|
(get-in entities [:state :active?])
|
|
(not (get-in entities [:state :hud-active?]))
|
|
(= 0.0 (get-in entities [:fade :opacity])))
|
|
(let [[x y] (utils/unproject screen options)
|
|
entities (utils/update-override screen (assoc-in entities [:cursor :last-pos] [input-x input-y]) options)
|
|
interaction (get-interaction entities x y)
|
|
interacting-entity (get-interacting-entity entities x y)]
|
|
(-> entities
|
|
(assoc-in [:cursor :depressed?] true)
|
|
(assoc-in [:cursor :down-target] (or (:id interacting-entity ) (:id interaction) nil)))))))
|
|
|
|
:on-touch-up (fn [screen entities options]
|
|
(when-not utils/mobile?
|
|
(handle-touch-up screen entities options)))
|
|
|
|
:on-tap (fn [screen entities options]
|
|
(when utils/mobile?
|
|
(handle-touch-up screen entities options)))
|
|
|
|
:on-deactivate (fn [screen entities options]
|
|
(assoc-in entities [:state :active?] false))
|
|
|
|
:on-reactivate (fn [screen entities {:keys [came-from-inventory?]}]
|
|
(-> entities
|
|
(assoc-in [:state :active?] true)
|
|
(assoc-in [:cursor :came-from-inventory?] came-from-inventory?)))
|
|
|
|
:on-end-safe (fn [screen entities options]
|
|
((actions/get-script entities
|
|
(actions/play-animation entities :ego :end-squat)) entities)
|
|
(-> entities
|
|
(assoc-in [:state :active?] true)
|
|
(assoc-in [:cursor :override] nil)))
|
|
|
|
:on-open-inventory (fn [screen entities options]
|
|
(open-inventory screen entities))
|
|
|
|
:on-click-inventory (fn [screen entities options]
|
|
(click-inventory screen entities))
|
|
|
|
:on-save (fn [screen entities options]
|
|
(when-not (get-in entities [:fg-actions :script-running?])
|
|
(let [date (.format (java.text.SimpleDateFormat. "MM/dd/YY") (java.util.Date.))
|
|
save-name (str (-> entities :room :name) " - " date)]
|
|
(utils/save entities
|
|
(str (.getTime (java.util.Date.)))
|
|
save-name
|
|
date)
|
|
(screen! toast-screen :on-toast { :message (str "Saved \"" save-name "\"")}))))
|
|
|
|
:on-menu (fn [{:keys [viewport] :as screen} entities options]
|
|
(when-not (or (get-in entities [:tweens :fade-out])
|
|
(get-in entities [:tweens :fade-in]))
|
|
|
|
(graphics! :set-cursor (utils/cursor "cursor.png" :hourglass))
|
|
(-> entities
|
|
(assoc-in [:closing? :value] true)
|
|
(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
|
|
(utils/stop-all-sounds! %)
|
|
(asset-manager! @(resolve 'advent.core/am) :clear)
|
|
(set-screen! @(resolve 'advent.core/advent) @(resolve 'advent.screens.title/title-screen))
|
|
%))))))
|
|
|
|
:on-start-script (fn [screen entities {:keys [script]}]
|
|
(script entities)
|
|
entities)
|
|
:hud-active? (fn [screen entities {:keys [hud-active?]}]
|
|
(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 (* utils/ui-scale (if up? 1.0 1.1))
|
|
scale-to (* utils/ui-scale (if up? 1.1 1.0))
|
|
opacity-from (* utils/ui-scale (if up? 0.8 1.0))
|
|
opacity-to (* utils/ui-scale (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)))
|
|
|
|
(defn get-selected-inventory-item []
|
|
(let [{{:keys [state state-data]} :inv-fsm} (-> hud :entities deref)]
|
|
(and (= state :selected)
|
|
state-data)))
|
|
|
|
(defscreen demo
|
|
:on-show
|
|
(fn [screen entities options]
|
|
(let [screen (assoc screen :total-time 0)]
|
|
(utils/setup-viewport screen 640 480)
|
|
{:label (assoc (label "Demo version - DO NOT COPY" (color :white) ) :y 460 :x 5 :baseline 0 :opacity 0.5)}))
|
|
|
|
:on-render
|
|
(fn [{:keys [^FitViewport viewport] :as screen} entities options]
|
|
(.apply viewport)
|
|
(render! screen [(:label entities)])
|
|
entities)
|
|
|
|
:on-resize
|
|
(fn [{:keys [^FitViewport viewport]} entities {:keys [width height]}]
|
|
(.update viewport width height true))
|
|
|
|
)
|
|
(defn hud-interactable? []
|
|
(let [scene-entities (-> scene :entities deref)]
|
|
(and (not (get-in scene-entities [:fg-actions :script-running?]))
|
|
(get-in scene-entities [:state :active?])
|
|
(= 0.0 (get-in scene-entities [:fade :opacity])))))
|
|
|
|
(defmulti transition-hud (fn [screen entities new-state state-data]
|
|
|
|
[(get-in entities [:inv-fsm :state]) new-state]))
|
|
|
|
(defmethod transition-hud :default [screen entities new-state state-data] entities)
|
|
|
|
(defprotocol ITransition
|
|
(start-transition [this screen entities])
|
|
(transition-done? [this screen entities]))
|
|
|
|
(defn accept-state [entities state state-data transitions]
|
|
(-> entities
|
|
(assoc-in [:inv-fsm :state] state)
|
|
(assoc-in [:inv-fsm :state-data] state-data)
|
|
(assoc-in [:inv-fsm :transition-steps] transitions)))
|
|
|
|
(defn appear-transition [item hide-or-show in-or-out]
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(let [fade-tween (if (= :hide hide-or-show)
|
|
(tween/tween :appear-item screen [:selected-item :opacity] 1.0 0.0 0.5 :ease tween/ease-linear)
|
|
(tween/tween :appear-item screen [:selected-item :opacity] 0.0 1.0 0.5 :ease tween/ease-linear))
|
|
move-tween (condp = in-or-out
|
|
:far-out
|
|
(tween/tween :appear-item-y screen [:selected-item :y] 35 40 0.5 :ease tween/ease-linear)
|
|
:out
|
|
(tween/tween :appear-item-y screen [:selected-item :y] 30 35 0.5 :ease tween/ease-linear)
|
|
|
|
:in
|
|
(tween/tween :appear-item-y screen [:selected-item :y] 35 30 0.5 :ease tween/ease-linear)
|
|
|
|
:none
|
|
(tween/tween :appear-item-y screen [:selected-item :y] 35 35 0.5 :ease tween/ease-linear))]
|
|
(-> entities
|
|
(assoc :selected-item
|
|
(assoc (texture (aget (get-in entities [:all-items]) 0 (.indexOf utils/+all-cursors+ (:cursor item))))
|
|
:x 300 :y (condp = in-or-out
|
|
:in
|
|
35
|
|
:out
|
|
30
|
|
:none
|
|
35
|
|
:far-out
|
|
35) :baseline 9000 :opacity (if (= :hide hide-or-show) 1.0 0.0)
|
|
:item item))
|
|
(assoc-in [:tweens :appear-item] fade-tween)
|
|
(assoc-in [:tweens :appear-item-y] move-tween))))
|
|
(transition-done? [this screen entities]
|
|
(not (get-in entities [:tweens :appear-item])))))
|
|
|
|
(defmethod transition-hud [:none :open]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] #(actions/start-animation screen % :open)))
|
|
(transition-done? [this screen entities]
|
|
(animation! (get-in entities [:inventory :anim])
|
|
:is-animation-finished
|
|
(- ^double (:total-time screen) ^double (get-in entities [:inventory :anim-start])))))
|
|
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] #(actions/start-animation screen % :opened)))
|
|
(transition-done? [this screen entities]
|
|
true))
|
|
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(screen! scene :on-open-inventory {})
|
|
entities)
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:open :none]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] #(actions/start-animation screen % :closing)))
|
|
(transition-done? [this screen entities]
|
|
(animation! (get-in entities [:inventory :anim])
|
|
:is-animation-finished
|
|
(- ^double (:total-time screen) ^double (get-in entities [:inventory :anim-start])))))
|
|
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] #(actions/start-animation screen % :default)))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:open :selected]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(appear-transition state-data :show :out)]))
|
|
|
|
(defmethod transition-hud [:selected :none]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :closing))))
|
|
(transition-done? [this screen entities] true))
|
|
(appear-transition (or state-data (get-in entities [:inv-fsm :state-data])) :hide :in)
|
|
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(-> entities
|
|
(update-in [:inventory] (fn [i] (actions/start-animation screen i :default)))
|
|
(dissoc :selected-item)))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:selected :remove]
|
|
[screen entities state state-data]
|
|
(let [current-item (get-in entities [:inv-fsm :state-data])
|
|
transitions (if (= state-data current-item )
|
|
[(appear-transition state-data :hide :far-out)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(-> entities
|
|
(dissoc :selected-item)))
|
|
(transition-done? [this screen entities]
|
|
true))]
|
|
[(appear-transition current-item :hide :in)
|
|
(appear-transition state-data :show :out)
|
|
(appear-transition state-data :hide :far-out)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(-> entities
|
|
(dissoc :selected-item)))
|
|
(transition-done? [this screen entities]
|
|
true))])]
|
|
(accept-state entities state state-data
|
|
transitions)))
|
|
|
|
(defmethod transition-hud [:remove :selected]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(appear-transition state-data :show :out)]))
|
|
|
|
(defmethod transition-hud [:none :remove]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :open))))
|
|
(transition-done? [this screen entities]
|
|
(animation! (get-in entities [:inventory :anim])
|
|
:is-animation-finished
|
|
(- ^double (:total-time screen) ^double (get-in entities [:inventory :anim-start])))))
|
|
|
|
(appear-transition state-data :show :out)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :closing))))
|
|
(transition-done? [this screen entities] true))
|
|
(appear-transition state-data :hide :far-out)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(dissoc entities :selected-item))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:remove :none]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :closing))))
|
|
(transition-done? [this screen entities]
|
|
(animation! (get-in entities [:inventory :anim])
|
|
:is-animation-finished
|
|
(- ^double (:total-time screen) ^double (get-in entities [:inventory :anim-start])))))
|
|
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(-> entities
|
|
(update-in [:inventory] (fn [i] (actions/start-animation screen i :default)))
|
|
(dissoc :selected-item)))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:none :acquire]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :open))))
|
|
(transition-done? [this screen entities]
|
|
(animation! (get-in entities [:inventory :anim])
|
|
:is-animation-finished
|
|
(- ^double (:total-time screen) ^double (get-in entities [:inventory :anim-start])))))
|
|
|
|
(appear-transition state-data :show :none)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(update-in entities [:inventory] (fn [i] (actions/start-animation screen i :closing))))
|
|
(transition-done? [this screen entities] true))
|
|
(appear-transition state-data :hide :in)
|
|
(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(dissoc entities :selected-item))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:acquire :none]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data [(reify ITransition
|
|
(start-transition [this screen entities]
|
|
(-> entities
|
|
(update-in [:inventory] (fn [i] (actions/start-animation screen i :default)))
|
|
(dissoc :selected-item)))
|
|
(transition-done? [this screen entities]
|
|
true))]))
|
|
|
|
(defmethod transition-hud [:selected :acquire]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(appear-transition (get-in entities [:inv-fsm :state-data]) :hide :none)
|
|
(appear-transition state-data :show :none)
|
|
(appear-transition state-data :hide :in)]))
|
|
|
|
(defmethod transition-hud [:acquire :selected]
|
|
[screen entities state state-data]
|
|
(accept-state entities state state-data
|
|
[(appear-transition state-data :show :out)]))
|
|
|
|
(defn fsm-busy? [entities]
|
|
(seq (get-in entities [:inv-fsm :transition-steps])))
|
|
|
|
(defn process-fsm [screen { {:keys [transition-steps current-transition] [[next-state next-state-data] & pending-states] :pending-states [next-transition & remaining-transitions] :transition-steps} :inv-fsm :as entities}]
|
|
(cond
|
|
(and current-transition (transition-done? current-transition screen entities))
|
|
(-> entities
|
|
(update-in [:inv-fsm ] dissoc :current-transition))
|
|
|
|
current-transition
|
|
nil ;; waiting
|
|
|
|
(fsm-busy? entities)
|
|
(-> (start-transition next-transition screen entities)
|
|
(assoc-in [:inv-fsm :current-transition] next-transition)
|
|
(assoc-in [:inv-fsm :transition-steps] remaining-transitions))
|
|
|
|
next-state
|
|
(-> (transition-hud screen entities next-state next-state-data)
|
|
(assoc-in [:inv-fsm :pending-states] (vec pending-states)))
|
|
|
|
:else
|
|
nil))
|
|
|
|
(defscreen hud
|
|
:on-show
|
|
(fn [screen entities options]
|
|
(let [screen (assoc screen :total-time 0)
|
|
screen (utils/setup-viewport screen 320 240)]
|
|
|
|
|
|
{:inv-fsm {:state :none
|
|
:state-data {}
|
|
:target nil
|
|
:target-data nil
|
|
:transition-steps []
|
|
:pending-states []}
|
|
:already-saved? false
|
|
|
|
:close (assoc (utils/get-texture "close.png")
|
|
:x (- 320 (* utils/ui-scale 16)) :y (- 240 16)
|
|
:width 16 :height 16
|
|
:baseline 9000
|
|
:opacity 0.8)
|
|
:save (assoc (utils/get-texture "save.png")
|
|
:x (- 320 (* 2.5 (* utils/ui-scale 16))) :y (- 240 16)
|
|
:width 16 :height 16
|
|
:baseline 9000
|
|
:opacity 0.8)
|
|
:inventory (assoc (utils/get-texture "inventory.png") :x (- 320 (* 21 utils/ui-scale)) :y (* 27 utils/ui-scale ) :baseline 9000
|
|
:origin-x 21 :origin-y 27
|
|
:open (doto (utils/make-anim-seq "open-inventory" [42 56] 0.055 (flatten [(range 6) 6 7 8 7 ]))
|
|
(animation! :set-play-mode (play-mode :normal)))
|
|
:anim (utils/make-anim "inventory.png" [42 56] 0.1 [0])
|
|
:anim-loop? false
|
|
:default (utils/make-anim "inventory.png" [42 56] 0.1 [0])
|
|
:opened (utils/make-anim-seq "open-inventory" [42 56] 0.1 [7])
|
|
:closing (doto (utils/make-anim-seq "open-inventory" [42 56] 0.055 [7 7 7 7 7 7 7 9 10 11 12 0])
|
|
(animation! :set-play-mode (play-mode :normal)))
|
|
:anim-start 0
|
|
:mouse-in? (zone/box 278 0 320 42)
|
|
:opacity 0.8)
|
|
:all-items (texture! (texture (pixmap "cursor.png")) :split 18 16)
|
|
#_#_:fps (->> (assoc (label "" (color :white) ) :x 5 :baseline 0 :opacity 0.1)
|
|
(utils/add-actor-to-stage screen))}))
|
|
|
|
:on-render
|
|
(fn [{:keys [^FitViewport viewport] :as screen} entities options]
|
|
(.apply viewport)
|
|
(let [entities (utils/apply-tweens screen entities (:tweens entities))
|
|
entities (update-in entities [:inventory] animate screen )
|
|
hud-interactable? (hud-interactable?)
|
|
entities (if hud-interactable?
|
|
(as-> entities entities
|
|
(update-in entities [:inventory] assoc :r 1.0 :g 1.0 :b 1.0 ))
|
|
(as-> entities entities
|
|
(update-in entities [:inventory] assoc :r 0.75 :g 0.75 :b 0.75)
|
|
(grow-hud screen entities :inventory false)))
|
|
entities (if (= :selected (get-in entities [:inv-fsm :state]))
|
|
(if hud-interactable?
|
|
(as-> entities entities
|
|
(update-in entities [:selected-item] assoc :r 1.0 :g 1.0 :b 1.0 ))
|
|
(as-> entities entities
|
|
(update-in entities [:selected-item] assoc :r 0.75 :g 0.75 :b 0.75)
|
|
(grow-hud screen entities :selected-item false)))
|
|
entities)
|
|
entities (if (and hud-interactable? (not (:already-saved? entities)))
|
|
(as-> entities entities
|
|
(update-in entities [:save] assoc :r 1.0 :g 1.0 :b 1.0 ))
|
|
(as-> entities entities
|
|
(update-in entities [:save] assoc :r 0.75 :g 0.75 :b 0.75)
|
|
(grow-hud screen entities :save false)))
|
|
|
|
entities (or (process-fsm screen entities) entities)]
|
|
#_(label! (:fps entities) :set-text (str (game :fps)))
|
|
|
|
|
|
|
|
(render! screen [ (if (and hud-interactable? (not (:already-saved? entities)))
|
|
(:save entities)
|
|
(assoc (:save entities) :opacity 0.5))
|
|
#_(:fps entities)
|
|
(if hud-interactable?
|
|
(:inventory entities)
|
|
(assoc (:inventory entities) :opacity 0.5))
|
|
(:selected-item entities)
|
|
(:close entities)])
|
|
entities))
|
|
|
|
:on-resize
|
|
(fn [{:keys [^FitViewport viewport]} entities {:keys [width height]}]
|
|
(.update viewport width height true))
|
|
|
|
:on-give-item
|
|
(fn [screen entities {:keys [item]}]
|
|
(-> entities
|
|
(update-in [:inv-fsm :pending-states] conj [:acquire item])
|
|
(update-in [:inv-fsm] (fn [{:keys [state state-data] :as fsm}]
|
|
(if (and (= state :selected) (= item state-data))
|
|
(update-in fsm [:pending-states] conj [:none state-data])
|
|
(update-in fsm [:pending-states] conj [:none state-data]))))))
|
|
|
|
:on-remove-item
|
|
(fn [screen entities {:keys [item]}]
|
|
(-> entities
|
|
(update-in [:inv-fsm :pending-states] conj [:remove item])
|
|
(update-in [:inv-fsm] (fn [{:keys [state state-data] :as fsm}]
|
|
(cond
|
|
(and (= state :selected) (= item state-data))
|
|
(update-in fsm [:pending-states] conj [:none state-data])
|
|
(= state :selected)
|
|
(update-in fsm [:pending-states] conj [state state-data])
|
|
:else
|
|
(update-in fsm [:pending-states] conj [:none state-data]))))))
|
|
|
|
:on-return-item
|
|
(fn [screen entities options]
|
|
(if (hud-interactable?)
|
|
(-> entities
|
|
(update-in [:inv-fsm :pending-states] conj [:none (get-in entities [:inv-fsm :state-data])]))))
|
|
|
|
|
|
:on-start-script
|
|
(fn [_ entities _]
|
|
(-> entities
|
|
(update-in [:inv-fsm :pending-states] conj [:none nil])
|
|
(assoc-in [:already-saved?] false)))
|
|
|
|
|
|
:on-reactivate
|
|
(fn [screen entities {:keys [script-started? item]}]
|
|
(let [selected-item? (and (:value item)
|
|
(:cursor item))]
|
|
(if (and (not script-started?) selected-item?)
|
|
(transition-hud screen entities :selected item)
|
|
(transition-hud screen entities :none nil))))
|
|
|
|
:on-touch-down
|
|
(fn [screen entities options]
|
|
(let [[x y] (utils/unproject screen options)
|
|
hovered-inventory? ((:mouse-in? (:inventory entities)) x y)
|
|
hovered-close? (utils/intersects? (:close entities) [x y])
|
|
hovered-save? (utils/intersects? (:save entities) [x y])]
|
|
(screen! scene :hud-active? { :hud-active? (or hovered-close? hovered-inventory? hovered-save?)})))
|
|
|
|
:on-mouse-moved
|
|
|
|
(fn [screen entities options]
|
|
(let [[x y] (utils/unproject screen options)
|
|
hovered-inventory? ((:mouse-in? (:inventory entities)) x y)
|
|
hovered-close? (utils/intersects? (:close entities) [x y])
|
|
hovered-save? (utils/intersects? (:save entities) [x y])]
|
|
(cond (and hovered-inventory? (hud-interactable?))
|
|
(as-> entities entities
|
|
(grow-hud screen entities :inventory true)
|
|
(if (:selected-item entities)
|
|
(grow-hud screen entities :selected-item true)
|
|
entities))
|
|
|
|
hovered-close?
|
|
(grow-hud screen entities :close true)
|
|
|
|
(and hovered-save? (hud-interactable?) (not (:already-saved? entities)))
|
|
(grow-hud screen entities :save true)
|
|
|
|
:else
|
|
(let [entities (update-in entities [:tweens] dissoc :inventory-grow-x :inventory-grow-y)
|
|
entities (grow-hud screen entities :inventory false)
|
|
entities (if (:selected-item entities)
|
|
(grow-hud screen entities :selected-item false)
|
|
entities)
|
|
entities (grow-hud screen entities :close false)
|
|
entities (grow-hud screen entities :save false)]
|
|
entities
|
|
))))
|
|
|
|
|
|
:on-touch-up
|
|
(fn [screen entities options]
|
|
(if (= (button-code :left) (:button options))
|
|
(let [[x y] (utils/unproject screen options)]
|
|
(cond
|
|
(not (hud-interactable?))
|
|
nil
|
|
|
|
|
|
((:mouse-in? (:inventory entities)) x y)
|
|
|
|
(if (= :selected (get-in entities [:inv-fsm :state]))
|
|
(update-in entities [:inv-fsm :pending-states] conj [:none (get-in entities [:inv-fsm :state-data])])
|
|
|
|
(do
|
|
(screen! scene :on-deactivate {})
|
|
(update-in entities [:inv-fsm :pending-states] conj [:open nil])))
|
|
|
|
(utils/intersects? (:close entities) [x y])
|
|
(screen! scene :on-menu {})
|
|
|
|
(and (not (:already-saved? entities)) (utils/intersects? (:save entities) [x y]) (hud-interactable?))
|
|
(do
|
|
(screen! scene :on-save {})
|
|
(assoc entities :already-saved? true))
|
|
|
|
:else
|
|
nil)))))
|