|
|
@ -1,50 +1,40 @@
|
|
|
|
(ns topdown2d.core
|
|
|
|
(ns topdown2d.core
|
|
|
|
(:require
|
|
|
|
(:require
|
|
|
|
[topdown2d.demoscene :as demoscene]
|
|
|
|
[topdown2d.demoscene :as demoscene]
|
|
|
|
[topdown2d.input :as input]))
|
|
|
|
[topdown2d.input :as input]))
|
|
|
|
|
|
|
|
|
|
|
|
(enable-console-print!)
|
|
|
|
(enable-console-print!)
|
|
|
|
|
|
|
|
|
|
|
|
(def gamestate {
|
|
|
|
(def gamestate
|
|
|
|
:canvas (.getElementById js/document "gamecanvas")
|
|
|
|
{:canvas (.getElementById js/document "gamecanvas")
|
|
|
|
:ctx (.getContext (.getElementById js/document "gamecanvas") "2d")
|
|
|
|
:ctx (.getContext (.getElementById js/document "gamecanvas") "2d")
|
|
|
|
:target-fps 40
|
|
|
|
:target-fps 40
|
|
|
|
:timing {
|
|
|
|
:timing {;; msecs of previous frame
|
|
|
|
; msecs of previous frame
|
|
|
|
:prev 0
|
|
|
|
:prev 0
|
|
|
|
;; msecs of current frame
|
|
|
|
; msecs of current frame
|
|
|
|
:now 0
|
|
|
|
:now 0
|
|
|
|
;; fps resulting of prev and now
|
|
|
|
; fps resulting of prev and now
|
|
|
|
:fps 0
|
|
|
|
:fps 0
|
|
|
|
;; difference between prev and now in seconds
|
|
|
|
; difference between prev and now in seconds
|
|
|
|
:elapsed 0}
|
|
|
|
:elapsed 0
|
|
|
|
;; width and height of the canvas
|
|
|
|
}
|
|
|
|
:dimensions {:w 600
|
|
|
|
; width and height of the canvas
|
|
|
|
:h 400}
|
|
|
|
:dimensions {
|
|
|
|
:input {:dir :?}
|
|
|
|
:w 600
|
|
|
|
;; currently active scene
|
|
|
|
:h 400
|
|
|
|
:scene :demo
|
|
|
|
}
|
|
|
|
:scenes {:demo {:update demoscene/update-scene
|
|
|
|
:input {
|
|
|
|
:draw demoscene/draw-scene
|
|
|
|
:dir :?
|
|
|
|
:init demoscene/init
|
|
|
|
}
|
|
|
|
:data {}}}})
|
|
|
|
; currently active scene
|
|
|
|
|
|
|
|
:scene :demo
|
|
|
|
|
|
|
|
:scenes {
|
|
|
|
|
|
|
|
:demo {
|
|
|
|
|
|
|
|
:update demoscene/update-scene
|
|
|
|
|
|
|
|
:draw demoscene/draw-scene
|
|
|
|
|
|
|
|
:init demoscene/init
|
|
|
|
|
|
|
|
:data {}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defn set-timing
|
|
|
|
(defn set-timing
|
|
|
|
"sets the current time at the given key"
|
|
|
|
"sets the current time at the given key"
|
|
|
|
[state timingkey]
|
|
|
|
[state timingkey]
|
|
|
|
(assoc-in state
|
|
|
|
(assoc-in
|
|
|
|
[:timing timingkey]
|
|
|
|
state
|
|
|
|
(.now js/performance)))
|
|
|
|
[:timing timingkey]
|
|
|
|
|
|
|
|
(.now js/performance)))
|
|
|
|
|
|
|
|
|
|
|
|
(defn set-fps
|
|
|
|
(defn set-fps
|
|
|
|
"calculates the current fps using the elapsed time"
|
|
|
|
"calculates the current fps using the elapsed time"
|
|
|
@ -56,11 +46,10 @@
|
|
|
|
(defn set-elapsed-seconds
|
|
|
|
(defn set-elapsed-seconds
|
|
|
|
"calculates and writes the elapsed seconds since the last frame"
|
|
|
|
"calculates and writes the elapsed seconds since the last frame"
|
|
|
|
[gamestate]
|
|
|
|
[gamestate]
|
|
|
|
(assoc-in gamestate
|
|
|
|
(assoc-in
|
|
|
|
[:timing :elapsed]
|
|
|
|
gamestate
|
|
|
|
(/
|
|
|
|
[:timing :elapsed]
|
|
|
|
(-
|
|
|
|
(/ (-(get-in gamestate [:timing :now])
|
|
|
|
(get-in gamestate [:timing :now])
|
|
|
|
|
|
|
|
(get-in gamestate [:timing :prev]))
|
|
|
|
(get-in gamestate [:timing :prev]))
|
|
|
|
1000)))
|
|
|
|
1000)))
|
|
|
|
|
|
|
|
|
|
|
@ -77,12 +66,12 @@
|
|
|
|
"updates timing information and the current scene"
|
|
|
|
"updates timing information and the current scene"
|
|
|
|
[gamestate]
|
|
|
|
[gamestate]
|
|
|
|
(-> gamestate
|
|
|
|
(-> gamestate
|
|
|
|
(assoc-in [:input :dir] (input/dir))
|
|
|
|
(assoc-in [:input :dir] (input/dir))
|
|
|
|
(set-timing :now)
|
|
|
|
(set-timing :now)
|
|
|
|
(set-elapsed-seconds)
|
|
|
|
(set-elapsed-seconds)
|
|
|
|
(set-fps)
|
|
|
|
(set-fps)
|
|
|
|
(update-scene)
|
|
|
|
(update-scene)
|
|
|
|
(set-timing :prev)))
|
|
|
|
(set-timing :prev)))
|
|
|
|
|
|
|
|
|
|
|
|
(defn draw-fps
|
|
|
|
(defn draw-fps
|
|
|
|
"draws the current fps"
|
|
|
|
"draws the current fps"
|
|
|
@ -90,22 +79,22 @@
|
|
|
|
(let [ctx (:ctx gamestate)]
|
|
|
|
(let [ctx (:ctx gamestate)]
|
|
|
|
(aset ctx "fillStyle" "white")
|
|
|
|
(aset ctx "fillStyle" "white")
|
|
|
|
(.fillRect
|
|
|
|
(.fillRect
|
|
|
|
ctx
|
|
|
|
ctx
|
|
|
|
0 0 13 13)
|
|
|
|
0 0 13 13)
|
|
|
|
(aset ctx "fillStyle" "black")
|
|
|
|
(aset ctx "fillStyle" "black")
|
|
|
|
(aset ctx "font" "10px monospace")
|
|
|
|
(aset ctx "font" "10px monospace")
|
|
|
|
(.fillText
|
|
|
|
(.fillText
|
|
|
|
(:ctx gamestate)
|
|
|
|
(:ctx gamestate)
|
|
|
|
(int (get-in gamestate [:timing :fps]))
|
|
|
|
(int (get-in gamestate [:timing :fps]))
|
|
|
|
0 10)))
|
|
|
|
0 10)))
|
|
|
|
|
|
|
|
|
|
|
|
(defn draw-step
|
|
|
|
(defn draw-step
|
|
|
|
"clears the canvas, draws fps and invokes the scene draw function"
|
|
|
|
"clears the canvas, draws fps and invokes the scene draw function"
|
|
|
|
[gamestate]
|
|
|
|
[gamestate]
|
|
|
|
(.clearRect (:ctx gamestate)
|
|
|
|
(.clearRect (:ctx gamestate)
|
|
|
|
0 0
|
|
|
|
0 0
|
|
|
|
(get-in gamestate [:dimensions :w])
|
|
|
|
(get-in gamestate [:dimensions :w])
|
|
|
|
(get-in gamestate [:dimensions :h]))
|
|
|
|
(get-in gamestate [:dimensions :h]))
|
|
|
|
(let [scenekey (:scene gamestate)
|
|
|
|
(let [scenekey (:scene gamestate)
|
|
|
|
scene (scenekey (:scenes gamestate))
|
|
|
|
scene (scenekey (:scenes gamestate))
|
|
|
|
drawfunc (:draw scene)]
|
|
|
|
drawfunc (:draw scene)]
|
|
|
@ -119,32 +108,34 @@
|
|
|
|
[gamestate]
|
|
|
|
[gamestate]
|
|
|
|
(let [newstate (update-step gamestate)]
|
|
|
|
(let [newstate (update-step gamestate)]
|
|
|
|
(draw-step newstate)
|
|
|
|
(draw-step newstate)
|
|
|
|
; calculate the duration of update-step and draw-step
|
|
|
|
;; calculate the duration of update-step and draw-step
|
|
|
|
; substract that from the wait time to reach target-fps
|
|
|
|
;; substract that from the wait time to reach target-fps
|
|
|
|
; more accurately
|
|
|
|
;; more accurately
|
|
|
|
(let [now (get-in newstate [:timing :now])
|
|
|
|
(let [now (get-in newstate [:timing :now])
|
|
|
|
duration (- (.now js/performance) now)]
|
|
|
|
duration (- (.now js/performance) now)]
|
|
|
|
(.setTimeout js/window
|
|
|
|
(.setTimeout js/window
|
|
|
|
(fn []
|
|
|
|
(fn []
|
|
|
|
(.requestAnimationFrame js/window
|
|
|
|
(.requestAnimationFrame
|
|
|
|
#(mainloop newstate)))
|
|
|
|
js/window
|
|
|
|
(/
|
|
|
|
#(mainloop newstate)))
|
|
|
|
(- 1000 duration)
|
|
|
|
(/
|
|
|
|
(:target-fps gamestate))))))
|
|
|
|
(- 1000 duration)
|
|
|
|
|
|
|
|
(:target-fps gamestate))))))
|
|
|
|
|
|
|
|
|
|
|
|
(defn init-scenes
|
|
|
|
(defn init-scenes
|
|
|
|
"initiates the scene data maps using their respective init functions"
|
|
|
|
"initiates the scene data maps using their respective init functions"
|
|
|
|
[]
|
|
|
|
[]
|
|
|
|
(assoc
|
|
|
|
(assoc
|
|
|
|
gamestate
|
|
|
|
gamestate
|
|
|
|
:scenes
|
|
|
|
:scenes
|
|
|
|
(reduce
|
|
|
|
(reduce
|
|
|
|
(fn [scenes [scenekey scenedata]]
|
|
|
|
(fn [scenes [scenekey scenedata]]
|
|
|
|
(let [initfunc (:init scenedata)
|
|
|
|
(let [initfunc (:init scenedata)
|
|
|
|
newdata (initfunc gamestate scenedata)]
|
|
|
|
newdata (initfunc gamestate scenedata)]
|
|
|
|
(assoc scenes
|
|
|
|
(assoc
|
|
|
|
scenekey newdata)))
|
|
|
|
scenes
|
|
|
|
{}
|
|
|
|
scenekey newdata)))
|
|
|
|
(:scenes gamestate))))
|
|
|
|
{}
|
|
|
|
|
|
|
|
(:scenes gamestate))))
|
|
|
|
|
|
|
|
|
|
|
|
(mainloop (init-scenes))
|
|
|
|
(mainloop (init-scenes))
|
|
|
|