From e233c67004ca785091906291ef821b5b35ce8cc5 Mon Sep 17 00:00:00 2001 From: Remington Covert Date: Tue, 5 May 2015 08:41:30 -0700 Subject: [PATCH] A totally different approach to night. --- .../advent/screens/rooms/inside_castle.clj | 2 +- .../advent/screens/rooms/outside_house.clj | 51 +++-- desktop/src-common/advent/screens/scene.clj | 175 +++++++++++++++++- desktop/src-common/advent/tween.clj | 8 +- desktop/src-common/advent/utils.clj | 3 + 5 files changed, 212 insertions(+), 27 deletions(-) diff --git a/desktop/src-common/advent/screens/rooms/inside_castle.clj b/desktop/src-common/advent/screens/rooms/inside_castle.clj index 0dd26bad..54e3dbae 100644 --- a/desktop/src-common/advent/screens/rooms/inside_castle.clj +++ b/desktop/src-common/advent/screens/rooms/inside_castle.clj @@ -482,7 +482,7 @@ entities) (if (and (not (actions/has-item? entities :walkie-talkies)) (actions/has-obtained? entities :walkie-talkies)) - entities + (update-in entities [:room :entities] dissoc :walkie-talkie) (update-in entities [:room :entities] dissoc :walkie-talkie)) (if (#{:night :sunrise} (get-in entities [:state :time])) (make-night entities) diff --git a/desktop/src-common/advent/screens/rooms/outside_house.clj b/desktop/src-common/advent/screens/rooms/outside_house.clj index 0a1718e2..fbfd78f7 100644 --- a/desktop/src-common/advent/screens/rooms/outside_house.clj +++ b/desktop/src-common/advent/screens/rooms/outside_house.clj @@ -16,20 +16,37 @@ -(defn dawn-fade [screen entities] - (as-> entities entities - (assoc-in entities - [:tweens :dawn-fade] - (tween/tween :dawn-fade screen [:dawn :opacity] 1.0 0.0 12.5)) - (assoc-in entities - [:dawn :opacity] - 1.0))) +(defn dawn-fade [entities] + (actions/run-action entities + (begin [this screen entities] + (-> entities + (assoc-in [:tweens :dawn-r] (tween/tween :dawn-r screen [:time-profiles :default :r] :current 0.63 50.0 :entities entities)) + (assoc-in [:tweens :dawn-g] (tween/tween :dawn-g screen [:time-profiles :default :g] :current 0.36 50.0 :entities entities)) + (assoc-in [:tweens :dawn-b] (tween/tween :dawn-b screen [:time-profiles :default :b] :current 0.23 50.0 :entities entities)) + (assoc-in [:tweens :hue-amount-v] (tween/tween :hue-amount-v screen [:time-profiles :default :hue-amount] :current 0.0 50.0 :entities entities)) + (assoc-in [:tweens :multiply-amount-v] (tween/tween :multiply-amount-v screen [:time-profiles :default :multiply-amount] :current 0.0 50.0 :entities entities)) + + (assoc-in [:tweens :dawn-r-s] (tween/tween :dawn-r-s screen [:time-profiles :sprite :r] :current 0.63 50.0 :entities entities)) + (assoc-in [:tweens :dawn-g-s] (tween/tween :dawn-g-s screen [:time-profiles :sprite :g] :current 0.36 50.0 :entities entities)) + (assoc-in [:tweens :dawn-b-s] (tween/tween :dawn-b-s screen [:time-profiles :sprite :b] :current 0.23 50.0 :entities entities)) + (assoc-in [:tweens :hue-amount-v-s] (tween/tween :hue-amount-v-s screen [:time-profiles :sprite :hue-amount] :current 0.0 50.0 :entities entities)) + (assoc-in [:tweens :multiply-amount-v-s] (tween/tween :multiply-amount-v-s screen [:time-profiles :sprite :multiply-amount] :current 0.0 50.0 :entities entities))) + ) + (continue [this screen entities] + entities) + (done? [this screen entities] + true) + (terminate [this screen entities] + entities))) + + + (defn walk-to-castle [entities dawn?] (actions/walk-to entities :ego [0 80]) (actions/walk-straight-to entities :ego [-20 80]) (if dawn? - (actions/transition-background entities :outside-castle [330 80] :between dawn-fade) + (actions/transition-background entities :outside-castle [330 80]) (actions/transition-background entities :outside-castle [330 80])) (actions/walk-straight-to entities :ego [310 80])) @@ -81,6 +98,7 @@ (if (is-ready-for-slingshot entities) (do (actions/walk-to entities :ego [141 90] :face :right) + (dawn-fade entities) (actions/talk entities :ego "Here goes!") (actions/play-animation entities :ego :reach-start :stop? false) (magic entities) @@ -359,14 +377,14 @@ (assoc (texture "outsidehouse/background-trees.png") :x 0 :y 0 :baseline 44) (assoc (texture "outsidehouse/fg1.png") :x 0 :y 0 :baseline 1000 :parallax 1.5) - (assoc (texture "outsidehouse/fg2.png") :x (- 320 55) :y 0 :baseline 1000 :parallax 1.5) - #_(assoc (texture "outsidehouse/fg1.png") :x 0 :y 0 :baseline 1000 :parallax 1.5) - #_(assoc (texture "outsidehouse/fg2.png") :x (- 320 30) :y 0 :baseline 1000 :parallax 1.5)] - :night [(assoc (texture "outsidehouse/background-dark.png") :x 0 :y 0 :baseline 0) - (assoc (texture "outsidehouse/house-dark.png") :x 0 :y 0 :baseline 122) - (assoc (texture "outsidehouse/fence-dark.png") :x 0 :y 0 :baseline 93) + (assoc (texture "outsidehouse/fg2.png") :x (- 320 55) :y 0 :baseline 1000 :parallax 1.5)] + :night [(assoc (texture "outsidehouse/background.png") :x 0 :y 0 :baseline 0) + (assoc (texture "outsidehouse/house.png") :x 0 :y 0 :baseline 122) + (assoc (texture "outsidehouse/fence.png") :x 0 :y 0 :baseline 93) - (assoc (texture "outsidehouse/background-trees-dark.png") :x 0 :y 0 :baseline 44)]} + (assoc (texture "outsidehouse/background-trees.png") :x 0 :y 0 :baseline 44) + (assoc (texture "outsidehouse/fg1.png") :x 0 :y 0 :baseline 1000 :parallax 1.5) + (assoc (texture "outsidehouse/fg2.png") :x (- 320 55) :y 0 :baseline 1000 :parallax 1.5)]} :entities {:sheep (actions/start-animation screen (assoc (animation->texture screen sheep-stand) :x 38 :y 160 :baseline 80 :scale-x (scaler [38 160]) @@ -463,6 +481,7 @@ :x 139 :y 73 :baseline 167 :anim cauldron :anim-start 0 + :night-profile :none :script (actions/get-script entities (actions/talk entities :ego "That's a big cauldron!")) :scripts put-something-in-cauldron)) :wizard (rooms/make-entity :wizard (common/make-wizard screen {:x 190 :y 78 :baseline 162 :scale-x 1.2 :scale-y 1.2 diff --git a/desktop/src-common/advent/screens/scene.clj b/desktop/src-common/advent/screens/scene.clj index 92febed3..c18e043f 100644 --- a/desktop/src-common/advent/screens/scene.clj +++ b/desktop/src-common/advent/screens/scene.clj @@ -40,6 +40,7 @@ [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 @@ -49,6 +50,155 @@ (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) @@ -293,6 +443,7 @@ :axe-wood (utils/flip axe-wood)} :baseline (- 240 (last start-pos)) :facing :right + :night-profile :sprite :origin-x 9 :origin-y 0 :scaled true @@ -496,7 +647,7 @@ (update-fn screen entities) entities)) -(defn render-parallax [{:keys [^OrthographicCamera camera ^Stage renderer] :as screen} {:keys [parallax] :as e }] +(defn render-parallax [{:keys [^OrthographicCamera camera ^Stage renderer ^ShaderProgram shader] :as screen} {:keys [parallax] :as e }] (let [tmp (Vector3.) tmp2 (Vector3.) @@ -520,7 +671,7 @@ (.begin batch) (.setProjectionMatrix batch parallax-combined) - (.setColor batch (color 1 1 1 (or (:opacity e) 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)) @@ -532,6 +683,11 @@ (.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) @@ -565,6 +721,9 @@ (let [[cam] (utils/setup-viewport screen 320 240)] (set! (. cam zoom) 0.95) (let [_ (input! :set-cursor-image (utils/cursor "cursor.png" :main) 0 0) + shader (ShaderProgram. v-shader pix-shader) + _ (println (.getLog 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) @@ -594,6 +753,10 @@ :pull-sword (utils/make-music "pull-sword.ogg") :night (utils/make-music "night.ogg")} :state (get-state) + :time-profiles {:object nil + :default utils/default-night-merge + :sprite utils/default-night-merge-sprite + :none {}} :sounds {:blink (sound "blink-other.ogg") :object nil} @@ -606,10 +769,6 @@ :opacity 0.0 :origin-x 0 :origin-y 0) - :dawn (assoc (texture "dawn.png") - :x 0 :y 0 :baseline 240 - :colorize? true - :opacity 0.0) :actions {:object nil :channel (chan) :current nil @@ -709,8 +868,8 @@ (music! m :set-volume (utils/current-music-volume (get-in entities [:volume :value]))))) (doseq [e (sort-by :baseline all-entities)] (if (:parallax e) - (render-parallax screen e) - (render! screen [e]))) + (render-parallax screen (get-rendered entities e)) + (render! screen [(get-rendered entities e)]))) entities))) diff --git a/desktop/src-common/advent/tween.clj b/desktop/src-common/advent/tween.clj index 312ab24a..31974ba7 100644 --- a/desktop/src-common/advent/tween.clj +++ b/desktop/src-common/advent/tween.clj @@ -43,11 +43,15 @@ (let [t (dec (/ t duration))] (+ (* delta (inc (* t t t))) start))) -(defn tween [id screen path start end duration & {:keys [finish ease]}] +(defn tween [id screen path start end duration & {:keys [finish ease entities]}] (let [ease (or ease ease-linear) finish (or finish identity) start-time (or (:total-time screen) 0.0) - delta (- end start)] + start (if (and entities (= start :current)) + (get-in entities path) + start) + delta (- end start) + ] (fn [e total-time] (let [delta-time (- total-time start-time) pct-done (min (/ delta-time duration) 1.0) diff --git a/desktop/src-common/advent/utils.clj b/desktop/src-common/advent/utils.clj index 6e871a6f..8ece79c6 100644 --- a/desktop/src-common/advent/utils.clj +++ b/desktop/src-common/advent/utils.clj @@ -218,3 +218,6 @@ (assoc-in entities [:cursor :override] (or (:cursor mouse-override) (when (#{:main :active-main} (get-in entities [:cursor :last])) :active-main))) (assoc-in entities [:cursor :override] nil)) entities))) + +(def default-night-merge {:r 0.08 :g 0.1 :b 0.36 :multiply-amount 1.0 :hue-amount 1.0}) +(def default-night-merge-sprite {:r 0.08 :g 0.1 :b 0.36 :multiply-amount 0.3 :hue-amount 0.4})