(ns advent.tween) (defn ease-in-expo [power t start delta duration] (let [pct-done (/ t duration) pct-done (Math/pow pct-done power)] (+ start (* delta pct-done)))) (def ease-linear (partial ease-in-expo 1.0)) (def ease-in-quadratic (partial ease-in-expo 2.0)) (def ease-in-cubic (partial ease-in-expo 3.0)) (def ease-in-quartic (partial ease-in-expo 4.0)) (def ease-in-quintic (partial ease-in-expo 5.0)) (def ease-in-dectic (partial ease-in-expo 10.0)) (defn ease-in-out-quadratic [t start delta duration] (let [t (/ t (/ duration 2))] (if (< t 1) (+ (* (/ delta 2) t t) start) (let [t (dec t)] (+ (* (/ (- delta) 2) (dec (* t (- t 2)))) start))))) (defn ease-in-out-quintic [t start delta duration] (let [t (/ t (/ duration 2))] (if (< t 1) (+ (* (/ delta 2) t t t t t) start) (let [t (- t 2)] (+ (* (/ (- delta) 2) (- (* t t t t) 2)) start))))) (defn ease-out-quadratic [t start delta duration] (let [t (/ t duration)] (+ (* (- delta) t (- t 2)) start))) (defn ease-out-cubic [t start delta duration] (let [t (dec (/ t duration))] (+ (* delta (inc (* t t t))) start))) (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) 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) new-val (ease delta-time start delta duration) e (assoc-in e path (if (= 1.0 pct-done) end new-val))] (if (= 1.0 pct-done) (finish (update-in e [:tweens] dissoc id)) e)))))