somewhat better layered maps, simpler serialization

This commit is contained in:
Jeremy Penner 2021-11-17 21:46:38 -05:00
parent 18f62e89b9
commit 8d97344643
5 changed files with 59 additions and 34 deletions

View file

@ -14,11 +14,16 @@
(fn platform [?key] (let [p (dimensions)] (if ?key (. p ?key) p))) (fn platform [?key] (let [p (dimensions)] (if ?key (. p ?key) p)))
(fn MapEditView.layer-type [self ?ilayer] (or (?. (platform :layers) (or ?ilayer self.ilayer)) :tiles)) (fn MapEditView.layer-type [self ?ilayer] (or (?. (platform :layers) (or ?ilayer self.ilayer)) :tiles))
(fn MapEditView.dimensions [self ?ilayer] (or (platform (self:layer-type)) (platform))) (fn MapEditView.dimensions [self ?ilayer] (or (platform (self:layer-type)) (platform)))
(fn MapEditView.scaled-dimensions [self ?ilayer]
(let [dim (lume.clone (self:dimensions))]
(each [_ key (ipairs [:tilew :tileh :xstagger :ystagger])]
(when (. dim key) (tset dim key (* sprite-scale (. dim key)))))
dim))
(fn MapEditView.mapw [self ?ilayer] (. (self:dimensions ?ilayer) :mapw)) (fn MapEditView.mapw [self ?ilayer] (. (self:dimensions ?ilayer) :mapw))
(fn MapEditView.maph [self ?ilayer] (. (self:dimensions ?ilayer) :maph)) (fn MapEditView.maph [self ?ilayer] (. (self:dimensions ?ilayer) :maph))
(fn MapEditView.tilew [self ?ilayer] (* sprite-scale (. (self:dimensions ?ilayer) :tilew))) (fn MapEditView.tilew [self ?ilayer] (. (self:scaled-dimensions ?ilayer) :tilew))
(fn MapEditView.tileh [self ?ilayer] (* sprite-scale (. (self:dimensions ?ilayer) :tileh))) (fn MapEditView.tileh [self ?ilayer] (. (self:scaled-dimensions ?ilayer) :tileh))
(fn MapEditView.empty-map [self] (string.rep "\0" (* (self:mapw) (self:maph)))) (fn MapEditView.empty-map [self] (string.rep "\0" (* (self:mapw) (self:maph))))
@ -120,7 +125,7 @@
(love.graphics.circle :line xEnd yEnd (/ tilew 5)) (love.graphics.circle :line xEnd yEnd (/ tilew 5))
(love.graphics.setColor 1 1 1))) (love.graphics.setColor 1 1 1)))
(fn MapEditView.draw-tilestrip [self x y my] (fn MapEditView.draw-tilestrip [self x y my ?ilayer]
; stripcache leaks but honestly who cares ; stripcache leaks but honestly who cares
(local tilestrip []) (local tilestrip [])
(var stripid "") (var stripid "")
@ -131,40 +136,49 @@
(set stripid (.. stripid (string.char itile)))) (set stripid (.. stripid (string.char itile))))
(var sprite (. self.stripcache stripid)) (var sprite (. self.stripcache stripid))
(when (= sprite nil) (when (= sprite nil)
(set sprite (tilestrip-to-sprite tilestrip)) (set sprite (tilestrip-to-sprite tilestrip (self:layer-type ?ilayer)))
(tset self.stripcache stripid sprite)) (tset self.stripcache stripid sprite))
(love.graphics.draw sprite x y 0 self.sprite-scale self.sprite-scale)) (love.graphics.draw sprite x y 0 self.sprite-scale self.sprite-scale))
(fn MapEditView.draw-map-editor [self x y] (fn MapEditView.mapsize [self ilayer]
(let [{: mapw : maph : tilew : tileh : xstagger : ystagger} (self:scaled-dimensions ilayer)
intileh (or ystagger tileh)]
[(+ (or xstagger 0) (* mapw tilew)) (+ tileh (* (- maph 1) intileh))]))
(fn MapEditView.draw-map-editor [self x y ilayer]
(love.graphics.setColor 1 1 1 1) (love.graphics.setColor 1 1 1 1)
(local button-state self.imstate.left) (local button-state self.imstate.left)
(local [mapw maph tilew tileh] [(self:mapw) (self:maph) (self:tilew) (self:tileh)]) (local {: mapw : maph : tilew : tileh : xstagger : ystagger} (self:scaled-dimensions ilayer))
(activate self :map x y (* tilew mapw) (* tileh maph)) (local intileh (or ystagger tileh))
(local [mappw mapph] (self:mapsize ilayer))
(activate self :map x y mappw mapph)
(var iobject-over nil) (var iobject-over nil)
(for [my 1 maph] (for [my 1 maph]
(local tiley (+ y (* (- my 1) tileh))) (local tiley (+ y (* (- my 1) (or ystagger tileh))))
(self:draw-tilestrip x tiley my) (local intiley (+ tiley (- tileh intileh)))
(local xoff (if (and xstagger (= (% my 2) 0)) xstagger 0))
(self:draw-tilestrip (+ x xoff) tiley my ilayer)
(for [mx 1 mapw] (for [mx 1 mapw]
(local tilex (+ x (* (- mx 1) tilew))) (local tilex (+ x (* (- mx 1) tilew) xoff))
(local itile (self:itile-from-xy mx my)) (local itile (self:itile-from-xy mx my))
(local iobject (self:iobject-from-xy mx my)) (local iobject (self:iobject-from-xy mx my))
(when (= self.itile nil) (when (= self.itile nil)
(each [_ player (ipairs (or files.game.players [:player]))] (each [_ player (ipairs (or files.game.players [:player]))]
(match (. self.level player) (match (. self.level player)
{:x mx :y my} (renderer.draw_text style.font player tilex tiley style.text))) {:x mx :y my} (renderer.draw_text style.font player tilex intiley style.text)))
(love.graphics.setColor 1 1 1)) (love.graphics.setColor 1 1 1))
(when (and (not= iobject nil) (= self.itile nil)) (when (and (not= iobject nil) (= self.itile nil))
(love.graphics.setColor 1 0 (if (and (= self.itile nil) (= iobject self.iobject)) 1 0)) (love.graphics.setColor 1 0 (if (and (= self.itile nil) (= iobject self.iobject)) 1 0))
(love.graphics.setLineWidth 3) (love.graphics.setLineWidth 3)
(love.graphics.rectangle :line tilex tiley tilew tileh) (love.graphics.rectangle :line tilex intiley tilew intileh)
(love.graphics.setColor 1 1 1)) (love.graphics.setColor 1 1 1))
(when (mouse-inside tilex tiley tilew tileh) (when (mouse-inside tilex intiley tilew intileh)
(when (not= iobject nil) (set iobject-over iobject)) (when (not= iobject nil) (set iobject-over iobject))
(renderer.draw_text style.font (string.format "%x" (encode-yx {:x mx :y my})) tilex (+ tiley 15) style.text) (renderer.draw_text style.font (string.format "%x" (encode-yx {:x mx :y my})) tilex (+ intiley 15) style.text)
(love.graphics.setColor 1 1 1)) (love.graphics.setColor 1 1 1))
(when (and self.itile (active? self :map) (mouse-inside tilex tiley tilew tileh) (not= itile self.itile)) (when (and self.itile (active? self :map) (mouse-inside tilex intiley tilew intileh) (not= itile self.itile))
(self:set-tile mx my self.itile)) (self:set-tile mx my self.itile))
(when (and (= self.itile nil) (active? self :map) (mouse-inside tilex tiley tilew tileh)) (when (and (= self.itile nil) (active? self :map) (mouse-inside tilex intiley tilew intileh))
(match button-state (match button-state
:pressed (set self.iobject-linking iobject) :pressed (set self.iobject-linking iobject)
:released :released
@ -188,7 +202,8 @@
(when (not= iobject-over nil) (self:draw-link-line x y iobject-over [0 0.5 1] false)) (when (not= iobject-over nil) (self:draw-link-line x y iobject-over [0 0.5 1] false))
(when (not= self.iobject-linking nil) (when (not= self.iobject-linking nil)
(if (= self.imstate.left :released) (set self.iobject-linking nil) (if (= self.imstate.left :released) (set self.iobject-linking nil)
(self:draw-link-line x y self.iobject-linking [0 1 0] true))))) (self:draw-link-line x y self.iobject-linking [0 1 0] true))))
mapph)
(fn condition-label [flag] (fn condition-label [flag]
(if flag {:label flag : flag} {:label "<always>"})) (if flag {:label flag : flag} {:label "<always>"}))
@ -270,14 +285,12 @@
(var y (+ self.position.y style.padding.y (- self.scroll.y))) (var y (+ self.position.y style.padding.y (- self.scroll.y)))
(self:draw_background style.background) (self:draw_background style.background)
(self:draw_scrollbar) (self:draw_scrollbar)
(local [mapw maph tilew tileh] [(self:mapw) (self:maph) (self:tilew) (self:tileh)]) (local {: mapw : maph : tilew : tileh} (self:scaled-dimensions))
(local ytop y) (local ytop y)
(local editor-on-side (> self.size.x (+ (* tilew mapw) (* 300 SCALE)))) (local editor-on-side (> self.size.x (+ (* tilew mapw) (* 300 SCALE))))
(when (platform :layers) (self:draw-layer-selector (+ x (* 200 SCALE)) y)) (when (platform :layers) (self:draw-layer-selector (+ x (* 200 SCALE)) y))
(set y (+ y (self:draw-map-selector x y) style.padding.y)) (set y (+ y (self:draw-map-selector x y) style.padding.y))
(set y (+ y (self:draw-map-editor x y) style.padding.y))
(self:draw-map-editor x y)
(set y (+ y (* tileh maph) style.padding.y))
(set y (+ y (self:draw-tile-selector x y (if editor-on-side (* tilew mapw) (set y (+ y (self:draw-tile-selector x y (if editor-on-side (* tilew mapw)
(- self.size.x (* style.padding.x 2)))))) (- self.size.x (* style.padding.x 2))))))

View file

@ -13,7 +13,7 @@
(local scissor [(love.graphics.getScissor)]) (local scissor [(love.graphics.getScissor)])
(love.graphics.setScissor) (love.graphics.setScissor)
(love.graphics.setCanvas canvas) (love.graphics.setCanvas canvas)
(love.graphics.clear 0 0 0) (love.graphics.clear 0 0 0 0)
(f canvas) (f canvas)
(love.graphics.setCanvas prevcanvas) (love.graphics.setCanvas prevcanvas)
(love.graphics.setScissor (table.unpack scissor)) (love.graphics.setScissor (table.unpack scissor))
@ -25,8 +25,9 @@
:pal-from-bit :pal-from-byte :draw-byte) :pal-from-bit :pal-from-byte :draw-byte)
(files.default-platform-method TileDraw :editor.tiledraw :tilestrip-to-sprite (files.default-platform-method TileDraw :editor.tiledraw :tilestrip-to-sprite
(fn [tiles] (fn [tiles style]
(let [sprites (icollect [_ tile (ipairs tiles)] (TileDraw.tile-to-sprite tile))] (let [spritegen (TileDraw.spritegen-for-style style)
sprites (icollect [_ tile (ipairs tiles)] (spritegen tile))]
(TileDraw.make-canvas (* (: (. sprites 1) :getWidth) (length sprites)) (: (. sprites 1) :getHeight) (TileDraw.make-canvas (* (: (. sprites 1) :getWidth) (length sprites)) (: (. sprites 1) :getHeight)
#(each [isprite sprite (ipairs sprites)] #(each [isprite sprite (ipairs sprites)]
(love.graphics.draw sprite (* (sprite:getWidth) (- isprite 1)) 0)))))) (love.graphics.draw sprite (* (sprite:getWidth) (- isprite 1)) 0))))))

View file

@ -42,6 +42,17 @@
value) value)
_ value)) _ value))
; serialization, take 2: just always convert unprintable strings to hex everywhere
(fn deserialize2 [o]
(if (and (= (type o) :table) o.__hex__) (o.__hex__:fromhex)
(= (type o) :table) (collect [k v (pairs o)] (values k (deserialize2 v)))
o))
(fn printable? [s] (= (string.match s "[^%w%s%p]") nil))
(fn serialize2 [o]
(if (and (= (type o) :string) (not (printable? o))) {:__hex__ (o:tohex)}
(= (type o) :table) (collect [k v (pairs o)] (values k (serialize2 v)))
o))
(fn clone [v] (fn clone [v]
(match (type v) (match (type v)
:table (lume.clone v) :table (lume.clone v)
@ -52,19 +63,19 @@
(when ?filename (set files.filename ?filename)) (when ?filename (set files.filename ?filename))
(set files.game (set files.game
(if (util.file-exists (filename)) (if (util.file-exists (filename))
(let [game (util.readjson (filename))] (let [game (util.readjson (filename))]
(each [k v (pairs game)] (if (= game.version 2) (deserialize2 game)
(when (= (type v) :table) (do (each [k v (pairs game)]
(tset game k (lume.map v #(deserialize k (clone $1) game))))) (when (= (type v) :table)
game) (tset game k (lume.map v #(deserialize k (clone $1) game)))))
game)))
{:tiles [] :portraits [] :font [] :levels []})) {:tiles [] :portraits [] :font [] :levels []}))
files.game) files.game)
(fn files.save [?filename] (fn files.save [?filename]
(when ?filename (set files.filename ?filename)) (when ?filename (set files.filename ?filename))
(let [game {}] (let [game (serialize2 files.game)]
(each [k v (pairs files.game)] (set game.version 2)
(tset game k (if (= (type v) :table) (lume.map v #(serialize k (clone $1) files.game)) v)))
(util.writejson (filename) game))) (util.writejson (filename) game)))
(fn new-cache [game key] (fn new-cache [game key]

View file

@ -10,7 +10,7 @@
:iigs {:mapw 26 :maph 16 :tilew 12 :tileh 12 :iigs {:mapw 26 :maph 16 :tilew 12 :tileh 12
:layers [:tiles :iso :iso] :layers [:tiles :iso :iso]
:yoffsets [0 6 0] :yoffsets [0 6 0]
:iso {:mapw 13 :maph 16 :tilew 24 :tileh 32 :stagger 12} :iso {:mapw 12 :maph 28 :tilew 24 :tileh 32 :xstagger 12 :ystagger 6}
:font {:tilew 8 :tileh 8} :font {:tilew 8 :tileh 8}
:brushes {:tilew 8 :tileh 8} :brushes {:tilew 8 :tileh 8}
:portraits {:tilew 32 :tileh 32}} :portraits {:tilew 32 :tileh 32}}

File diff suppressed because one or more lines are too long