Files
gitea-docker/desktop/src-common/advent/screens/scene.clj
2015-09-15 09:35:31 -07:00

1305 lines
60 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.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]]
[advent.screens.inventory :refer [inventory-screen]]
[clojure.core.async :refer [put! <! <!! >! chan go thread take! alts!! dropping-buffer]])
(: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]
[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]))
(declare hud)
(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;
vec3 RGBToHSL(vec3 color)
{
vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part)
float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB
float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB
float delta = fmax - fmin; //Delta RGB value
hsl.z = (fmax + fmin) / 2.0; // Luminance
if (delta == 0.0)//This is a gray, no chroma...
{
hsl.x = 0.0;// Hue
hsl.y = 0.0;// Saturation
}
else //Chromatic data...
{
if (hsl.z < 0.5)
hsl.y = delta / (fmax + fmin); // Saturation
else
hsl.y = delta / (2.0 - fmax - fmin); // Saturation
float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;
if (color.r == fmax )
hsl.x = deltaB - deltaG; // Hue
else if (color.g == fmax)
hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
else if (color.b == fmax)
hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue
if (hsl.x < 0.0)
hsl.x += 1.0; // Hue
else if (hsl.x > 1.0)
hsl.x -= 1.0; // Hue
}
return hsl;
}
float HueToRGB(float f1, float f2, float hue)
{
if (hue < 0.0)
hue += 1.0;
else if (hue > 1.0)
hue -= 1.0;
float res;
if ((6.0 * hue) < 1.0)
res = f1 + (f2 - f1) * 6.0 * hue;
else if ((2.0 * hue) < 1.0)
res = f2;
else if ((3.0 * hue) < 2.0)
res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
else
res = f1;
return res;
}
vec3 HSLToRGB(vec3 hsl)
{
vec3 rgb;
if (hsl.y == 0.0)
rgb = vec3(hsl.z); // Luminance
else
{
float f2;
if (hsl.z < 0.5)
f2 = hsl.z * (1.0 + hsl.y);
else
f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);
float f1 = 2.0 * hsl.z - f2;
rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));
rgb.g = HueToRGB(f1, f2, hsl.x);
rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));
}
return rgb;
}
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));
}
}
// Color Mode keeps the brightness of the base color and applies both the hue and saturation of the blend color.
vec3 BlendColor(vec3 base, vec3 blend)
{
vec3 blendHSL = RGBToHSL(blend);
return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));
}
#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O))
void main()
{
vec3 multiplied = mix(texture2D(u_texture, v_texCoords).rgb, v_color.rgb * texture2D(u_texture, v_texCoords).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], texture2D(u_texture, v_texCoords).a * v_color.a);
}
")
;
(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 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 skip-action [screen entities]
(let [current-action (get-in entities [: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 [:actions :current] nil)
(assoc-in [:actions :started?] false))))
(= :end (actions/skip-type current-action screen entities))
(let [terminated-entities (actions/terminate current-action screen entities)]
(println "trying to end")
(do (put! (actions/get-channel current-action) :end)
(-> terminated-entities
(assoc-in [:actions :script-running?] false)
(assoc-in [:actions :current] nil)
(assoc-in [:actions :started?] false))))
:else
entities)))
(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-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)))]
interacting-entity))
(defn left-click [screen entities]
(let [[x y] (utils/unproject screen)
_ (println "clicked " x y)
interaction (get-interaction entities x y)
interacting-entity (get-interacting-entity entities x y)
current-action (get-in entities [:actions :current])
;; TODO - hacky way of resetting queue
entities (if (and current-action
(= (get-in entities [:cursor :down-target])
(or (:id interacting-entity) (:id interaction) nil)))
(skip-action screen entities)
entities)]
(when (and (not (get-in entities [:actions :script-running?]))
(= (get-in entities [:cursor :down-target])
(or (:id interacting-entity) (:id interaction) nil)))
((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))
(assoc-in entities [:cursor :down-target] nil)))
(defn get-ego-script [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 (= :held
(get-in @entities [:state :last-room]))
(common/do-win entities)
(get-in @entities [:room :entities :warden])
(do
(actions/talk entities :ego "I'll just take a sip!")
(sound! (utils/load-sound "ego/potion.ogg") :play (utils/current-sound-volume))
(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))
(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! (utils/load-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?"))
: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.")
: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 prove 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 sheey's milk in my flask.")
:flask-1-with-mushrooms
(common/one-liner "I've got some mushrooms in my flask.")
:balloon
(common/one-liner "My choicest baloon 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))))
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))))
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]]))
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]))
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" [18 36] 0.10 [0])
suspended-talk (utils/make-anim "ego/suspended.png" [18 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))
ego {:right {:walk walk-right
:stand stand-anim
:talk talk-anim
:squat squat-anim
: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
: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
}
:left {:walk (utils/flip walk-right)
:stand (utils/flip stand-anim)
:talk (utils/flip talk-anim)
: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)
: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)
}
:baseline (- 240 (last start-pos))
:facing :right
:night-profile :sprite
:origin-x 9
:origin-y 0
:scaled true
: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")
:sigh-sound (utils/load-sound "ego/sigh.ogg")
:breakglass-sound (utils/load-sound "ego/breakglass.ogg")
:idea-sound (utils/load-sound "ego/idea.ogg")
:blink (utils/load-sound "ego/blink2.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 [{entity-x :x entity-y :y ^TextureRegion 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))]
((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 [: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]}
(get-in ego [:left :idea]) {1 [:idea-sound 1.0]}
(get-in ego [:right :idea]) {1 [:idea-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 :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 [: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 {{:keys [script-running? script-chan]} :actions :as entities}]
(if script-running?
entities
(let [[next-script] (alts!! [script-chan] :default nil)]
(if next-script
(do
(next-script entities)
(println "starting script")
(assoc-in entities [:actions :script-running?] true))
entities))))
(defn update-from-script [screen {{:keys [current started? channel script-chan]} :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 :script-chan (get-in entities [:actions :script-chan]) :current nil :started? false :script-running? (get-in entities [:actions :script-running?]) :last-skip-type (get-in entities [:actions :last-skip-type])})))
(assoc-in entities [:actions :started?] true)))
(let [[current _] (alts!! [channel] :default nil)]
(assoc entities :actions {:script-chan (get-in entities [:actions :script-chan]) :channel channel :current current :started? false :script-running? (get-in entities [:actions :script-running?]) :last-skip-type (if current
(actions/skip-type current screen entities)
(get-in entities [:actions :last-skip-type]))}))))
(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 active was-active]} :cursor :as entities}]
(if (= 0.0 (get-in entities [:fade :opacity]))
(let [new-current (or override current)]
(when-not (and (= new-current
last)
(= active was-active))
(let [image-path (if active "cursor_light.png" "cursor.png")]
(input! :set-cursor-image (utils/cursor image-path (or (:cursor new-current) new-current)) 0 0)))
(update-in entities [:cursor ] assoc :last new-current
:was-active active))
entities))
(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 (animation! ^Animation (:anim entity) :get-key-frame-index (get-animation-point (:anim entity) (- (:total-time screen) (:anim-start entity))))
:previous-frame-index (animation! ^Animation (: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 (utils/has-save?)
(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])))
(when (get-in entities [:state :seen-intro?])
(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)
%)
%))
: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)
(* (or vol-scale 1.0))
(utils/clamp-volume))
(utils/proximity-volume entities [x y] :scale vol-scale))
pan (/ (- (:x e) 160 ) 160)]
(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 ^ShaderProgram shader] :as screen} {:keys [parallax ^float multiply-amount ^float hue-amount] :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)
(.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 (+ (/ (: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 get-rendered [entities e]
(merge e
(when (not= :day (get-in entities [:state :time]))
(get-in entities [:time-profiles (:night-profile e :default)]))))
(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]))
(defn mouse-moved [{:keys [input-x input-y viewport] :as screen} [entities]]
(utils/update-override screen (assoc-in entities [:cursor :last-pos] [input-x input-y])))
(defscreen scene
:on-timer
(fn [screen [entities]]
(when-let [timer-fn (get-in entities [:room :timers (:id screen) 2])]
(timer-fn screen entities)))
:on-show
(fn [screen entities]
(let [screen (assoc screen :total-time 0)]
(let [[^OrthographicCamera cam] (utils/setup-viewport screen 320 240)]
(set! (. cam zoom) 0.95)
(let [shader (ShaderProgram. ^String v-shader ^String pix-shader)
_ (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)}
entities {:rooms rooms
:step-particles (assoc (particle-effect "particles/step") :x 100 :y 100 :baseline 241)
:cam {:zoom 0.95
:paused? false
:object nil}
: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")}
:state (get-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 "blink-other.ogg")
:object nil}
:fade {:object nil
:opacity 0.0}
:white-fade (assoc (utils/get-texture "white.png")
:scale-x 20
:scale-y 20
:baseline 9500
:opacity 0.0
:origin-x 0
:origin-y 0)
: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"
:current :main
:last nil
:override :hourglass
:last-pos [0 0]
:down-target nil}
: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 screen entities)
entities)))))
:on-resume (fn [screen [entities]]
(doseq [[k [start time fn]] (get-in entities [:room :timers])]
(add-timer! screen k start time)))
:on-key-up
(fn [screen entities]
(when (= (key-code :escape) (:key screen))
(utils/toggle-fullscreen!))
nil)
:on-render
(fn [{:keys [^OrthographicCamera camera ^FitViewport viewport] :as screen} [entities]]
(.apply viewport)
(if (get-in entities [:closing? :value])
(let [entities (utils/apply-tweens screen entities (:tweens entities))
layers (get-layers entities)
all-entities (concat (vals entities) 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])))))
nil)
(let [entities (fade-in-first-time-if-necessary screen entities)
entities (utils/apply-tweens screen entities (:tweens entities))
entities (update-cursor screen entities)
entities (start-script-if-necessary 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])))]
(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 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 (get-rendered entities e))
(render! screen [(get-rendered entities e)])))
entities))))
:on-resize (fn [{:keys [^FitViewport 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
mouse-moved
:on-touch-dragged
mouse-moved
:on-touch-down
(fn [{:keys [input-x input-y ^FitViewport viewport] :as screen} [entities]]
(when (utils/contains-point? (.getScreenX viewport) (.getScreenY viewport)
(.getScreenWidth viewport) (.getScreenHeight viewport)
input-x input-y)
(when (and (= (button-code :left)
(:button screen))
(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)
interaction (get-interaction entities x y)
interacting-entity (get-interacting-entity entities x y)]
(assoc-in entities [:cursor :down-target] (or (:id interacting-entity ) (:id interaction) nil))))))
:on-touch-up (fn [{:keys [input-x input-y ^FitViewport 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]]
(when-not (get-in entities [:tweens :fade-out])
(input! :set-cursor-image (utils/cursor "cursor.png" :hourglass) 0 0)
(-> 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 (.clear @(resolve 'advent.core/am))
(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 demo
:on-show
(fn [screen entities]
(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]]
(.apply viewport)
(render! screen [(:label entities)])
entities)
:on-resize
(fn [{:keys [^FitViewport viewport width height]} entities]
(.update viewport width height true))
)
(defscreen hud
:on-show
(fn [screen entities]
(let [screen (assoc screen :total-time 0)]
(utils/setup-viewport screen 320 240)
{:close (assoc (utils/get-texture "close.png")
:x 304 :y 224
:width 16 :height 16
:baseline 9000
:opacity 0.8)
:inventory (assoc (utils/get-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.1)}))
:on-render
(fn [{:keys [^FitViewport viewport] :as screen} [entities]]
(.apply viewport)
(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 [{:keys [^FitViewport viewport width height]} entities]
(.update viewport width height 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)))))