stuff
This commit is contained in:
@@ -43,7 +43,7 @@
|
|||||||
(>! tx-chan (js/JSON.stringify (clj->js msg))))))
|
(>! tx-chan (js/JSON.stringify (clj->js msg))))))
|
||||||
(assoc state :outbox []))
|
(assoc state :outbox []))
|
||||||
|
|
||||||
(defn ticker [app state layers entity-id rx-chan tx-chan t]
|
(defn ticker [app state layers rx-chan tx-chan t]
|
||||||
(let [dt (.-deltaTime t)
|
(let [dt (.-deltaTime t)
|
||||||
{world-layer :world-layer
|
{world-layer :world-layer
|
||||||
entity-layer :entity-layer} layers
|
entity-layer :entity-layer} layers
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
elapsed (.-elapsedMS t)
|
elapsed (.-elapsedMS t)
|
||||||
{:keys [player entities]} (-> (update @state :elapsed + elapsed)
|
{:keys [player entities]} (-> (update @state :elapsed + elapsed)
|
||||||
(update/update-entities dt layers)
|
(update/update-entities dt layers)
|
||||||
(update/update-player dt send-interval layers entity-id entity-relative-mouse-pos)
|
(update/update-player dt send-interval layers entity-relative-mouse-pos)
|
||||||
(update/update-from-server rx-chan)
|
(update/update-from-server rx-chan)
|
||||||
(drain-outbox! tx-chan)
|
(drain-outbox! tx-chan)
|
||||||
(->> (swap! state merge)))
|
(->> (swap! state merge)))
|
||||||
@@ -78,7 +78,6 @@
|
|||||||
(defn init []
|
(defn init []
|
||||||
(let [app (doto (pixi/Application.)
|
(let [app (doto (pixi/Application.)
|
||||||
(.init {:resizeTo js/window :autoDensity true :resolution (.-devicePixelRatio js/window)}))
|
(.init {:resizeTo js/window :autoDensity true :resolution (.-devicePixelRatio js/window)}))
|
||||||
entity-id (atom 1)
|
|
||||||
state (atom {:player {:velocity {:x 0 :y 0}
|
state (atom {:player {:velocity {:x 0 :y 0}
|
||||||
:keymap {:w 0 :a 0 :s 0 :d 0 :lmb 0}
|
:keymap {:w 0 :a 0 :s 0 :d 0 :lmb 0}
|
||||||
:last-attack -1
|
:last-attack -1
|
||||||
@@ -98,8 +97,8 @@
|
|||||||
world-layer (pixi/Container.)
|
world-layer (pixi/Container.)
|
||||||
entity-layer (pixi/Container.)
|
entity-layer (pixi/Container.)
|
||||||
ui-layer (pixi/Container.)
|
ui-layer (pixi/Container.)
|
||||||
tx-chan (async/chan (async/sliding-buffer 10))
|
tx-chan (async/chan (async/dropping-buffer 10))
|
||||||
rx-chan (async/chan (async/sliding-buffer 2))
|
rx-chan (async/chan)
|
||||||
layers {:entity-layer entity-layer
|
layers {:entity-layer entity-layer
|
||||||
:world-layer world-layer
|
:world-layer world-layer
|
||||||
:ui-layer ui-layer}
|
:ui-layer ui-layer}
|
||||||
@@ -134,4 +133,4 @@
|
|||||||
(partial sb-callback false))
|
(partial sb-callback false))
|
||||||
player (assoc e :renderable p :shootbox sb)]
|
player (assoc e :renderable p :shootbox sb)]
|
||||||
(swap! state update-in [:player] merge player)
|
(swap! state update-in [:player] merge player)
|
||||||
(.. app -ticker (add (partial ticker app state layers entity-id rx-chan tx-chan)))))))))
|
(.. app -ticker (add (partial ticker app state layers rx-chan tx-chan)))))))))
|
||||||
|
|||||||
@@ -19,36 +19,16 @@
|
|||||||
(assoc e :renderable renderable))
|
(assoc e :renderable renderable))
|
||||||
e))
|
e))
|
||||||
|
|
||||||
(defn apply-player-shoot [state entity-id mouse-pos]
|
(defn apply-player-shoot [state mouse-pos]
|
||||||
(if (and (get-in state [:player :keymap :lmb] false)
|
(if (and (get-in state [:player :keymap :lmb] false)
|
||||||
(< (+ (get-in state [:player :last-attack] -1)
|
(< (+ (get-in state [:player :last-attack] -1)
|
||||||
(* 1000 (get-in state [:player :attack-speed] 0.75)))
|
(* 1000 (get-in state [:player :attack-speed] 0.75)))
|
||||||
(js/Date.now)))
|
(js/Date.now)))
|
||||||
(let [player-sprite (get-in state [:player :renderable])
|
|
||||||
speed 15
|
|
||||||
image "/sprite/projectile.png"
|
|
||||||
start-x (.-x player-sprite)
|
|
||||||
start-y (.-y player-sprite)
|
|
||||||
position mouse-pos
|
|
||||||
target-x (.-x position)
|
|
||||||
target-y (.-y position)
|
|
||||||
dx (- target-x start-x)
|
|
||||||
dy (- target-y start-y)
|
|
||||||
h (js/Math.sqrt (+ (* dx dx) (* dy dy)))
|
|
||||||
vx (* (/ dx h) speed)
|
|
||||||
vy (* (/ dy h) speed)
|
|
||||||
eid (-> (swap! entity-id inc)
|
|
||||||
(str)
|
|
||||||
(keyword))
|
|
||||||
e {:sprite image
|
|
||||||
:hypotenuse h
|
|
||||||
:x start-x
|
|
||||||
:y start-y
|
|
||||||
:velocity {:x vx :y vy}}]
|
|
||||||
(-> state
|
(-> state
|
||||||
(update :outbox conj {:type "shoot"})
|
(update :outbox conj {:type "shoot"
|
||||||
(assoc-in [:entities eid] e)
|
:x (.-x mouse-pos)
|
||||||
(assoc-in [:player :last-attack] (js/Date.now))))
|
:y (.-y mouse-pos)})
|
||||||
|
(assoc-in [:player :last-attack] (js/Date.now)))
|
||||||
state))
|
state))
|
||||||
|
|
||||||
(defn apply-player-position [state send-interval]
|
(defn apply-player-position [state send-interval]
|
||||||
@@ -69,14 +49,14 @@
|
|||||||
(apply-velocity dt)))]
|
(apply-velocity dt)))]
|
||||||
(assoc state :entities new-entities)))
|
(assoc state :entities new-entities)))
|
||||||
|
|
||||||
(defn update-player [state dt send-interval layers entity-id mouse-pos]
|
(defn update-player [state dt send-interval layers mouse-pos]
|
||||||
(let [{player :player} state
|
(let [{player :player} state
|
||||||
updated-player (-> player
|
updated-player (-> player
|
||||||
(apply-renderable layers)
|
(apply-renderable layers)
|
||||||
(apply-velocity dt))]
|
(apply-velocity dt))]
|
||||||
(-> (assoc state :player updated-player)
|
(-> (assoc state :player updated-player)
|
||||||
(apply-player-position send-interval)
|
(apply-player-position send-interval)
|
||||||
(apply-player-shoot entity-id mouse-pos))))
|
(apply-player-shoot mouse-pos))))
|
||||||
|
|
||||||
(defn- deep-merge [a b]
|
(defn- deep-merge [a b]
|
||||||
(if (and (map? a) (map? b))
|
(if (and (map? a) (map? b))
|
||||||
|
|||||||
@@ -11,19 +11,21 @@
|
|||||||
|
|
||||||
(defn ws-handler [state state-chan player-id]
|
(defn ws-handler [state state-chan player-id]
|
||||||
(go-websocket [in out err]
|
(go-websocket [in out err]
|
||||||
(s/change state-chan update :players assoc player-id {:out out :in in :err err})
|
(s/change state-chan update :players assoc player-id {:out out :in in :err err :x 0 :y 0})
|
||||||
(go-loop []
|
(go-loop []
|
||||||
(when-let [e (<! err)]
|
(when-let [e (<! err)]
|
||||||
(println (.getMessage e))
|
(println (.getMessage e))
|
||||||
(recur)))
|
(recur)))
|
||||||
(go-loop []
|
(go-loop []
|
||||||
(if-let [raw (<! in)]
|
(if-let [raw (<! in)]
|
||||||
|
(when (contains? (@state :players) player-id) ; Only if player has been initialized do we accept messages
|
||||||
(let [msg (j/from-json raw)
|
(let [msg (j/from-json raw)
|
||||||
type (get msg :type "invalid")]
|
type (get msg :type "invalid")]
|
||||||
(cond
|
(cond
|
||||||
(= type "shoot") (handler/handle-shoot state state-chan player-id msg)
|
(= type "position") (handler/handle-position @state state-chan player-id msg)
|
||||||
|
(= type "shoot") (handler/handle-shoot @state state-chan player-id msg)
|
||||||
(= type "invalid") (>! out "Hello World!"))
|
(= type "invalid") (>! out "Hello World!"))
|
||||||
(println msg)
|
(println msg))
|
||||||
(recur))
|
(recur))
|
||||||
(do
|
(do
|
||||||
(s/change state-chan update :players dissoc player-id)
|
(s/change state-chan update :players dissoc player-id)
|
||||||
@@ -42,14 +44,14 @@
|
|||||||
(defn build-application [state state-chan]
|
(defn build-application [state state-chan]
|
||||||
(c/routes
|
(c/routes
|
||||||
(c/GET "/" r (index-handler r))
|
(c/GET "/" r (index-handler r))
|
||||||
(c/GET "/ws" [] (ws-handler @state state-chan (random-uuid))) ; TODO: Auth here
|
(c/GET "/ws" [] (ws-handler state state-chan (random-uuid))) ; TODO: Auth here
|
||||||
(route/resources "/")
|
(route/resources "/")
|
||||||
(route/not-found "<h1>The requested resource does not exist...</h1>")))
|
(route/not-found "<h1>The requested resource does not exist...</h1>")))
|
||||||
|
|
||||||
(defn game-loop [state state-chan]
|
(defn game-loop [state state-chan]
|
||||||
(go-loop []
|
(go-loop []
|
||||||
(let [start-time (System/currentTimeMillis)
|
(let [start-time (System/currentTimeMillis)
|
||||||
max-inputs-per-tick 15000 ; Stops the game from spinning endlessly, dropping ticks
|
max-inputs-per-tick 15000 ; Stops the game from spinning for too long with events endlessly, dropping ticks
|
||||||
events-to-apply (loop [inputs []
|
events-to-apply (loop [inputs []
|
||||||
count 0]
|
count 0]
|
||||||
(if (>= count max-inputs-per-tick)
|
(if (>= count max-inputs-per-tick)
|
||||||
@@ -57,15 +59,22 @@
|
|||||||
(if-let [args (async/poll! state-chan)]
|
(if-let [args (async/poll! state-chan)]
|
||||||
(recur (conj inputs args) (inc count))
|
(recur (conj inputs args) (inc count))
|
||||||
inputs)))]
|
inputs)))]
|
||||||
(doseq [event-args events-to-apply]
|
(let [event-state (reduce (fn [state event-args] ((event-args 0) state (rest event-args)))
|
||||||
(apply swap! state event-args))
|
@state
|
||||||
(doseq [{out :out} (vals (:players @state))]
|
events-to-apply)
|
||||||
|
system-state (reduce (fn [state system] (system state))
|
||||||
|
event-state
|
||||||
|
(event-state :systems))
|
||||||
|
entities (:entities @state)
|
||||||
|
players (:players @state)]
|
||||||
|
(swap! state merge system-state)
|
||||||
|
(doseq [{out :out} (vals players)]
|
||||||
(>! out (j/to-json {:type "sync"
|
(>! out (j/to-json {:type "sync"
|
||||||
:entities (:entities @state)})))
|
:entities entities}))))
|
||||||
(let [elapsed (- (System/currentTimeMillis) start-time)
|
(let [elapsed (- (System/currentTimeMillis) start-time)
|
||||||
sleep-time (max 0 (- 50 elapsed))]
|
sleep-time (max 0 (- 50 elapsed))]
|
||||||
(<! (async/timeout sleep-time))))
|
(<! (async/timeout sleep-time)))
|
||||||
(recur)))
|
(recur))))
|
||||||
|
|
||||||
(defn -main []
|
(defn -main []
|
||||||
(let [state (atom {:systems []
|
(let [state (atom {:systems []
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
(ns il.handler
|
(ns il.handler
|
||||||
(:require [il.state :as s]))
|
(:require [il.state :as s]))
|
||||||
|
|
||||||
|
(defn handle-position [_ state-chan player-id {x :x y :y}]
|
||||||
|
(s/change state-chan update-in [:players player-id] assoc :x x :y y))
|
||||||
|
|
||||||
(defn handle-shoot [state state-chan player-id msg]
|
(defn handle-shoot [state state-chan player-id msg]
|
||||||
(let [bullet-id (random-uuid)
|
(let [bullet-id (random-uuid)
|
||||||
{x :x y :y} (get-in state [:players player-id])
|
{x :x y :y} (get-in state [:players player-id])
|
||||||
{tx :x ty :y} msg
|
{tx :x ty :y} msg
|
||||||
|
_ (println state)
|
||||||
|
_ (println msg)
|
||||||
|
_ (println (get-in state [:players player-id]))
|
||||||
dx (- tx x)
|
dx (- tx x)
|
||||||
dy (- ty y)
|
dy (- ty y)
|
||||||
h (Math/sqrt (+ (Math/pow dx 2) (Math/pow dy 2)))
|
h (Math/sqrt (+ (Math/pow dx 2) (Math/pow dy 2)))
|
||||||
|
|||||||
@@ -2,4 +2,5 @@
|
|||||||
(:require [clojure.core.async :refer [>! go]]))
|
(:require [clojure.core.async :refer [>! go]]))
|
||||||
|
|
||||||
(defn change [state-chan & args]
|
(defn change [state-chan & args]
|
||||||
|
(println "Appending to state-chan: " args)
|
||||||
(go (>! state-chan args)))
|
(go (>! state-chan args)))
|
||||||
|
|||||||
Reference in New Issue
Block a user