rpg-engine/src/ch/lyrion/rpg-engine/tilemap.clj

87 lines
2.8 KiB
Clojure

(ns ch.lyrion.rpg-engine.tilemap
(:require [clojure.java.io :as io]
[tile-soup.core :as ts]
[ch.lyrion.rpg-engine.validation :as validation]
[mount.core :refer [defstate]]))
(defn- load-raw-tileset [filename]
(->> filename
io/resource
slurp
(ts/parse :tile-soup.tileset/tileset)))
(defn- tileset-basemap [{:keys [attrs]}]
{:tileset/name (-> attrs :name keyword)
:tiles/width (:tilewidth attrs)
:tiles/height (:tileheight attrs)
:tiles/count (:tilecount attrs)})
(defn- tileset-tiles [tileset-map [tile & tiles]]
(case (:tag tile)
:tile (recur (update tileset-map :tiles conj
{:tile/id (-> tile :attrs :id)
:tile/width (-> tile :content first :attrs :width)
:tile/height (-> tile :content first :attrs :height)
:tile/src (-> tile :content first :attrs :source)})
tiles)
nil tileset-map
(recur tileset-map tiles)))
(defn- load-tileset* [filename]
{:post [(validation/validate :tileset %)]}
(let [raw-tileset (load-raw-tileset filename)]
(-> raw-tileset
tileset-basemap
(tileset-tiles (:content raw-tileset)))))
(defstate tilesets
:start (atom {}))
(defn load-tileset [filename]
(let [tileset (load-tileset* filename)]
(swap! tilesets assoc (:tileset/name tileset) tileset)
tileset))
;; Map
(defn- load-raw-tilemap [filename]
(->> filename
io/resource
slurp
ts/parse))
(defn- tilemap-basemap [{:keys [attrs]}]
{:map/width (:width attrs)
:map/height (:height attrs)
:tiles/width (:tilewidth attrs)
:tiles/height (:tileheight attrs)})
(defn- tilemap-layer [tilemap-map [entry & entries]]
(case (:tag entry)
:tileset (recur (update tilemap-map :map/tilesets conj
{:tileset/start-index (-> entry :attrs :firstgid)
:tileset/name (:tileset/name (load-tileset (-> entry :attrs :source)))})
entries)
:layer (recur (update tilemap-map :map/layers conj
{:layer/id (-> entry :attrs :id)
:layer/name (-> entry :attrs :name)
:layer/width (-> entry :attrs :width)
:layer/height (-> entry :attrs :height)
:layer/tiles (->> entry :content first :content first (map ts/tile-id->map))})
entries)
nil tilemap-map))
(defn load-tilemap* [filename]
{:post [(validation/validate :tilemap %)]}
(let [raw-tilemap (load-raw-tilemap filename)]
(-> raw-tilemap
tilemap-basemap
(tilemap-layer (:content raw-tilemap)))))
(defstate tilemap
:start (atom {}))
(defn load-tilemap [filename]
(let [tilemap-map (load-tilemap* filename)]
(reset! tilemap tilemap-map)
tilemap-map))