fennel_love2d_experiments/two_player_cleaning_game/assets/gen_levels.bb
Travis Shears bbbe7bfe8a
move objects out of bg tiles
"
Press any key to quit" 10 10))
2026-04-19 21:25:08 +02:00

110 lines
4.4 KiB
Clojure
Executable file

#!/usr/bin/env bb
(ns gen-levels
(:require
[babashka.fs :as fs]
[clojure.pprint :refer [pprint]]
[clojure.data.xml :as xml]
[clojure.string :as str]
[clojure.java.io :as io])
(:import
'java.io.StringReader))
(defn load-tiled-xml-file [path]
(-> (slurp (io/reader path))
(str/replace #">\s+" ">")
(StringReader.)
(xml/parse)))
(defn parse-tile-set [tsx]
(->>
(:content tsx)
(filter #(= (:tag %) :tile))
(reduce (fn [acc tile]
(conj acc
{(Integer/parseInt (get-in tile [:attrs :id]))
(vec
(->> (:content tile)
(map :content)
(flatten)
(map :attrs)
(map #(select-keys % [:x :y :height :width]))
(map #(update-vals % (fn [v] (Math/round (Double/parseDouble v)))))))}))
{})))
(def walls-tsx (load-tiled-xml-file "./tiled/walls.tsx"))
(def objects-tsx (load-tiled-xml-file "./tiled/objects.tsx"))
;; (def colliders {:walls (parse-tile-set walls-tsx) :objects (parse-tile-set objects-tsx)})
;; (into {} (map (fn [[k v]]
;; [(transform-key k) v])
;; your-map))
(def colliders
"collider boxes by tile GID"
(let [walls (into {} (map (fn [[k v]] [(+ k 1) v]) (parse-tile-set walls-tsx)))
objects (into {} (map (fn [[k v]] [(+ k 21) v]) (parse-tile-set objects-tsx)))]
(merge walls objects)))
(def tutorial-map-tmx (load-tiled-xml-file "./tiled/tutorial.tmx"))
(def level-001-map-tmx (load-tiled-xml-file "./tiled/level_001.tmx"))
(defn parse-gid [gid]
(let [gid-long (Long/parseLong (str gid))
h-flip (bit-test gid-long 31) ; Bit 32 (horizontal flip)
v-flip (bit-test gid-long 30) ; Bit 31 (vertical flip)
d-flip (bit-test gid-long 29) ; Bit 30 (diagonal flip)
tile-id (bit-and gid-long 0x0FFFFFFF)] ; Clear top 4 bits to get actual tile ID
{:tile-id tile-id
:colliders (get colliders tile-id)
:h-flip h-flip
:v-flip v-flip
:d-flip d-flip}))
(defn parse-map
[map-tmx]
(let [tiles (-> (filter #(= (:tag %) :layer) (:content map-tmx))
first :content first :content first str/split-lines
(->>
(mapv #(str/split % #","))
(mapv (fn [row] (mapv parse-gid row)))))]
{:tiles
(vec (map-indexed
(fn [y row]
(vec (map-indexed
(fn [x tile] (conj {:x (* x 25) :y (* y 25)} tile))
row))) tiles))
:spawns
(let [spawns (first (filter #(= (get-in % [:attrs :name]) "spawns") (:content map-tmx)))
player-1 (first (filter #(= (get-in % [:attrs :name]) "player_1") (:content spawns)))
player-2 (first (filter #(= (get-in % [:attrs :name]) "player_2") (:content spawns)))
round-num-str #(Double/parseDouble (format "%.2f" (Double/parseDouble %)))
extract-pos (fn [tag] {:x (round-num-str (get-in tag [:attrs :x]))
:y (round-num-str (get-in tag [:attrs :y]))})]
{:player-1 (extract-pos player-1)
:player-2 (extract-pos player-2)})
;; {:tag :objectgroup,
;; :attrs {:id "2", :name "spawns"},
;; {:player-1 nil
;; :player-2 nil}
;; (vec (reduce (fn [acc tag]
;; (if (= (:tag tag) :object)
;; (conj acc
;; (hash-map
;; :name (get-in tag [:attrs :name])
;; :x (Math/round (Double/parseDouble (get-in tag [:attrs :x])))
;; :y (Math/round (Double/parseDouble (get-in tag [:attrs :y])))))
;; acc)) '() (:content (first (filter #(= (get-in % [:attrs :name]) "spawns") tags))))))))
}))
(def levels {:levels {:level-001 (parse-map level-001-map-tmx)
:tutorial (parse-map tutorial-map-tmx)}
:colliders colliders})
;; (pprint (get-in levels [:levels :level-001 :spawns]))
;; (pprint/pprint {:row (first (:tiles level-001))})
;; (pprint/pprint (pr-str level-001))
(fs/write-lines "../levels.fnl" ["(local levels"
(str/replace (pr-str levels) #",+" "")
")\n\n"
"{ :levels levels }"])