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