MOVEMENT
This commit is contained in:
BIN
resources/public/sprite/projectile.png
Normal file
BIN
resources/public/sprite/projectile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 302 B |
@@ -1,31 +1,111 @@
|
|||||||
(ns frontend.il.app
|
(ns frontend.il.app
|
||||||
(:require ["pixi.js" :as pixi]
|
(:require
|
||||||
[goog.dom :as dom]))
|
[clojure.string :as str]
|
||||||
|
["pixi.js" :as pixi]
|
||||||
|
[goog.dom :as dom]
|
||||||
|
[frontend.il.entity :as entity]))
|
||||||
|
|
||||||
|
(def app
|
||||||
|
(pixi/Application.))
|
||||||
|
|
||||||
|
(def stage
|
||||||
|
(.-stage app))
|
||||||
|
|
||||||
(def websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws"))
|
(def websocket (doto (js/WebSocket. (str "ws://" js/location.host "/ws"))
|
||||||
(.addEventListener "open" #(println "Websocket opened."))
|
(.addEventListener "open" #(println "Websocket opened."))
|
||||||
(.addEventListener "message" #(println "Received message:" (.-data %)))
|
(.addEventListener "message" #(println "Received message " (.-data %)))
|
||||||
(.addEventListener "close" #(println "Websocket closed."))))
|
(.addEventListener "close" #(println "Websocket closed."))))
|
||||||
|
|
||||||
(defn ticker [game ticker-object]
|
(def base-player {:meta {:type "player"
|
||||||
(let [bunny (game :bunny)]
|
:name "Player"
|
||||||
(set! (.-rotation bunny) (+ (.-rotation bunny) 0.01))))
|
:race "Human"
|
||||||
|
:class "Priest"}
|
||||||
|
:sprite "https://pixijs.com/assets/bunny.png"
|
||||||
|
:speed 10
|
||||||
|
:renderable nil})
|
||||||
|
|
||||||
|
(def world-layer
|
||||||
|
(pixi/Container.))
|
||||||
|
|
||||||
|
(def entity-layer
|
||||||
|
(pixi/Container.))
|
||||||
|
|
||||||
|
(def entity-id (atom 1))
|
||||||
|
(def state (atom {:player {:movement {:x 0 :y 0} :keymap {:w 0 :a 0 :s 0 :d 0}}
|
||||||
|
:entities {}}))
|
||||||
|
|
||||||
|
(def lerp 0.1)
|
||||||
|
|
||||||
|
(defn add-entity [entity]
|
||||||
|
(let [id (swap! entity-id inc)]
|
||||||
|
(swap! state update-in [:entities] conj {(-> id str keyword) entity})))
|
||||||
|
|
||||||
|
(defn- velocity-for-key-down [key]
|
||||||
|
(case key
|
||||||
|
"w" -1
|
||||||
|
"s" 1
|
||||||
|
"a" -1
|
||||||
|
"d" 1
|
||||||
|
{}))
|
||||||
|
|
||||||
|
(defn handle-key [func event]
|
||||||
|
(let [key (-> event .-key str/lower-case)
|
||||||
|
vel (func key)]
|
||||||
|
(swap! state update-in [:player :keymap] assoc (keyword key) vel)
|
||||||
|
(print @state)
|
||||||
|
(let [{left :d
|
||||||
|
right :a
|
||||||
|
up :w
|
||||||
|
down :s} (get-in @state [:player :keymap])]
|
||||||
|
(swap! state update-in [:player :movement] assoc :x (+ left right) :y (+ up down)))))
|
||||||
|
|
||||||
|
(defn init-input-handlers []
|
||||||
|
(js/window.addEventListener "keydown" (partial handle-key velocity-for-key-down))
|
||||||
|
(js/window.addEventListener "keyup" (partial handle-key (fn [_] 0))))
|
||||||
|
|
||||||
|
(defn ticker [t]
|
||||||
|
(let [dt (.-deltaTime t)
|
||||||
|
{entities :entities
|
||||||
|
player :player} @state]
|
||||||
|
(doseq [k (keys entities)]
|
||||||
|
(let [{:keys [x y renderable]
|
||||||
|
:as e} (entities k)]
|
||||||
|
(if-not (nil? renderable)
|
||||||
|
(do
|
||||||
|
(set! (.. renderable -x) x)
|
||||||
|
(set! (.. renderable -y) y))
|
||||||
|
(let [renderable (entity/render {:layer entity-layer} e)]
|
||||||
|
(swap! state update-in [:entities k] assoc :renderable renderable)))))
|
||||||
|
(when-not (nil? (:renderable player))
|
||||||
|
(let [{dx :x dy :y} (:movement player)
|
||||||
|
{renderable :renderable
|
||||||
|
speed :speed} player
|
||||||
|
new-x (+ (* dt speed dx) (.-x renderable))
|
||||||
|
new-y (+ (* dt speed dy) (.-y renderable))]
|
||||||
|
(set! (.. renderable -x) new-x)
|
||||||
|
(set! (.. renderable -y) new-y)
|
||||||
|
(swap! state update-in [:player] assoc :x new-x :y new-y)
|
||||||
|
(let [sx (- (/ (.. app -screen -width) 2) new-x)
|
||||||
|
sy (- (/ (.. app -screen -height) 2) new-y)]
|
||||||
|
(set! (.. world-layer -x) sx)
|
||||||
|
(set! (.. world-layer -y) sy))))))
|
||||||
|
|
||||||
(defn init []
|
(defn init []
|
||||||
(let [app (pixi/Application.)
|
(let [width (.-width js/window.screen)
|
||||||
width (.-width js/window.screen)
|
|
||||||
height (.-height js/window.screen)]
|
height (.-height js/window.screen)]
|
||||||
(.. app
|
(.. app
|
||||||
(init #js {:width width :height height :backgroundColor 0x1099bb})
|
(init #js {:width width :height height :backgroundColor 0x222})
|
||||||
(then (fn [_]
|
(then (fn [_]
|
||||||
(dom/appendChild (dom/getElement "app") (.-canvas app))
|
(dom/appendChild (dom/getElement "app") (.-canvas app))
|
||||||
(let [texture (.. pixi -Assets (load "https://www.sprite-ai.art/sprite-img/99fa1574-fc52-41a6-ab76-1bd75b5dc4b3/16x16-pixel-art-sprite-cookie-shaped-like-a-32x32-pixel-art-90b4.png"))]
|
(init-input-handlers)
|
||||||
(.. texture
|
(add-entity {:x 500 :y 500 :sprite "https://pixijs.com/assets/bunny.png"})
|
||||||
(then (fn [loaded-texture]
|
(-> (.-stage app)
|
||||||
(let [bunny (pixi/Sprite. loaded-texture)]
|
(.addChild world-layer)
|
||||||
(set! (.. bunny -anchor -x) 0.5)
|
(.addChild entity-layer))
|
||||||
(set! (.. bunny -anchor -y) 0.5)
|
(let [e (merge {:x (-> width (/ 2) (int))
|
||||||
(set! (.. bunny -x) (/ width 2))
|
:y (-> height (/ 2) (int))}
|
||||||
(set! (.. bunny -y) (/ height 2))
|
base-player)
|
||||||
(.. app -stage (addChild bunny))
|
p (entity/render {:layer entity-layer} e)
|
||||||
(.. app -ticker (add (partial ticker {:bunny bunny})))))))))))))
|
player (assoc e :renderable p)]
|
||||||
|
(swap! state update-in [:player] merge player)
|
||||||
|
(.. app -ticker (add ticker))))))))
|
||||||
|
|||||||
20
src/frontend/il/entity.cljs
Normal file
20
src/frontend/il/entity.cljs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
(ns frontend.il.entity
|
||||||
|
(:require ["pixi.js" :as pixi]))
|
||||||
|
|
||||||
|
(defn render [render-info entity]
|
||||||
|
(let [{x :x
|
||||||
|
y :y
|
||||||
|
sprite :sprite} entity
|
||||||
|
{^js layer :layer} render-info
|
||||||
|
entity-sprite (pixi/Sprite.)]
|
||||||
|
(print "Creating sprite: " sprite " for entity " entity)
|
||||||
|
(.. pixi -Assets
|
||||||
|
(load sprite)
|
||||||
|
(then (fn [loaded-texture]
|
||||||
|
(set! (.. entity-sprite -texture) loaded-texture)
|
||||||
|
(set! (.. entity-sprite -anchor -x) 0.5)
|
||||||
|
(set! (.. entity-sprite -anchor -y) 0.5)
|
||||||
|
(set! (.. entity-sprite -x) x)
|
||||||
|
(set! (.. entity-sprite -y) y)
|
||||||
|
(.. layer (addChild entity-sprite)))))
|
||||||
|
entity-sprite))
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
(ns il.constant)
|
(ns il.constant)
|
||||||
|
|
||||||
(def world-width 4096)
|
(def screen-width 800)
|
||||||
(def world-height 4096)
|
(def screen-height 600)
|
||||||
|
|
||||||
(def resources
|
|
||||||
["zinc" "iron" "titanium" "wood" "sulfur"])
|
|
||||||
|
|
||||||
(def min-resources 10)
|
|
||||||
(def max-resources 28)
|
|
||||||
|
|||||||
@@ -5,19 +5,8 @@
|
|||||||
[compojure.route :as route]
|
[compojure.route :as route]
|
||||||
[clojure.core.async :refer [<! >! go-loop]]
|
[clojure.core.async :refer [<! >! go-loop]]
|
||||||
[clojure.data.json :as json]
|
[clojure.data.json :as json]
|
||||||
[il.world :as w]
|
|
||||||
[il.constant :as consts]
|
|
||||||
[hiccup.core :as h]))
|
[hiccup.core :as h]))
|
||||||
|
|
||||||
(def world (-> {}
|
|
||||||
(w/generate-water consts/world-width consts/world-height)
|
|
||||||
(w/generate-resources
|
|
||||||
consts/resources
|
|
||||||
consts/min-resources
|
|
||||||
consts/max-resources
|
|
||||||
consts/world-width
|
|
||||||
consts/world-height)))
|
|
||||||
|
|
||||||
(defn ws-handler [_]
|
(defn ws-handler [_]
|
||||||
(go-websocket [in out err]
|
(go-websocket [in out err]
|
||||||
(go-loop []
|
(go-loop []
|
||||||
@@ -28,7 +17,7 @@
|
|||||||
(if-let [msg (<! in)]
|
(if-let [msg (<! in)]
|
||||||
(do
|
(do
|
||||||
(cond
|
(cond
|
||||||
(= msg "world") (>! out (json/write-str world)))
|
(= msg "world") (>! out "Hello World!"))
|
||||||
(println msg)
|
(println msg)
|
||||||
(recur))
|
(recur))
|
||||||
(println "Closed.")))))
|
(println "Closed.")))))
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
(ns il.world
|
|
||||||
(:require
|
|
||||||
[il.util :refer [rand-int-range]]
|
|
||||||
[clojure.math :as math]))
|
|
||||||
|
|
||||||
(defn- resource-size [amt]
|
|
||||||
(cond
|
|
||||||
(>= amt 4000) "huge"
|
|
||||||
(>= amt 2750) "large"
|
|
||||||
(>= amt 1500) "medium"
|
|
||||||
:else "small"))
|
|
||||||
|
|
||||||
(defn- in-water [water point]
|
|
||||||
(let [[x y] point]))
|
|
||||||
|
|
||||||
(defn- rand-int-range-seq [min max]
|
|
||||||
(repeatedly (partial rand-int-range min max)))
|
|
||||||
|
|
||||||
(def region-division 4)
|
|
||||||
|
|
||||||
;; I thought about using Perlin noise to generate the water, but I find it over kill.
|
|
||||||
;; Instead, we split the world width, world height by a "region size", and pick
|
|
||||||
;; a random coordinate in those to generate water.
|
|
||||||
(defn generate-water [world world-width world-height]
|
|
||||||
(let [region-width (/ world-width region-division)
|
|
||||||
region-height (/ world-height region-division)
|
|
||||||
water (reduce
|
|
||||||
(fn [water [xs ys]]
|
|
||||||
(let [rw (* region-width xs)
|
|
||||||
rh (* region-height ys)]
|
|
||||||
(if (< (rand) 0.25) ; Only generate water in 25% of regions
|
|
||||||
(let [[wx wy] [(rand-int-range (- rw region-width) rw)
|
|
||||||
(rand-int-range (- rh region-height) rh)]
|
|
||||||
spokes (rand-int-range 5 17) ; "spokes" are how many points around the initial water placement
|
|
||||||
points (reduce
|
|
||||||
(fn [points [angle radius]]
|
|
||||||
(let [sx (+ wx (* radius (math/cos angle)))
|
|
||||||
sy (+ wy (* radius (math/sin angle)))]
|
|
||||||
(conj points [(int sx) (int sy)])))
|
|
||||||
[]
|
|
||||||
(mapv vector
|
|
||||||
(sort (take spokes (rand-int-range-seq 0 (* math/PI 2))))
|
|
||||||
(take spokes (rand-int-range-seq 6 12))))]
|
|
||||||
(conj water (conj points (first points)))) ; Append first point to end of vector, to complete the polygon
|
|
||||||
water)))
|
|
||||||
[]
|
|
||||||
(for [xs (range 1 (inc region-division))
|
|
||||||
ys (range 1 (inc region-division))]
|
|
||||||
[xs ys]))]
|
|
||||||
(assoc world :water water)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn generate-resources [world resource-types min max world-width world-height]
|
|
||||||
(let [resources (reduce
|
|
||||||
(fn [resources [type amt]]
|
|
||||||
(reduce
|
|
||||||
(fn [resources _]
|
|
||||||
(let [x (rand-int-range 0 world-width)
|
|
||||||
y (rand-int-range 0 world-height)
|
|
||||||
amt (rand-int-range 1000 5000)
|
|
||||||
size (resource-size amt)]
|
|
||||||
(if (in-water (:water world) [x y])
|
|
||||||
resources
|
|
||||||
(conj resources [x y type amt size]))))
|
|
||||||
resources
|
|
||||||
(range amt)))
|
|
||||||
[]
|
|
||||||
(for [rt resource-types
|
|
||||||
amt (take
|
|
||||||
(count resource-types)
|
|
||||||
(repeatedly (partial rand-int-range min max)))]
|
|
||||||
[rt amt]))]
|
|
||||||
(assoc world :resources resources)))
|
|
||||||
Reference in New Issue
Block a user