diff --git a/src/frontend/il/app.cljs b/src/frontend/il/app.cljs index 25f03b1..a81ae75 100644 --- a/src/frontend/il/app.cljs +++ b/src/frontend/il/app.cljs @@ -3,50 +3,9 @@ [clojure.string :as str] ["pixi.js" :as pixi] [goog.dom :as dom] - [cljs.math :as math] [frontend.il.entity :as entity] [frontend.il.update :as update])) -(def websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws")) - (.addEventListener "open" #(println "Websocket opened.")) - (.addEventListener "message" #(println "Received message​ " (.-data %))) - (.addEventListener "close" #(println "Websocket closed.")))) - -(def base-player {:meta {:type "player" - :name "Player" - :race "Human" - :class "Priest"} - :sprite "https://pixijs.com/assets/bunny.png" - :speed 10 - :renderable nil}) - -(defn add-entity [state entity-id entity] - (let [id (swap! entity-id inc)] - (swap! state update-in [:entities] conj {(-> id str keyword) entity}))) - -(defn on-shoot [state entity-id entity-layer player-sprite e] - (.log js/console e) - (let [speed 15 - image "/sprite/projectile.png" - start-x (.-x player-sprite) - start-y (.-y player-sprite) - position (.toLocal ^js entity-layer (.-global e)) - 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)] - (.log js/console "tx " target-x " ty " target-y " dx " dx " dy " dy " h " h) - (.log js/console "sx " start-x " sy " start-y) - (.log js/console player-sprite) - (add-entity state entity-id {:sprite image - :hyp h - :x start-x - :y start-y - :velocity {:x vx :y vy}}))) - (defn- velocity-for-key-down [key] (case key "w" -1 @@ -72,12 +31,16 @@ (js/window.addEventListener "keydown" (partial handle-key state velocity-for-key-down)) (js/window.addEventListener "keyup" (partial handle-key state (fn [_] 0)))) -(defn ticker [app state layers t] +(defn ticker [app state layers entity-id t] (let [dt (.-deltaTime t) - {world-layer :world-layer} layers + {world-layer :world-layer + entity-layer :entity-layer} layers + global-mouse-pos (.. app -renderer -events -pointer -global) + entity-relative-mouse-pos (.toLocal ^js entity-layer global-mouse-pos) + _ (println @state) {:keys [player entities]} (-> @state (update/update-entities dt layers) - (update/update-player dt layers) + (update/update-player dt layers entity-id entity-relative-mouse-pos) (->> (swap! state merge))) sx (- (/ (.. app -screen -width) 2) (player :x)) sy (- (/ (.. app -screen -height) 2) (player :y)) @@ -100,9 +63,19 @@ (defn init [] (let [app (doto (pixi/Application.) (.init {:resizeTo js/window :autoDensity true :resolution (.-devicePixelRatio js/window)})) - state (atom {:player {:velocity {:x 0 :y 0} :keymap {:w 0 :a 0 :s 0 :d 0}} - :entities {}}) entity-id (atom 1) + state (atom {:player {:velocity {:x 0 :y 0} + :keymap {:w 0 :a 0 :s 0 :d 0 :lmb 0} + :last-attack -1 + :attack-speed 666 + :meta {:type "player" + :name "Player" + :race "Human" + :class "Priest"} + :sprite "https://pixijs.com/assets/bunny.png" + :speed 10 + :renderable nil} + :entities {(-> entity-id (swap! inc) (keyword)) {:x 500 :y 500 :sprite "https://pixijs.com/assets/bunny.png"}}}) width (.-width js/window.screen) height (.-height js/window.screen) stage (.-stage app) @@ -111,22 +84,30 @@ ui-layer (pixi/Container.) layers {:entity-layer entity-layer :world-layer world-layer - :ui-layer ui-layer}] + :ui-layer ui-layer} + websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws")) + (.addEventListener "open" #(println "Websocket opened.")) + (.addEventListener "message" #(println "Received message​ " (.-data %))) + (.addEventListener "close" #(println "Websocket closed.")))] + (.. app (init #js {:width width :height height :backgroundColor 0x222}) (then (fn [_] (dom/appendChild (dom/getElement "app") (.-canvas app)) (init-input-handlers state) - (add-entity state entity-id {:x 500 :y 500 :sprite "https://pixijs.com/assets/bunny.png"}) (-> stage (.addChild world-layer) ; Bottom of the layer stack (.addChild entity-layer) ; Middle of the layer stack (.addChild ui-layer)) ; Top of the layer stack (let [e (merge {:x (-> width (/ 2) (int)) :y (-> height (/ 2) (int))} - base-player) + (@state :player)) p (entity/render entity-layer e) - sb (entity/player-shoot-box entity-layer (partial on-shoot state entity-id entity-layer p)) + 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))))))))) + (.. app -ticker (add (partial ticker app state layers entity-id))))))))) diff --git a/src/frontend/il/entity.cljs b/src/frontend/il/entity.cljs index 3e8139a..f8acc0c 100644 --- a/src/frontend/il/entity.cljs +++ b/src/frontend/il/entity.cljs @@ -15,16 +15,17 @@ (set! (.. entity-sprite -anchor -y) 0.5) (set! (.. entity-sprite -x) x) (set! (.. entity-sprite -y) y) - (.addChild layer entity-sprite)))) + (.addChild ^js layer entity-sprite)))) entity-sprite)) -(defn player-shoot-box [layer callback] +(defn player-shoot-box [layer down-callback up-callback] (let [g (pixi/Graphics.) width (- (.-width js/window.screen) 80) height (- (.-height js/window.screen) 80)] (set! (.-eventMode g) "static") (-> g - (.on "pointertap" callback) + (.on "pointerdown" down-callback) + (.on "pointerup" up-callback) (.rect (/ (- width) 2) (/ (- height) 2) width height) (.fill #js {:color "red" :alpha 0.1}) - (->> (.addChild layer))))) + (->> (.addChild ^js layer))))) diff --git a/src/frontend/il/update.cljs b/src/frontend/il/update.cljs index f53f505..4f20f39 100644 --- a/src/frontend/il/update.cljs +++ b/src/frontend/il/update.cljs @@ -18,16 +18,46 @@ (assoc e :renderable renderable)) e)) +(defn apply-player-shoot [state entity-id mouse-pos] + (if (and (get-in state [:player :keymap :lmb] false) + (< (+ (get-in state [:player :last-attack] -1) + (get-in state [:player :attack-speed] 888)) + (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) + e {:sprite image + :hyp h + :x start-x + :y start-y + :velocity {:x vx :y vy}}] + (-> state + (assoc-in [:entities (keyword (str eid))] e) + (assoc-in [:player :last-attack] (js/Date.now)))) + state)) + (defn update-entities [state dt layers] (let [{entities :entities} state new-entities (update-vals entities #(-> % - (apply-renderable layers) - (apply-velocity dt)))] + (apply-renderable layers) + (apply-velocity dt)))] (assoc state :entities new-entities))) -(defn update-player [state dt layers] +(defn update-player [state dt layers entity-id mouse-pos] (let [{player :player} state updated-player (-> player - (apply-renderable layers) - (apply-velocity dt))] - (assoc state :player updated-player))) + (apply-renderable layers) + (apply-velocity dt))] + (-> (assoc state :player updated-player) + (apply-player-shoot entity-id mouse-pos)))) diff --git a/src/il/class.clj b/src/il/class.clj new file mode 100644 index 0000000..927ac3f --- /dev/null +++ b/src/il/class.clj @@ -0,0 +1,24 @@ +(ns il.class) + +(def priest {:name "priest" + :stats { :atkspeed 0.5 }}) +(def warden "warden") +(def sorcerer "sorcerer") +(def magician "magician") +(def thief "thief") +(def ranger "ranger") +(def artificer "artificer") +(def corsair "corsair") +(def astromancer "astromancer") + +(def valid-class? [class] + (let [classes [priest + warden + sorcerer + magician + thief + ranger + artificer + corsair + astromancer]] + (contains? classes class))) diff --git a/src/il/constant.clj b/src/il/constant.clj index 9700e0b..a75689a 100644 --- a/src/il/constant.clj +++ b/src/il/constant.clj @@ -1,4 +1 @@ (ns il.constant) - -(def screen-width 800) -(def screen-height 600)