diff --git a/src/cljs/topdown2d/core.cljs b/src/cljs/topdown2d/core.cljs index bb08ef4..de8feec 100644 --- a/src/cljs/topdown2d/core.cljs +++ b/src/cljs/topdown2d/core.cljs @@ -31,10 +31,9 @@ (defn set-timing "sets the current time at the given key" [state timingkey] - (assoc-in - state - [:timing timingkey] - (.now js/performance))) + (assoc-in state + [:timing timingkey] + (.now js/performance))) (defn set-fps "calculates the current fps using the elapsed time" @@ -46,12 +45,12 @@ (defn set-elapsed-seconds "calculates and writes the elapsed seconds since the last frame" [gamestate] - (assoc-in - gamestate - [:timing :elapsed] - (/ (-(get-in gamestate [:timing :now]) - (get-in gamestate [:timing :prev])) - 1000))) + (update gamestate + :timing + #(let [{:keys [now prev]} %] + (assoc % :elapsed + (/ (- now prev) + 1000))))) (defn update-scene "updates the current scene using its udpate function" @@ -59,9 +58,9 @@ (if-not (:continue? gamestate) gamestate (let [scenekey (:scene gamestate) - scenestate (get-in gamestate [:scenes scenekey]) - updatefunc (:update scenestate) - newstate (updatefunc gamestate scenestate)] + {updatefunc :update + :as scene} (get-in gamestate [:scenes scenekey]) + newstate (updatefunc gamestate scene)] (assoc-in gamestate [:scenes scenekey] newstate)))) (defn continue-running? @@ -74,14 +73,11 @@ (cond (and continue? (input/keydown? :Digit2) - (input/keydown? :ControlLeft)) - false + (input/keydown? :ControlLeft)) false (and (not continue?) (input/keydown? :Digit3) - (input/keydown? :ControlLeft)) - true - :else - continue?)))) + (input/keydown? :ControlLeft)) true + :else continue?)))) (defn update-step "updates timing information and the current scene" @@ -118,11 +114,22 @@ (get-in gamestate [:dimensions :w]) (get-in gamestate [:dimensions :h])) (let [scenekey (:scene gamestate) - scene (get-in gamestate [:scenes scenekey]) - drawfunc (:draw scene)] - (drawfunc gamestate scene)) + {:keys [draw] :as scene} (get-in gamestate [:scenes scenekey])] + (draw gamestate scene)) (draw-fps gamestate)) +(defn timeout + "calculates the duration of update-step and draw-step. + substracts that from the wait time to reach target-fps + more accurately. + if continue? is true, wait for 5 seconds plain" + [gamestate] + (if (:continue? gamestate) + (/ (- 1000 (- (.now js/performance) + (get-in gamestate [:timing :now]))) + (:target-fps gamestate)) + 5000)) + (defn mainloop "transforms the given gamestate by invoking a series of update functions and draws it using the 2d context of the gamestate. @@ -130,35 +137,21 @@ [gamestate] (let [newstate (update-step gamestate)] (draw-step newstate) - ;; calculate the duration of update-step and draw-step - ;; substract that from the wait time to reach target-fps - ;; more accurately - (let [now (get-in newstate [:timing :now]) - duration (- (.now js/performance) now) - timeout (if (:continue? newstate) - (/ - (- 1000 duration) - (:target-fps newstate)) - 5000)] - (.setTimeout js/window - (fn [] - (.requestAnimationFrame - js/window - #(mainloop newstate))) - timeout)))) + (.setTimeout js/window + (fn [] + (.requestAnimationFrame + js/window + #(mainloop newstate))) + (timeout newstate)))) (defn init-scenes "initiates the scene data maps using their respective init functions" [] - (assoc - gamestate - :scenes - (reduce - (fn [scenes [scenekey scenestate]] - (let [initfunc (:init scenestate) - newstate (initfunc gamestate scenestate)] - (assoc scenes scenekey newstate))) - {} - (:scenes gamestate)))) + (update gamestate + :scenes + #(reduce + (fn [carr [key scene]] + (assoc carr key ((:init scene) gamestate scene))) + {} %))) (mainloop (init-scenes)) diff --git a/src/cljs/topdown2d/demoscene.cljs b/src/cljs/topdown2d/demoscene.cljs index 0fd837f..fc75dbe 100644 --- a/src/cljs/topdown2d/demoscene.cljs +++ b/src/cljs/topdown2d/demoscene.cljs @@ -21,15 +21,15 @@ :from 1 :count 8 :last-cycle 0 - ;; seconds per cycle - :spc 0.08}}} + ;; cycles per second + :cps 10}}} :viewport {:image (.getElementById js/document "demo-background") :keep-in {:x 0 :y 0 :w 2239 :h 2235} :x 1 :y 1 :d :? ;; pixels per second - :pps 350 + :pps 150 :w (get-in gamestate [:dimensions :w]) :h (get-in gamestate [:dimensions :h])}})) diff --git a/src/cljs/topdown2d/sprites.cljs b/src/cljs/topdown2d/sprites.cljs index 35d2139..cab29fe 100644 --- a/src/cljs/topdown2d/sprites.cljs +++ b/src/cljs/topdown2d/sprites.cljs @@ -3,38 +3,30 @@ (defn- reset-cycle [obj] (let [cycle (get-in obj [:sprite :cycle]) {:keys [pos from] maxpos :count} cycle - reset-position? (> (inc pos) maxpos)] + reset? (> (inc pos) maxpos) + new-pos (if reset? from (inc pos))] (-> obj ;; set position - (assoc-in - [:sprite :cycle :pos] - (if reset-position? - from - (inc pos))) + (assoc-in [:sprite :cycle :pos] new-pos) ;; timestamp of last cycle is 0 - (assoc-in - [:sprite :cycle :last-cycle] - 0)))) + (assoc-in [:sprite :cycle :last-cycle] 0)))) (defn proc [gamestate obj] - (let [sprite (:sprite obj) - sprite-cycle (:cycle sprite) - {:keys [spc last-cycle]} sprite-cycle + (let [cycle (get-in obj [:sprite :cycle]) + {:keys [cps last-cycle]} cycle elapsed (get-in gamestate [:timing :elapsed])] ;; new sprite frame? - (if (> (+ last-cycle elapsed) spc) + (if (> (+ last-cycle elapsed) (/ 1 cps)) (reset-cycle obj) ;; no new sprite, increase last-cycle - (update-in - obj - [:sprite :cycle :last-cycle] - #(+ % elapsed))))) + (update-in obj + [:sprite :cycle :last-cycle] + + elapsed)))) (defn reset [obj] - (assoc-in - obj - [:sprite :cycle :pos] - 0)) + (assoc-in obj + [:sprite :cycle :pos] + 0)) (defn- pos-in-sprite [sprite d] (let [{:keys [size rows]} sprite @@ -43,13 +35,11 @@ {:y (* row size) :x (* pos size)})) (defn draw [ctx obj] - (let [{:keys [x y w h d sprite]} obj - image (:image sprite) - sprite-size (:size sprite) - sprite-cycle (:cycle sprite) + (let [{:keys [x y w h d] + {:keys [image size cycle] :as sprite} :sprite} obj pos (pos-in-sprite sprite d)] (.drawImage ctx image - (:x pos) (:y pos) sprite-size sprite-size - x y sprite-size sprite-size))) + (:x pos) (:y pos) size size + x y size size)))