From 18f62e89b9bb04f89b893bf35b0af0065526c4fe Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 14 Nov 2021 14:55:41 -0500 Subject: [PATCH] Multiple tile-style support, layered maps --- editor/gfxedit.fnl | 13 ++++++--- editor/mapedit.fnl | 62 ++++++++++++++++++++++++++++------------ editor/tiledraw/iigs.fnl | 34 +++++++++++++--------- editor/tiledraw/init.fnl | 8 ++++++ editor/tileedit/iigs.fnl | 8 ++++-- editor/tileedit/init.fnl | 22 ++++++++++---- game/files.fnl | 15 +++++----- game/tiles.fnl | 25 +++++++++++++++- neutgs/game.json | 2 +- 9 files changed, 137 insertions(+), 52 deletions(-) diff --git a/editor/gfxedit.fnl b/editor/gfxedit.fnl index 31ae28c..7c681d6 100644 --- a/editor/gfxedit.fnl +++ b/editor/gfxedit.fnl @@ -12,14 +12,19 @@ (fn GraphicsEditView.new [self] (GraphicsEditView.super.new self) - (set self.tilecache (files.cache (self:resource-key))) - (set self.itile 1) + (self:set-style (self:initial-style)) (set self.scrollheight math.huge) (set self.scrollable true) (attach-imstate self)) (fn GraphicsEditView.get_scrollable_size [self] self.scrollheight) -(fn GraphicsEditView.resource-key [self] :tiles) -(fn GraphicsEditView.tilesize [self] (values 16 16)) +(fn GraphicsEditView.initial-style [self] :tiles) +(fn GraphicsEditView.tilesize [self] + (let [style (tiles.style self.style)] + (values (or style.editw style.tilew) (or style.edith style.tileh)))) +(fn GraphicsEditView.set-style [self key] + (set self.style key) + (set self.tilecache (files.cache key)) + (set self.itile 1)) (fn GraphicsEditView.reload [self] (files.reload)) (fn GraphicsEditView.save [self] (files.save)) diff --git a/editor/mapedit.fnl b/editor/mapedit.fnl index cafd770..15e01ce 100644 --- a/editor/mapedit.fnl +++ b/editor/mapedit.fnl @@ -5,48 +5,56 @@ (local files (require :game.files)) (local {: mouse-inside : activate : active? : checkbox : textfield : textbutton : textbox : dropdown} (util.require :editor.imstate)) (local {: tilestrip-to-sprite} (util.require :editor.tiledraw)) -(local {: encode-yx : encode-itile : decode-itile} (util.require :game.tiles)) +(local {: encode-yx : encode-itile : decode-itile : dimensions} (util.require :game.tiles)) (local actions (require :editor.actions)) (local MapEditView (GraphicsEditView:extend)) (local sprite-scale 3) -(local platforms { - :ii {:mapw 20 :maph 12 :tilew 14 :tileh 16} - :iigs {:mapw 20 :maph 12 :tilew 16 :tileh 16} -}) +(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.dimensions [self ?ilayer] (or (platform (self:layer-type)) (platform))) -(local platform (. platforms (files.platform))) -(local {: mapw : maph} platform) -(local tilew (* sprite-scale platform.tilew)) -(local tileh (* sprite-scale platform.tileh)) +(fn MapEditView.mapw [self ?ilayer] (. (self:dimensions ?ilayer) :mapw)) +(fn MapEditView.maph [self ?ilayer] (. (self:dimensions ?ilayer) :maph)) +(fn MapEditView.tilew [self ?ilayer] (* sprite-scale (. (self:dimensions ?ilayer) :tilew))) +(fn MapEditView.tileh [self ?ilayer] (* sprite-scale (. (self:dimensions ?ilayer) :tileh))) + +(fn MapEditView.empty-map [self] (string.rep "\0" (* (self:mapw) (self:maph)))) (fn MapEditView.new [self] (MapEditView.super.new self) (set self.sprite-scale sprite-scale) (set self.stripcache {}) (set self.ilevel 1) + (self:set-ilayer 1) (self:reload)) ; map is stored bottom-to-top -(fn imap-from-xy [mx my] - (+ mx -1 (* mapw (- maph my)))) +(fn MapEditView.imap-from-xy [self mx my] + (+ mx -1 (* (self:mapw) (- (self:maph) my)))) -(fn update-map [map mx my itile] - (local imap (imap-from-xy mx my)) +(fn MapEditView.update-map [self map mx my itile] + (local imap (self:imap-from-xy mx my)) (local enctile (encode-itile itile)) (.. (map:sub 1 imap) (string.char enctile) (map:sub (+ imap 2)))) +(fn MapEditView.map [self] + (if (platform :layers) (or (?. self.level.layers self.ilayer) (self:empty-map)) + self.level.map)) + (fn MapEditView.itile-from-xy [self mx my] - (local imap (+ (imap-from-xy mx my) 1)) - (local enctile (string.byte (self.level.map:sub imap imap))) + (local imap (+ (self:imap-from-xy mx my) 1)) + (local enctile (string.byte (string.sub (self:map) imap imap))) (decode-itile enctile)) (fn MapEditView.set-tile [self mx my itile] - (set self.level.map (update-map self.level.map mx my itile))) + (let [updated-map (self:update-map (self:map) mx my itile)] + (if (platform :layers) (util.nested-tset self.level [:layers self.ilayer] updated-map) + (set self.level.map updated-map)))) (fn MapEditView.iobject-from-xy [self mx my ?iobj] (local iobj (or ?iobj 1)) @@ -83,11 +91,25 @@ (self:load-level)) (- yNext y))) +(fn MapEditView.set-ilayer [self ilayer] + (set self.ilayer ilayer) + (self:set-style (self:layer-type))) + +(fn MapEditView.draw-layer-selector [self x y] + (renderer.draw_text style.font "Layer" x (+ y (/ style.padding.y 2)) style.text) + (let [mkopt (fn [ilayer] {: ilayer :label (.. ilayer " (" (self:layer-type ilayer) ")")}) + options (icollect [ilayer (ipairs (platform :layers))] (mkopt ilayer)) + (selection yNext) (dropdown self :layer-selector (mkopt self.ilayer) options (+ x (* 50 SCALE)) y (* 100 SCALE))] + (when (not= self.ilayer selection.ilayer) + (self:set-ilayer selection.ilayer)) + (- yNext y))) + (fn MapEditView.linking-obj [self] (. self.level.objects self.iobject-linking)) (fn MapEditView.draw-link-line [self x y iobjectSrc color toMouse?] (local objectSrc (. self.level.objects iobjectSrc)) (local objectDest (. self.level.objects objectSrc.link)) (local coord (fn [c m d] (+ c (* (- m 1) d) (/ d 2)))) + (local [tilew tileh] [(self:tilew) (self:tileh)]) (local xStart (coord x objectSrc.x tilew)) (local yStart (coord y objectSrc.y tileh)) (when (or toMouse? objectDest) @@ -102,7 +124,7 @@ ; stripcache leaks but honestly who cares (local tilestrip []) (var stripid "") - (for [mx 1 mapw] + (for [mx 1 (self:mapw)] (local itile (self:itile-from-xy mx my)) (local tile (?. self.tilecache.tiles itile :gfx)) (table.insert tilestrip tile) @@ -116,6 +138,7 @@ (fn MapEditView.draw-map-editor [self x y] (love.graphics.setColor 1 1 1 1) (local button-state self.imstate.left) + (local [mapw maph tilew tileh] [(self:mapw) (self:maph) (self:tilew) (self:tileh)]) (activate self :map x y (* tilew mapw) (* tileh maph)) (var iobject-over nil) (for [my 1 maph] @@ -234,7 +257,7 @@ (fn MapEditView.load-level [self] (set self.stripcache {}) (when (= (. (self:levels) self.ilevel) nil) - (tset (self:levels) self.ilevel {:map (string.rep "\0" (* mapw maph)) :objects []})) + (tset (self:levels) self.ilevel {:map (self:empty-map) :objects []})) (set self.level (. (self:levels) self.ilevel)) (set self.iobject nil)) @@ -247,9 +270,12 @@ (var y (+ self.position.y style.padding.y (- self.scroll.y))) (self:draw_background style.background) (self:draw_scrollbar) + (local [mapw maph tilew tileh] [(self:mapw) (self:maph) (self:tilew) (self:tileh)]) (local ytop y) (local editor-on-side (> self.size.x (+ (* tilew mapw) (* 300 SCALE)))) + (when (platform :layers) (self:draw-layer-selector (+ x (* 200 SCALE)) y)) (set y (+ y (self:draw-map-selector 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) diff --git a/editor/tiledraw/iigs.fnl b/editor/tiledraw/iigs.fnl index 16f7e97..9009910 100644 --- a/editor/tiledraw/iigs.fnl +++ b/editor/tiledraw/iigs.fnl @@ -1,21 +1,29 @@ (local {: putpixel : make-canvas} (require :editor.tiledraw)) +(local tiles (require :game.tiles)) ; converted from http://pixeljoint.com/forum/forum_posts.asp?TID=12795 (db16) ; maybe check out https://lospec.com/palette-list ? (local pal [[1 0 1] [4 2 3] [3 3 6] [4 4 4] [8 4 3] [3 6 2] [13 4 4] [7 7 6] [5 7 12] [13 7 2] [8 9 10] [6 10 2] [13 10 9] [6 12 12] [13 13 5] [13 14 13]]) -(fn gs-to-rgb [color] (icollect [_ v (ipairs color)] (* v 0x11))) +(fn gs-to-rgb [color] (icollect [_ v (ipairs (or color [0 0 0]))] (* v 0x11))) -(fn tile-to-sprite [tile] - (if tile (make-canvas 16 16 (fn [canvas] - (love.graphics.clear 0 0 0 0) - (for [y 0 15] - (for [x 0 15] - (let [ibyte (+ (* y 16) x 1) - byte (string.byte (tile:sub ibyte ibyte)) - mask (bit.band (bit.rshift byte 4) 0xf) - color (bit.band byte 0xf) - rgb (if (= mask 0) (gs-to-rgb (. pal (+ color 1))) [255 0 255])] - (when (= mask 0) (putpixel x y rgb))))))))) +(fn spritegen-for-size [w h] + (fn [tile] + (when tile (make-canvas w h (fn [canvas] + (love.graphics.clear 0 0 0 0) + (for [y 0 (- h 1)] + (for [x 0 (- w 1)] + (let [ibyte (+ (* y w) x 1) + byte (string.byte (tile:sub ibyte ibyte)) + mask (bit.band (bit.rshift byte 4) 0xf) + color (bit.band byte 0xf) + rgb (if (= mask 0) (gs-to-rgb (. pal (+ color 1))) [255 0 255])] + (when (= mask 0) (putpixel x y rgb)))))))))) -{: tile-to-sprite : pal : gs-to-rgb} +(local tile-to-sprite (spritegen-for-size 16 16)) + +(fn spritegen-for-style [name] + (let [{: tilew : tileh} (tiles.style name)] + (spritegen-for-size tilew tileh))) + +{: tile-to-sprite : spritegen-for-size : spritegen-for-style : pal : gs-to-rgb} diff --git a/editor/tiledraw/init.fnl b/editor/tiledraw/init.fnl index 109ec95..045eb1f 100644 --- a/editor/tiledraw/init.fnl +++ b/editor/tiledraw/init.fnl @@ -31,6 +31,14 @@ #(each [isprite sprite (ipairs sprites)] (love.graphics.draw sprite (* (sprite:getWidth) (- isprite 1)) 0)))))) +(files.default-platform-method TileDraw :editor.tiledraw :spritegen-for-style + (fn [style] + (match style + :font TileDraw.char-to-sprite + :brushes TileDraw.char-to-sprite + :portraits TileDraw.portrait-to-sprite + _ TileDraw.tile-to-sprite))) + (fn TileDraw.TileCache [tiles ?spritegen] {: tiles :spritegen (or ?spritegen TileDraw.tile-to-sprite) diff --git a/editor/tileedit/iigs.fnl b/editor/tileedit/iigs.fnl index f63e0de..040e50a 100644 --- a/editor/tileedit/iigs.fnl +++ b/editor/tileedit/iigs.fnl @@ -1,12 +1,16 @@ (local {: pal : gs-to-rgb} (require :editor.tiledraw.iigs)) (local lume (require :lib.lume)) -{:map-bitxy (fn [self x y] (values (+ (* y 16) x) 0 0xff)) +{:map-bitxy (fn [self x y w h] (values (+ (* y w) x) 0 0xff)) :pixel-color (fn [self b] (match b 0xf0 (values [128 128 128] [64 64 64]) _ (gs-to-rgb (. pal (+ b 1))))) :draw-bits #(if (= $1.icolor 17) 0xf0 (- $1.icolor 1)) :palette #(lume.concat (icollect [_ color (ipairs pal)] (gs-to-rgb color)) [[255 0 255]]) :pixel-storage-divisor #1 - :preview-locations #[[8 0] [0 5] [16 5] [8 10]] + :blank-tile-byte #"\xf0" + :preview-locations (fn [self] + (match self.style + :iso [[12 0] [0 6] [24 6] [12 12]] + _ [[0 0] [12 0] [0 12] [12 12]])) } diff --git a/editor/tileedit/init.fnl b/editor/tileedit/init.fnl index d0533cc..d7731a2 100644 --- a/editor/tileedit/init.fnl +++ b/editor/tileedit/init.fnl @@ -3,14 +3,13 @@ (local tiles (require :game.tiles)) (local files (require :game.files)) (local util (require :lib.util)) -(local {: mouse-inside : activate : active? : checkbox : textfield : button} (util.require :editor.imstate)) +(local {: mouse-inside : activate : active? : checkbox : textfield : button : dropdown} (util.require :editor.imstate)) (local TileView (GraphicsEditView:extend)) (set TileView.pixel-size 24) (local pixel-size TileView.pixel-size) -(fn TileView.tilesize [self] (values 16 16)) (fn TileView.tilekeys [self] (if files.game.tilesets (icollect [_ key (pairs files.game.tilesets)] key) [:gfx])) @@ -37,10 +36,12 @@ (files.default-platform-method TileView :editor.tileedit :preview-locations (fn [self] (let [(w h) (self:tilesize)] [[0 0] [w 0] [0 h] [w h]]))) +(files.default-platform-method TileView :editor.tileedit :blank-tile-byte #"\0") + (fn TileView.tile [self] (local (w h) (self:tilesize)) (or (-?> self.tilecache.tiles (. self.itile) (. (or self.tilekey :gfx))) - (string.rep "\0" (/ (* w h) (self:pixel-storage-divisor))))) + (string.rep (self:blank-tile-byte) (/ (* w h) (self:pixel-storage-divisor))))) (fn TileView.draw-pixel [self x y colorbg ?colorfg] (renderer.draw_rect x y pixel-size pixel-size colorbg) @@ -53,7 +54,7 @@ (local editor-h (* (+ pixel-size 1) h)) (activate self :tile x y editor-w editor-h) (for [bitx 0 (- w 1)] (for [bity 0 (- h 1)] - (local (ibyte ibit mask) (self:map-bitxy bitx bity)) + (local (ibyte ibit mask) (self:map-bitxy bitx bity w h)) (local b (get-bits tile ibyte ibit mask)) (local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1))))) (local (colorbg colorfg) (self:pixel-color b ibyte ibit)) @@ -107,7 +108,14 @@ 0)) (fn TileView.update-tile [self newtile] - (self.tilecache:update-tile self.itile newtile self.tilekey)) + (self.tilecache:update-tile self.itile newtile self.tilekey)) + +(fn TileView.draw-style-selector [self x y] + (renderer.draw_text style.font "Style" x (+ y (/ style.padding.y 2)) style.text) + (let [(selection yNext) (dropdown self :layer-selector self.style (tiles.tile-styles) (+ x (* 50 SCALE)) y (* 100 SCALE)) ] + (when (not= self.style selection) + (self:set-style selection)) + (- yNext y))) (fn TileView.draw [self] (self:draw_background style.background) @@ -119,12 +127,14 @@ (self:draw-tile-preview (+ x editor-w pixel-size) (+ preview-y style.padding.y)) (var selector-y (+ y editor-h pixel-size)) (set selector-y (+ selector-y (self:draw-tile-palette x selector-y (- self.size.x 20)))) + (when (> (length (tiles.tile-styles)) 1) + (set selector-y (+ selector-y (self:draw-style-selector x selector-y) style.padding.y))) (each [_ key (ipairs (self:tilekeys))] (local selector-h (self:draw-tile-selector x selector-y (- self.size.x 20) key)) (set selector-y (+ selector-y selector-h pixel-size))) (set self.scrollheight (- selector-y y))) -(fn TileView.resource-key [self] :tiles) +(fn TileView.initial-style [self] :tiles) (fn TileView.get_name [self] "Tile Editor") TileView diff --git a/game/files.fnl b/game/files.fnl index 77e1d06..4ce2076 100644 --- a/game/files.fnl +++ b/game/files.fnl @@ -29,13 +29,17 @@ (fn deserialize [key value root] (match key (where (or :tiles :portraits :font :brushes)) (tile-deserialize value root) - :levels (do (set value.map (value.map:fromhex)) value) + :levels (do (set value.map (value.map:fromhex)) + (set value.layers (icollect [_ layer (ipairs (or value.layers []))] (layer:fromhex))) + value) _ value)) (fn serialize [key value root] (match key (where (or :tiles :portraits :font :brushes)) (tile-serialize value root) - :levels (do (set value.map (value.map:tohex)) value) + :levels (do (set value.map (value.map:tohex)) + (set value.layers (icollect [_ layer (ipairs (or value.layers []))] (layer:tohex))) + value) _ value)) (fn clone [v] @@ -65,11 +69,8 @@ (fn new-cache [game key] (let [tiledraw (require :editor.tiledraw) - spritegen (match key - :font tiledraw.char-to-sprite - :brushes tiledraw.char-to-sprite - :portraits tiledraw.portrait-to-sprite - _ tiledraw.tile-to-sprite) + tiles (require :game.tiles) + spritegen (tiledraw.spritegen-for-style key) gfx (. game key)] (tiledraw.TileCache gfx spritegen))) diff --git a/game/tiles.fnl b/game/tiles.fnl index ec0593b..8568290 100644 --- a/game/tiles.fnl +++ b/game/tiles.fnl @@ -2,6 +2,29 @@ (local lume (require :lib.lume)) (local files (require :game.files)) +(local platforms { + :ii {:mapw 20 :maph 12 :tilew 14 :tileh 16 :editw 16 + :font {:tilew 7 :editw 8 :tileh 8} + :brushes {:tilew 7 :editw 8 :tileh 8} + :portraits {:tilew 28 :editw 32 :tileh 32}} + :iigs {:mapw 26 :maph 16 :tilew 12 :tileh 12 + :layers [:tiles :iso :iso] + :yoffsets [0 6 0] + :iso {:mapw 13 :maph 16 :tilew 24 :tileh 32 :stagger 12} + :font {:tilew 8 :tileh 8} + :brushes {:tilew 8 :tileh 8} + :portraits {:tilew 32 :tileh 32}} +}) + +(fn dimensions [] (. platforms (files.platform))) +(fn style [name] (or (. (dimensions) name) (dimensions))) +(fn tile-styles [include-details] + (let [dim (dimensions) + styles {:tiles dim}] + (each [_ layer (ipairs (or dim.layers []))] + (when (not= layer :tiles) (tset styles layer (. dim layer)))) + (if include-details styles (lume.keys styles)))) + (fn flags [] (or files.game.tileflags [:walkable])) (fn flag-to-bit [] (collect [iflag flag (ipairs (flags))] (values flag (bit.lshift 1 (- iflag 1))))) @@ -55,5 +78,5 @@ (find-itile tiles label (+ itile 1)))) {: appendtiles : appendgfx : append-portraitwords : flags : flag-to-bit : find-itile - : encode-yx : encode-itile : decode-itile} + : encode-yx : encode-itile : decode-itile : dimensions : tile-styles : style} diff --git a/neutgs/game.json b/neutgs/game.json index 34662eb..045981e 100644 --- a/neutgs/game.json +++ b/neutgs/game.json @@ -1 +1 @@ -{"tiles":[{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00F0FF0F0F0F0F0F0F0F0F0F0F0F00F0F0F0F0F0FF0F0F0F0F0F0F0F00A0A0F0F0F0F0F0F0A0AF0F0F0F00A0A0A0A0A0A0F0F0A0A0A0A0A0AF00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AF00A0A0A0A0A0A0F0F0A0A0A0A0A0AF0F0F0F00A0A0F0F0F0F0F0F0A0AF0F0F0F0F0F0F0F00F0F0F0F0F0FF0F0F0F0F0F0F0F0F0F0F0F00F0FF0F0F0F0F0F0F0"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00808F0F0F0F0F0F0F0F0F0F0F0F0080808080808F0F0F0F0F0F0F0F008080208020802080808F0F0F0F00808080808020802080808080808F008080808080808080808080808080808F00808080808080808080808080808F0F0F0F008080808020802080208F0F0F0F0F0F0F0F0080808020802F0F0F0F0F0F0F0F0F0F0F0F00808F0F0F0F0F0F0F0"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00904F0F0F0F0F0F0F0F0F0F0F0F0040409090404F0F0F0F0F0F0F0F009090904040909090404F0F0F0F00909040909090404090909040909F004040909040409090904040909040409F00904090904040404090904090909F0F0F0F004090909090904090904F0F0F0F0F0F0F0F0040409090404F0F0F0F0F0F0F0F0F0F0F0F00409F0F0F0F0F0F0F0"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F00707F0F0F0F0F0F0F0F0F0F0F0F0070707070707F0F0F0F0F0F0F0F007070707070707070707F0F0F0F00707070707070707070707070707F00707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070303070707070707070707070707030303030307070707070707070707030303F00303030307070707070703030303F0F0F0F003030303070703030303F0F0F0F0F0F0F0F0030303030303F0F0F0F0F0F0F0F0F0F0F0F00303F0F0F0F0F0F0F0"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00000F0F0F0F0F0F0F0F0F0F0F0F0F0000A0A0000F0F0F0F0F0F0F0F0F0F0000A0A0303030000F0F0F0F0F0F0F0000A0A00000303030300F0F0F0F0F0000A0A030303000003000AF0F0F0F0000A0A000003030303000A0AF0F0F0000A0A030303000003000A0A0AF0F0000A0A000003030303000A0A0A0AF0000A0A030303000003000A0A0A0A0A000A0A000003030303000A0A0A0A0A0A000A030303000003000A0A0A0A0A0A0AF0000003030303000A0A0A0A0A0A0AF0F0F0F0000003000A0A0A0A0A0AF0F0F0F0F0F0F0F0000A0A0A0A0AF0F0F0F0F0F0F0F0F0F0F0F00A0AF0F0F0F0F0F0F0"}],"platform":"iigs","levels":[{"loadword":"","objects":[],"tickword":"","moveword":"","map":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000200000000000000000000000000000400000000040000000000000000000000000000040000020204000000000000000000000000000004000004000000000000000000000000000000000402020400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"tilesets":{"jaye-tileset":"gfx","neut-tileset":"neut"}} \ No newline at end of file +{"tiles":[{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"},{"flags":[],"word":"","label":"","gfx":"080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F00808F0F0F0F0F0F0F0F008080808F0F0F0F0F0F0080808080808F0F0F0F00808080808080808F0F008080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808"},{"flags":[],"word":"","label":"","gfx":"0808F0F0F0F0F0F0F0F0F0F008080808F0F0F0F0F0F0F0F0080808080808F0F0F0F0F0F00808080808080808F0F0F0F008080808080808080808F0F0080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00808F0F0F0F0F0F0F0F008080808F0F0F0F0F0F0080808080808F0F0F0F00808080808080808F0F008080808080808080808080808080808080808080808"},{"flags":[],"word":"","label":"","gfx":"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00808F0F0F0F0F0F0F0F0F0F008080808F0F0F0F0F0F0F0F0080808080808F0F0F0F0F0F00808080808080808F0F0F0F008080808080808080808F0F0080808080808080808080808"}],"levels":[{"loadword":"","layers":[],"map":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000200000000000000000000000000000400000000040000000000000000000000000000040000020204000000000000000000000000000004000004000000000000000000000000000000000402020400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","tickword":"","moveword":"","objects":[]}],"tilesets":{"jaye-tileset":"gfx","neut-tileset":"neut"},"iso":[{"flags":[],"word":"","label":"","gfx":"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd"},{"flags":[],"word":"","label":"","gfx":"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0007\u0007\u0007\u0007\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0007\u0007\u0007\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0003\u0003\u0003\u0003\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\ufffd\ufffd\u0003\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0003\u0003\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0003\ufffd\ufffd\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0003\u0003\u0003\u0003\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0007\u0007\u0007\u0007\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0007\u0007\u0007\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0003\u0003\u0003\u0003\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd"}],"platform":"iigs"} \ No newline at end of file