This commit is contained in:
2026-07-11 23:13:31 -06:00
parent 445863ee41
commit cd5b99f150
5 changed files with 97 additions and 64 deletions

View File

@@ -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)))))))))

View File

@@ -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)))))

View File

@@ -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))))

24
src/il/class.clj Normal file
View File

@@ -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)))

View File

@@ -1,4 +1 @@
(ns il.constant)
(def screen-width 800)
(def screen-height 600)