Compare commits
6 Commits
0e24e171da
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bd7ad1a28 | |||
| 507faf8875 | |||
| befcdfc352 | |||
| a179e453b1 | |||
| ba10d04fa2 | |||
| f11ce94adf |
@@ -4,8 +4,6 @@
|
|||||||
["pixi.js" :as pixi]
|
["pixi.js" :as pixi]
|
||||||
[goog.dom :as dom]
|
[goog.dom :as dom]
|
||||||
[cljs.core.async :as async :refer [go go-loop <! >!]]
|
[cljs.core.async :as async :refer [go go-loop <! >!]]
|
||||||
[il.common.race :as race]
|
|
||||||
[il.common.class :as class]
|
|
||||||
[frontend.il.entity :as entity]
|
[frontend.il.entity :as entity]
|
||||||
[frontend.il.update :as update]))
|
[frontend.il.update :as update]))
|
||||||
|
|
||||||
@@ -25,7 +23,7 @@
|
|||||||
right :a
|
right :a
|
||||||
up :w
|
up :w
|
||||||
down :s} (get-in @state [:player :keymap])
|
down :s} (get-in @state [:player :keymap])
|
||||||
speed (get-in @state [:player :speed] 5)]
|
speed (get-in @state [:player :speed] 2.33)]
|
||||||
(swap! state update-in [:player :velocity] assoc
|
(swap! state update-in [:player :velocity] assoc
|
||||||
:x (* speed (+ left right))
|
:x (* speed (+ left right))
|
||||||
:y (* speed (+ up down))))))
|
:y (* speed (+ up down))))))
|
||||||
@@ -38,12 +36,12 @@
|
|||||||
(when (count outbox)
|
(when (count outbox)
|
||||||
(go
|
(go
|
||||||
(doseq [msg outbox]
|
(doseq [msg outbox]
|
||||||
(println state)
|
(js/console.log (clj->js state))
|
||||||
(println "Writing event: " msg)
|
(js/console.log "Writing event: " (clj->js msg))
|
||||||
(>! 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 rx-chan tx-chan t]
|
(defn ticker [app state layers sb 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
|
||||||
@@ -51,9 +49,10 @@
|
|||||||
entity-relative-mouse-pos (.toLocal ^js entity-layer global-mouse-pos)
|
entity-relative-mouse-pos (.toLocal ^js entity-layer global-mouse-pos)
|
||||||
send-interval 25 ; Send every 25ms (10 tps)
|
send-interval 25 ; Send every 25ms (10 tps)
|
||||||
elapsed (.-elapsedMS t)
|
elapsed (.-elapsedMS t)
|
||||||
{:keys [player entities]} (-> (update @state :elapsed + elapsed)
|
{:keys [player entities players]} (-> (update @state :elapsed + elapsed)
|
||||||
(update/update-entities dt layers)
|
(update/update-state :entities dt layers)
|
||||||
(update/update-player dt send-interval layers entity-relative-mouse-pos)
|
(update/update-state :players dt layers)
|
||||||
|
(update/update-player dt send-interval layers entity-relative-mouse-pos sb)
|
||||||
(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)))
|
||||||
@@ -62,35 +61,35 @@
|
|||||||
entity-renderables (->> (vals entities)
|
entity-renderables (->> (vals entities)
|
||||||
(remove #(nil? (% :renderable)))
|
(remove #(nil? (% :renderable)))
|
||||||
(vec))
|
(vec))
|
||||||
|
other-players-renderables (->> (vals players)
|
||||||
|
(remove #(nil? (% :renderable)))
|
||||||
|
(vec))
|
||||||
world-renderables (vector {:renderable world-layer :x sx :y sy})
|
world-renderables (vector {:renderable world-layer :x sx :y sy})
|
||||||
player-renderables (vector player
|
player-renderables (vector player
|
||||||
(assoc player :renderable (:shootbox player)))
|
(assoc player :renderable (:shootbox player)))
|
||||||
things-to-update (concat player-renderables entity-renderables world-renderables)]
|
things-to-update (concat player-renderables
|
||||||
|
other-players-renderables
|
||||||
|
entity-renderables
|
||||||
|
world-renderables)]
|
||||||
(doseq [thing things-to-update]
|
(doseq [thing things-to-update]
|
||||||
; TODO: Add lerp here, we shouldn't just launch things around with their X/Y
|
|
||||||
; instead if the difference between curr-pos and tar-pos is > than vel try to move it to their every frame via vel
|
|
||||||
(let [{renderable :renderable
|
(let [{renderable :renderable
|
||||||
x :x
|
x :x
|
||||||
y :y} thing]
|
y :y} thing]
|
||||||
|
(when renderable
|
||||||
|
(js/console.log "Rendering thing: " x y)
|
||||||
(set! (.. renderable -x) x)
|
(set! (.. renderable -x) x)
|
||||||
(set! (.. renderable -y) y)))))
|
(set! (.. renderable -y) y))))))
|
||||||
|
|
||||||
(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)}))
|
||||||
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}
|
||||||
:attack-speed 0.66
|
|
||||||
:meta {:name "Player"
|
|
||||||
:race race/human
|
|
||||||
:class class/priest}
|
|
||||||
:sprite "https://pixijs.com/assets/bunny.png"
|
|
||||||
:speed 10
|
|
||||||
:renderable nil}
|
|
||||||
:elapsed 0
|
:elapsed 0
|
||||||
:outbox []
|
:outbox []
|
||||||
:entities {}})
|
:entities {}
|
||||||
|
:players {}})
|
||||||
width (.-width js/window.screen)
|
width (.-width js/window.screen)
|
||||||
height (.-height js/window.screen)
|
height (.-height js/window.screen)
|
||||||
stage (.-stage app)
|
stage (.-stage app)
|
||||||
@@ -102,6 +101,11 @@
|
|||||||
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}
|
||||||
|
sb-callback (fn [v _] (swap! state update-in [:player :keymap] assoc :lmb v))
|
||||||
|
sb (entity/player-shoot-box
|
||||||
|
entity-layer
|
||||||
|
(partial sb-callback true)
|
||||||
|
(partial sb-callback false))
|
||||||
websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws"))
|
websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws"))
|
||||||
(.addEventListener "open" #(go-loop []
|
(.addEventListener "open" #(go-loop []
|
||||||
(when-let [msg (<! tx-chan)]
|
(when-let [msg (<! tx-chan)]
|
||||||
@@ -121,15 +125,4 @@
|
|||||||
(.addChild world-layer) ; Bottom of the layer stack
|
(.addChild world-layer) ; Bottom of the layer stack
|
||||||
(.addChild entity-layer) ; Middle of the layer stack
|
(.addChild entity-layer) ; Middle of the layer stack
|
||||||
(.addChild ui-layer)) ; Top of the layer stack
|
(.addChild ui-layer)) ; Top of the layer stack
|
||||||
(let [e (merge {:x (-> width (/ 2) (int))
|
(.. app -ticker (add (partial ticker app state layers sb rx-chan tx-chan))))))))
|
||||||
:y (-> height (/ 2) (int))}
|
|
||||||
(@state :player))
|
|
||||||
p (entity/render entity-layer e)
|
|
||||||
sb-callback (fn [v _] (swap! state update-in [:player :keymap] assoc :lmb v))
|
|
||||||
sb (entity/player-shoot-box
|
|
||||||
entity-layer
|
|
||||||
(partial sb-callback true)
|
|
||||||
(partial sb-callback false))
|
|
||||||
player (assoc e :renderable p :shootbox sb)]
|
|
||||||
(swap! state update-in [:player] merge player)
|
|
||||||
(.. app -ticker (add (partial ticker app state layers rx-chan tx-chan)))))))))
|
|
||||||
|
|||||||
@@ -2,33 +2,41 @@
|
|||||||
(:require
|
(:require
|
||||||
[frontend.il.entity :as entity]
|
[frontend.il.entity :as entity]
|
||||||
[cljs.core.async :as async]
|
[cljs.core.async :as async]
|
||||||
[il.common.velocity :as v]))
|
[il.common.math :as ilmath]))
|
||||||
|
|
||||||
(defn apply-velocity [e dt]
|
(defn apply-velocity [e dt]
|
||||||
(if (contains? e :velocity)
|
(if (contains? e :velocity)
|
||||||
(let [{x :x y :y vel :velocity} e
|
(let [{x :x y :y vel :velocity} e
|
||||||
{vx :x vy :y} vel
|
{vx :x vy :y} vel
|
||||||
dtvx (* dt vx)
|
dtvx (Math/floor (* dt vx))
|
||||||
dtvy (* dt vy)]
|
dtvy (Math/floor (* dt vy))]
|
||||||
(assoc e :x (+ x dtvx) :y (+ y dtvy)))
|
(assoc e :x (+ x dtvx) :y (+ y dtvy)))
|
||||||
e))
|
e))
|
||||||
|
|
||||||
(defn apply-renderable [e layers]
|
(defn apply-renderable [e layers]
|
||||||
(if-not (contains? e :renderable)
|
(if (and (nil? (e :renderable)) (e :sprite))
|
||||||
(let [{entity-layer :entity-layer} layers
|
(let [{entity-layer :entity-layer} layers
|
||||||
renderable (entity/render entity-layer e)]
|
renderable (entity/render entity-layer e)]
|
||||||
(assoc e :renderable renderable))
|
(assoc e :renderable renderable))
|
||||||
e))
|
e))
|
||||||
|
|
||||||
|
|
||||||
(defn apply-server-position [e]
|
(defn apply-server-position [e]
|
||||||
(let [{:keys [x y tx ty]} e
|
(let [{:keys [x y tx ty]} e
|
||||||
speed (get e :speed 15)
|
speed (get e :speed 15)
|
||||||
|
min-distance-for-update 1
|
||||||
has-server-pos (not (and (nil? tx) (nil? ty)))
|
has-server-pos (not (and (nil? tx) (nil? ty)))
|
||||||
has-actual-pos (not (and (nil? x) (nil? y)))]
|
has-actual-pos (not (and (nil? x) (nil? y)))
|
||||||
|
velocityless-entity (dissoc e :velocity)]
|
||||||
(cond
|
(cond
|
||||||
(and has-server-pos (not has-actual-pos)) (assoc e :x tx :y ty)
|
; If the position given by the server is the same as the current position, do nothing
|
||||||
(and has-server-pos has-actual-pos) (assoc e :velocity (v/velocity-for x y tx ty speed))
|
(and has-server-pos (= x tx) (= y ty)) velocityless-entity
|
||||||
|
; When the entity has a rendered position, and a new server position
|
||||||
|
(and has-server-pos has-actual-pos) (let [delta (ilmath/euclidean-distance x y tx ty)]
|
||||||
|
(if (> delta min-distance-for-update)
|
||||||
|
(assoc velocityless-entity :velocity (ilmath/velocity-for x y tx ty speed))
|
||||||
|
velocityless-entity))
|
||||||
|
; When the entity has no rendered position, and a new server position
|
||||||
|
has-server-pos (assoc velocityless-entity :x tx :y ty)
|
||||||
:else e)))
|
:else e)))
|
||||||
|
|
||||||
(defn apply-player-shoot [state mouse-pos]
|
(defn apply-player-shoot [state mouse-pos]
|
||||||
@@ -36,11 +44,13 @@
|
|||||||
(< (+ (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 [{x :x y :y} (state :player)]
|
||||||
(-> state
|
(-> state
|
||||||
(update :outbox conj {:type "shoot"
|
(update :outbox conj {:type "shoot"
|
||||||
|
:player {:x x :y y}
|
||||||
:x (.-x mouse-pos)
|
:x (.-x mouse-pos)
|
||||||
:y (.-y mouse-pos)})
|
:y (.-y mouse-pos)})
|
||||||
(assoc-in [:player :last-attack] (js/Date.now)))
|
(assoc-in [:player :last-attack] (js/Date.now))))
|
||||||
state))
|
state))
|
||||||
|
|
||||||
(defn apply-player-position [state send-interval]
|
(defn apply-player-position [state send-interval]
|
||||||
@@ -54,23 +64,26 @@
|
|||||||
(update :outbox conj {:type "position" :x x :y y}))
|
(update :outbox conj {:type "position" :x x :y y}))
|
||||||
state)))
|
state)))
|
||||||
|
|
||||||
;; TODO: Cleanup entities somehow
|
(defn update-state [state key dt layers]
|
||||||
(defn update-entities [state dt layers]
|
(let [{v key} state
|
||||||
(let [{entities :entities} state
|
_ (js/console.log (clj->js v))
|
||||||
new-entities (update-vals entities #(-> %
|
new-values (update-vals v #(-> %
|
||||||
(apply-server-position)
|
(apply-server-position)
|
||||||
(apply-renderable layers)
|
(apply-renderable layers)
|
||||||
(apply-velocity dt)))]
|
(apply-velocity dt)))]
|
||||||
(assoc state :entities new-entities)))
|
(assoc state key new-values)))
|
||||||
|
|
||||||
(defn update-player [state dt send-interval layers mouse-pos]
|
(defn update-player [state dt send-interval layers mouse-pos sb]
|
||||||
(let [{player :player} state
|
(let [{player :player} state
|
||||||
updated-player (-> player
|
updated-player (-> player
|
||||||
(apply-renderable layers)
|
(apply-renderable layers)
|
||||||
|
(assoc :shootbox sb)
|
||||||
(apply-velocity dt))]
|
(apply-velocity dt))]
|
||||||
|
(if-not (and (nil? player) (nil? (player :renderable)))
|
||||||
(-> (assoc state :player updated-player)
|
(-> (assoc state :player updated-player)
|
||||||
(apply-player-position send-interval)
|
(apply-player-position send-interval)
|
||||||
(apply-player-shoot mouse-pos))))
|
(apply-player-shoot mouse-pos))
|
||||||
|
(update state :outbox conj {:type "request-init"}))))
|
||||||
|
|
||||||
(defn- deep-merge [& maps]
|
(defn- deep-merge [& maps]
|
||||||
(apply merge-with
|
(apply merge-with
|
||||||
@@ -83,14 +96,27 @@
|
|||||||
(defn update-from-server [state rx-chan]
|
(defn update-from-server [state rx-chan]
|
||||||
(loop [state-acc state
|
(loop [state-acc state
|
||||||
{:keys [type] :as msg} (async/poll! rx-chan)]
|
{:keys [type] :as msg} (async/poll! rx-chan)]
|
||||||
(if (and (not (nil? msg)) (= type "sync"))
|
(if-not (nil? msg)
|
||||||
(let [entities (msg :entities)
|
(cond
|
||||||
|
(= type "init") (update state-acc :player merge (dissoc msg :type))
|
||||||
|
(= type "sync") (let [entities (msg :entities)
|
||||||
|
players (if-not (nil? (get-in state-acc [:player :id]))
|
||||||
|
(dissoc (msg :players) (get-in state-acc [:player :id]))
|
||||||
|
{})
|
||||||
state-entities (state-acc :entities)
|
state-entities (state-acc :entities)
|
||||||
|
state-players (state-acc :players)
|
||||||
tx-entities (update-vals entities (fn [e] {:sprite (:sprite e)
|
tx-entities (update-vals entities (fn [e] {:sprite (:sprite e)
|
||||||
:tx (:x e)
|
:tx (:x e)
|
||||||
:ty (:y e)}))
|
:ty (:y e)}))
|
||||||
merged-entities (deep-merge state-entities tx-entities)]
|
tx-players (update-vals players (fn [e] {:sprite (:sprite e)
|
||||||
|
:tx (:x e)
|
||||||
|
:ty (:y e)}))
|
||||||
|
merged-entities (deep-merge state-entities tx-entities)
|
||||||
|
merged-players (deep-merge state-players tx-players)]
|
||||||
(recur
|
(recur
|
||||||
(assoc state-acc :entities merged-entities)
|
(assoc state-acc
|
||||||
|
:entities merged-entities
|
||||||
|
:players merged-players)
|
||||||
(async/poll! rx-chan)))
|
(async/poll! rx-chan)))
|
||||||
|
:else state-acc)
|
||||||
state-acc)))
|
state-acc)))
|
||||||
|
|||||||
1
src/il/common/constant.cljc
Normal file
1
src/il/common/constant.cljc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
(ns il.common.constant)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(ns il.common.velocity)
|
(ns il.common.math)
|
||||||
|
|
||||||
(defn velocity-for [x y tx ty speed]
|
(defn velocity-for [x y tx ty speed]
|
||||||
(let [dx (- tx x)
|
(let [dx (- tx x)
|
||||||
@@ -9,3 +9,6 @@
|
|||||||
(if (zero? h)
|
(if (zero? h)
|
||||||
{:x 0.0 :y 0.0}
|
{:x 0.0 :y 0.0}
|
||||||
{:x vx :y vy})))
|
{:x vx :y vy})))
|
||||||
|
|
||||||
|
(defn euclidean-distance [x1 y1 x2 y2]
|
||||||
|
(Math/sqrt (+ (Math/pow (- x2 x1) 2) (Math/pow (- y2 y1) 2))))
|
||||||
@@ -1 +0,0 @@
|
|||||||
(ns il.constant)
|
|
||||||
@@ -5,33 +5,41 @@
|
|||||||
[compojure.route :as route]
|
[compojure.route :as route]
|
||||||
[clojure.core.async :as async :refer [<! >! go-loop]]
|
[clojure.core.async :as async :refer [<! >! go-loop]]
|
||||||
[hiccup.core :as h]
|
[hiccup.core :as h]
|
||||||
|
[il.player :as p]
|
||||||
[il.state :as s]
|
[il.state :as s]
|
||||||
[il.json :as j]
|
[il.json :as j]
|
||||||
[il.handler :as handler]
|
[il.handler :as handler]
|
||||||
[il.system.movement :as movement]))
|
[il.system.movement :as movement]))
|
||||||
|
|
||||||
(defn ws-handler [state state-chan player-id]
|
(defn ws-handler [state state-chan player-id]
|
||||||
|
(println "Starting session for " 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 :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-not (contains? (@state :players) player-id)
|
||||||
|
(do (s/change state-chan update :players assoc player-id {:out out :in in :err err
|
||||||
|
:x 0 :y 0
|
||||||
|
:initialized false
|
||||||
|
:data (merge p/default-player {:id player-id})})
|
||||||
|
(recur))
|
||||||
(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")
|
||||||
|
state @state]
|
||||||
(cond
|
(cond
|
||||||
(= type "position") (handler/handle-position @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 "shoot") (handler/handle-shoot state state-chan player-id msg)
|
||||||
(= type "invalid") (>! out "Hello World!"))
|
(= type "request-init") (handler/handle-request-init state state-chan player-id msg)
|
||||||
|
(= type "invalid") (>! out "Invalid command!"))
|
||||||
(println msg)
|
(println msg)
|
||||||
(println @state))
|
(println state)
|
||||||
(recur))
|
(recur))
|
||||||
(do
|
(do
|
||||||
(s/change state-chan update :players dissoc player-id)
|
(s/change state-chan update :players dissoc player-id)
|
||||||
(println "Closed: " player-id))))))
|
(println "Closed: " player-id)))))))
|
||||||
|
|
||||||
(defn index-handler [_]
|
(defn index-handler [_]
|
||||||
(h/html
|
(h/html
|
||||||
@@ -53,7 +61,7 @@
|
|||||||
(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 for too long with events 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)
|
||||||
@@ -68,15 +76,32 @@
|
|||||||
system-state (reduce (fn [state system] (system state))
|
system-state (reduce (fn [state system] (system state))
|
||||||
event-state
|
event-state
|
||||||
(event-state :systems))
|
(event-state :systems))
|
||||||
entities (:entities @state)
|
updated-state (swap! state conj system-state)
|
||||||
players (:players @state)]
|
entities (updated-state :entities)
|
||||||
(swap! state conj system-state)
|
players (updated-state :players)]
|
||||||
(doseq [{out :out} (vals players)]
|
(doseq [{:keys [initialized data out] :as player} (vals players)]
|
||||||
(>! out (j/to-json {:type "sync"
|
(let [player-id (data :id)]
|
||||||
:entities entities}))))
|
(println player)
|
||||||
|
(when-not (nil? out)
|
||||||
|
(when-not initialized
|
||||||
|
(let [coords (select-keys player [:x :y])
|
||||||
|
data-to-send (conj data coords)
|
||||||
|
msg (assoc data-to-send :type "init")]
|
||||||
|
(println "Initializing " player-id)
|
||||||
|
(async/put! out (j/to-json msg))
|
||||||
|
(s/change state-chan update-in [:players player-id] assoc :initialized true)))
|
||||||
|
(let [players (update-vals players (fn [e] (-> e
|
||||||
|
(select-keys [:x :y :data])
|
||||||
|
(#(merge (dissoc % :data) (get % :data))))))
|
||||||
|
players-without-player-id (dissoc players player-id)] ; Strip the selected player from the update
|
||||||
|
(async/put! out (j/to-json {:type "sync"
|
||||||
|
:entities entities
|
||||||
|
:players players-without-player-id})))))))
|
||||||
|
|
||||||
(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 []
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
(ns il.handler
|
(ns il.handler
|
||||||
(:require [il.state :as s]
|
(:require [il.state :as s]
|
||||||
[il.common.velocity :as v]))
|
[il.common.math :as ilmath]))
|
||||||
|
|
||||||
(defn handle-position [_ state-chan player-id {x :x y :y}]
|
(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))
|
(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-request-init [_ state-chan player-id _]
|
||||||
|
(s/change state-chan update-in [:players player-id] assoc :initialized false))
|
||||||
|
|
||||||
|
(defn handle-shoot [_ state-chan player-id msg]
|
||||||
(let [bullet-id (random-uuid)
|
(let [bullet-id (random-uuid)
|
||||||
player (get-in state [:players player-id])
|
; player (get-in state [:players player-id])
|
||||||
|
{tx :x ty :y player :player} msg
|
||||||
{x :x y :y} player
|
{x :x y :y} player
|
||||||
{tx :x ty :y} msg
|
speed 50 ; TODO: Get projectile speed from player weapon
|
||||||
speed 25 ; TODO: Get projectile speed from player weapon
|
velocity (ilmath/velocity-for x y tx ty speed)
|
||||||
velocity (v/velocity-for x y tx ty speed)
|
|
||||||
bullet {:sprite "/sprite/projectile.png" ; TODO: Render sprite based on player weapon
|
bullet {:sprite "/sprite/projectile.png" ; TODO: Render sprite based on player weapon
|
||||||
:x x
|
:x x
|
||||||
:y y
|
:y y
|
||||||
:speed speed
|
:speed speed
|
||||||
|
:player-id player-id
|
||||||
:velocity velocity}]
|
:velocity velocity}]
|
||||||
(s/change state-chan update :entities assoc bullet-id bullet)))
|
(s/change state-chan update :entities assoc bullet-id bullet)))
|
||||||
|
|||||||
12
src/il/player.clj
Normal file
12
src/il/player.clj
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
(ns il.player
|
||||||
|
(:require
|
||||||
|
[il.common.race :as race]
|
||||||
|
[il.common.class :as class]))
|
||||||
|
|
||||||
|
(def default-player
|
||||||
|
{:attack-speed 0.66
|
||||||
|
:meta {:name "Player"
|
||||||
|
:race race/human
|
||||||
|
:class class/priest}
|
||||||
|
:sprite "https://pixijs.com/assets/bunny.png"
|
||||||
|
:speed 10})
|
||||||
Reference in New Issue
Block a user