(ns advent.actions (:require [play-clj.core :refer :all] [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.g2d :refer :all] [clojure.pprint] [clojure.string :as s] [advent.pathfind] [advent.actions :as actions] [advent.screens.dialogue :as dialogue] [clojure.core.async :refer [put! ! >!! chan go thread take! alts!!]]) (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter] [com.badlogic.gdx.graphics.g2d TextureRegion])) (defprotocol IAction (begin [this screen entities]) (done? [this screen entities]) (continue [this screen entities]) (terminate [this screen entities]) (get-channel [this])) (defmacro get-script [entities & forms] `(fn [starting-entities#] (let [~entities (atom starting-entities#)] (thread ~@forms)))) (defn jump-to [screen entities entity [x y]] (let [scale-fn (-> entities :background :scale-fn) entity (assoc entity :x x :y y :baseline (- 240 y))] (if (:scaled entity) (assoc entity :scale-x (scale-fn y) :scale-y (scale-fn y)) entity))) (defn stop [screen entities target-id] (update-in entities [:background :entities target-id] #(merge % {:anim nil} (when (:anim %) (texture (animation! (:anim %) :get-key-frame 0.25)))))) (defn dist [x1 y1 x2 y2] (let [dx (- x1 x2) dy (- y1 y2)] (Math/sqrt (+ (* dx dx) (* dy dy))))) (defmacro run-action [entities & forms] `(let [c# (chan)] (do (put! (get-in (deref ~entities) [:actions :channel]) (reify IAction (get-channel [_] c#) ~@forms)) (reset! ~entities ( delta-x 0) right :else (:anim %)))))))) (done? [this screen entities] (let [{from-x :x from-y :y :keys [left right anim] :as target-entity} (get-in entities [:background :entities target-id])] (< (dist final-x final-y from-x from-y) 1))) (terminate [this screen entities] (stop screen entities target-id))) @entities))) (defn get-text-duration [text] (* (count (s/split text #" ")) 0.75)) (defn talk [entities target-id text] (let [initial-time (atom nil)] (run-action entities (begin [this screen entities] (let [_ (swap! initial-time #(or % (:total-time screen))) target-y (get-in entities [:background :entities target-id :y]) scale-fn (get-in entities [:background :scale-fn]) scale (scale-fn target-y) height (* scale 36)] (run! dialogue/talking-screen :on-talk :text text :x (get-in entities [:background :entities target-id :x]) :y (+ (get-in entities [:background :entities target-id :y]) height) :target-id target-id :scale scale) (assoc-in entities [:background :entities target-id :anim] (get-in entities [:background :entities target-id :talk])))) (continue [this screen entities] entities) (done? [this screen entities] (> (- (:total-time screen) @initial-time) (get-text-duration text))) (terminate [this screen entities] (run! dialogue/talking-screen :stop-talk :target-id target-id) (stop screen entities target-id))))) (defn give [entities target-id item] (run-action entities (begin [this screen entities] (sound! (sound "pickup.mp3") :play) (-> entities (update-in [:background :entities target-id :inventory] #(conj % item)) (assoc-in [:cursor :current] item))) (continue [this screen entities] entities) (done? [this screen entities] true) (terminate [this screen entities] entities))) (defn transition-background [entities new-background [x y]] (run-action entities (begin [this screen entities] (-> entities (assoc-in [:transition] (assoc (texture "black.png") :scale-x 20 :scale-y 20 :baseline 9500 :opacity 0.1)))) (continue [this screen entities] (update-in entities [:transition :opacity] + 0.075)) (done? [this screen entities] (>= (get-in entities [:transition :opacity]) 1.0)) (terminate [this screen entities] entities)) (run-action entities (begin [this screen entities] (let [ego (get-in entities [:background :entities :ego])] (-> entities (assoc-in [:background] (get-in entities [:backgrounds new-background])) (assoc-in [:background :entities :ego] ego) (assoc-in [:background :entities :ego :x] x) (assoc-in [:background :entities :ego :y] y)))) (continue [this screen entities] (update-in entities [:transition :opacity] - 0.075)) (done? [this screen entities] (<= (get-in entities [:transition :opacity]) 0.0)) (terminate [this screen entities] (dissoc entities :transition))))