From dbc618acaa8715c50b94458482d473122afe4993 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 18 Oct 2020 20:13:26 -0400 Subject: [PATCH] map editor!! --- editor/gfxedit.fnl | 40 +++++++++++++++++++++++++++ editor/init.fnl | 19 +++++++++++-- editor/mapedit.fnl | 66 +++++++++++++++++++++++++++++++++++++++++++++ editor/tiledraw.fnl | 15 ++++++++++- editor/tileedit.fnl | 66 ++++++++++----------------------------------- game/init.fnl | 8 +++--- game/map00001.json | 1 + game/tiles.fnl | 6 ++++- game/tiles.json | 2 +- wrap.fnl | 2 +- 10 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 editor/gfxedit.fnl create mode 100644 editor/mapedit.fnl create mode 100644 game/map00001.json diff --git a/editor/gfxedit.fnl b/editor/gfxedit.fnl new file mode 100644 index 0000000..fe70b7a --- /dev/null +++ b/editor/gfxedit.fnl @@ -0,0 +1,40 @@ +(local View (require :core.view)) +(local tiles (require :game.tiles)) +(local tiledraw (require :editor.tiledraw)) +(local util (require :lib.util)) +(local {: attach-imstate : mouse-inside : activate : active? : button} (util.require :editor.imstate)) + +(local GraphicsEditView (View:extend)) + +(local sprite-scale 4) +(set GraphicsEditView.sprite-scale sprite-scale) + +(fn GraphicsEditView.new [self] + (GraphicsEditView.super.new self) + (set self.tilecache (tiledraw.TileCache (tiles.loadtiles))) + (set self.itile 1) + (attach-imstate self)) + +(fn GraphicsEditView.select-rel [self ditile] + (local itile (+ self.itile ditile)) + (when (>= itile 1) (set self.itile itile))) + +(fn GraphicsEditView.draw-sprite [self x y itile] + (love.graphics.draw (self.tilecache:sprite itile) x y 0 sprite-scale sprite-scale)) + +(fn GraphicsEditView.draw-tile-selector [self x y w] + (var tilex x) + (var tiley y) + (local tile-size (* 16 sprite-scale)) + (for [itile 1 (length self.tilecache.tiles)] + (self:draw-sprite tilex tiley itile) + (when (= itile self.itile) + (love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 sprite-scale) 4) (+ tile-size 4))) + (when (button self [:tile itile] tilex tiley tile-size tile-size) + (set self.itile itile)) + (set tilex (+ tilex tile-size)) + (when (>= (+ tilex tile-size) (+ x w)) + (set tilex x) + (set tiley (+ tiley tile-size 4))))) + +GraphicsEditView diff --git a/editor/init.fnl b/editor/init.fnl index 11e2444..9ad9d5b 100644 --- a/editor/init.fnl +++ b/editor/init.fnl @@ -1,5 +1,6 @@ (require :editor.lite) (local TileView (require :editor.tileedit)) +(local MapEditView (require :editor.mapedit)) (local core (require :core)) (local command (require :core.command)) (local keymap (require :core.keymap)) @@ -7,7 +8,11 @@ (command.add nil { "honeylisp:edit-tiles" (fn [] (local node (core.root_view:get_active_node)) - (node:add_view (TileView))) ; allow hot reload + (node:add_view (TileView))) + "honeylisp:edit-map" (fn [] + (local node (core.root_view:get_active_node)) + (node:add_view (MapEditView)) + ) }) (command.add :editor.tileedit { @@ -19,7 +24,6 @@ #(when (= (length (system.get_clipboard)) 64) (core.active_view:update-tile (: (system.get_clipboard) :fromhex))) }) - (keymap.add { "ctrl+s" "tileedit:save" "left" "tileedit:previous-tile" @@ -28,3 +32,14 @@ "ctrl+v" "tileedit:paste" }) +(command.add :editor.mapedit { + "mapedit:next-tile" #(core.active_view:select-rel 1) + "mapedit:previous-tile" #(core.active_view:select-rel -1) + "mapedit:save" (fn [] (core.active_view:save) (core.log "Saved map")) +}) +(keymap.add { + "ctrl+s" "mapedit:save" + "left" "mapedit:previous-tile" + "right" "mapedit:next-tile" +}) + diff --git a/editor/mapedit.fnl b/editor/mapedit.fnl new file mode 100644 index 0000000..db09645 --- /dev/null +++ b/editor/mapedit.fnl @@ -0,0 +1,66 @@ +(local GraphicsEditView (require :editor.gfxedit)) +(local style (require :core.style)) +(local util (require :lib.util)) +(local {: mouse-inside : activate : active?} (util.require :editor.imstate)) + +(local MapEditView (GraphicsEditView:extend)) + +(local mapw 20) +(local maph 12) +(local tilew (* GraphicsEditView.sprite-scale 14)) +(local tileh (* GraphicsEditView.sprite-scale 16)) + +(fn MapEditView.new [self] + (MapEditView.super.new self) + (set self.map (string.rep "\0" (* mapw maph)))) + +; map is stored bottom-to-top +(fn imap-from-xy [mx my] + (+ mx -1 (* mapw (- maph my)))) + +(fn update-map [map mx my itile] + (local imap (imap-from-xy mx my)) + (local enctile + (bit.bor + (bit.lshift (bit.band (- itile 1) 0x07) 5) + (bit.rshift (bit.band (- itile 1) 0xf8) 3))) + (.. + (map:sub 1 imap) + (string.char enctile) + (map:sub (+ imap 2)))) + +(fn MapEditView.itile-from-xy [self mx my] + (local imap (+ (imap-from-xy mx my) 1)) + (local enctile (string.byte (self.map:sub imap imap))) + (+ 1 (bit.bor + (bit.lshift (bit.band enctile 0x1f) 3) + (bit.rshift (bit.band enctile 0xe0) 5)))) + +(fn MapEditView.set-tile [self mx my itile] + (set self.map (update-map self.map mx my itile))) + +(fn MapEditView.draw-map-editor [self x y] + (activate self :map x y (* tilew mapw) (* tileh maph)) + (for [mx 1 mapw] (for [my 1 maph] + (local tilex (+ x (* (- mx 1) tilew))) + (local tiley (+ y (* (- my 1) tileh))) + (local itile (self:itile-from-xy mx my)) + (self:draw-sprite tilex tiley itile) + (when (and (active? self :map) (mouse-inside tilex tiley tilew tileh) (not= itile self.itile)) + (self:set-tile mx my self.itile))))) + +(fn MapEditView.save [self] + (util.writejson "game/map00001.json" (self.map:tohex))) + +(fn MapEditView.draw [self] + (self:draw_background style.background) + (love.graphics.setColor 1 1 1 1) + (self:draw-map-editor (+ self.position.x 10) (+ self.position.y 10)) + (self:draw-tile-selector + (+ self.position.x 10) + (+ self.position.y 20 (* tileh maph)) + (- self.size.x 20))) + +(fn MapEditView.get_name [self] "Map Editor") + +MapEditView diff --git a/editor/tiledraw.fnl b/editor/tiledraw.fnl index e54b48d..5d23778 100644 --- a/editor/tiledraw.fnl +++ b/editor/tiledraw.fnl @@ -57,4 +57,17 @@ (love.graphics.setColor 1 1 1 1) canvas) -{: tile-to-sprite : pal-from-bit : pal-from-byte} +(fn TileCache [tiles] + {: tiles + :tilesprites [] + :update-tile + (fn [self itile tile] + (tset self.tiles itile tile) + (tset self.tilesprites itile nil)) + :sprite + (fn [self itile] + (when (and (= nil (. self.tilesprites itile)) (not= nil (. self.tiles itile))) + (tset self.tilesprites itile (tile-to-sprite (. self.tiles itile)))) + (. self.tilesprites itile))}) + +{: tile-to-sprite : pal-from-bit : pal-from-byte : TileCache} diff --git a/editor/tileedit.fnl b/editor/tileedit.fnl index 4d7b8db..6a11b44 100644 --- a/editor/tileedit.fnl +++ b/editor/tileedit.fnl @@ -1,29 +1,22 @@ -(local core (require :core)) -(local command (require :core.command)) +(local GraphicsEditView (require :editor.gfxedit)) (local style (require :core.style)) -(local View (require :core.view)) (local tiles (require :game.tiles)) (local tiledraw (require :editor.tiledraw)) -(local lume (require :lib.lume)) (local util (require :lib.util)) -(local {: attach-imstate : mouse-inside : activate : active? : button} (util.require :editor.imstate)) -(local TileView (View:extend)) +(local {: mouse-inside : activate : active?} (util.require :editor.imstate)) + +(local TileView (GraphicsEditView:extend)) (local pixel-size 24) -(local sprite-scale 4) -(local xy-to-ibit []) -(for [x 0 15] (tset xy-to-ibit x [])) -(for [y 0 15] - (tset (. xy-to-ibit 0) y (+ (* y 8) 7)) - (for [ibit 0 6] - (tset (. xy-to-ibit (+ ibit 1)) y (+ (* y 8) ibit)))) -(for [y 0 15] (for [x 0 7] - (tset (. xy-to-ibit (+ x 8)) y (+ (* (+ y 16) 8) x)))) (fn map-bitxy [x y] (when (and (>= x 0) (< x 16) (>= y 0) (< y 16)) - (local ibit (. xy-to-ibit x y)) - (values (math.floor (/ ibit 8)) (% ibit 8)))) + (local ibyte (if (< x 8) y (+ y 16))) + (local ibit + (if (= x 0) 7 + (< x 8) (- x 1) + (- x 8))) + (values ibyte ibit))) (fn get-byte [tile ibyte] (: (tile:sub (+ ibyte 1) (+ ibyte 1)) :byte)) @@ -49,14 +42,7 @@ (fn draw-bit [bit x y even] (renderer.draw_rect x y pixel-size pixel-size (if bit [255 255 255] [0 0 0]))) -(fn TileView.new [self] - (TileView.super.new self) - (set self.tiles (tiles.loadtiles)) - (set self.itile 1) - (set self.tilesprites []) - (attach-imstate self)) - -(fn TileView.tile [self] (or (. self.tiles self.itile) (string.rep "\0" 32))) +(fn TileView.tile [self] (or (. self.tilecache.tiles self.itile) (string.rep "\0" 32))) (fn TileView.draw-tile-editor [self tile x y] (when (not (active? self :tile)) @@ -76,39 +62,15 @@ (love.graphics.setColor 1 1 1 1)) (fn TileView.update-tile [self newtile] - (tset self.tiles self.itile newtile) - (tset self.tilesprites self.itile nil)) + (self.tilecache:update-tile self.itile newtile)) -(fn TileView.save [self] (tiles.savetiles self.tiles)) -(fn TileView.select-rel [self ditile] - (local itile (+ self.itile ditile)) - (when (>= itile 1) (set self.itile itile))) - -(fn TileView.tilesprite [self itile] - (when (and (= nil (. self.tilesprites itile)) (not= nil (. self.tiles itile))) - (tset self.tilesprites itile (tiledraw.tile-to-sprite (. self.tiles itile)))) - (. self.tilesprites itile)) - -(fn TileView.draw-tile-selector [self x y] - (var tilex x) - (var tiley y) - (local tile-size (* 16 sprite-scale)) - (each [itile _ (ipairs self.tiles)] - (love.graphics.draw (self:tilesprite itile) tilex tiley 0 sprite-scale sprite-scale) - (when (= itile self.itile) - (love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 sprite-scale) 4) (+ tile-size 4))) - (when (button self [:tile itile] tilex tiley tile-size tile-size) - (set self.itile itile)) - (set tilex (+ tilex tile-size)) - (when (>= (+ tilex tile-size) (+ self.position.x self.size.x -10)) - (set tilex (+ self.position.x 10)) - (set tiley (+ tiley tile-size 4))))) +(fn TileView.save [self] (tiles.savetiles self.tilecache.tiles)) (fn TileView.draw [self] (self:draw_background style.background) (local (x y) (values (+ self.position.x 10) (+ self.position.y 10))) (self:draw-tile-editor (self:tile) x y) - (self:draw-tile-selector x (+ y (* 18 (+ pixel-size 1))))) + (self:draw-tile-selector x (+ y (* 18 (+ pixel-size 1))) (- self.size.x 20))) (fn TileView.get_name [self] "Tile Editor") diff --git a/game/init.fnl b/game/init.fnl index 6b62e41..e5cfbe8 100644 --- a/game/init.fnl +++ b/game/init.fnl @@ -152,13 +152,15 @@ ; hotswap-safe debug stub at root of call stack ; but REPL debug stub should be very available as a task -; 19x11 means full map is 209 bytes -(: (prg:org 0x6800) :append :map [:bytes (string.rep "\0\032\064\096\128\160\192\224\001\033\065\097\129\161\193" 17)]) +; 20x12 means full map is 240 bytes - we have an extra 16 bytes at the end to mess with? +(tile.appendmaps (prg:org 0x6800)) +; (: (prg:org 0x6800) :append :map [:bytes (string.rep "\0\032\064\096\128\160\192\224\001\033\065\097\129\161\193" 17)]) + (code1:append :main [:jsr :reset] [:jsr :interpret] [:vm :hires ; :mixed - :cleargfx + :cleargfx ; :drawmap (vm:forever (vm:hotswap-sync) :drawmap ) diff --git a/game/map00001.json b/game/map00001.json new file mode 100644 index 0000000..aa956f3 --- /dev/null +++ b/game/map00001.json @@ -0,0 +1 @@ +"2121212141212121212121212121412121212121610261616102616161026161616161026161612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C081C080C0C0C0024161C0C0C0C0C0C0C0C0C0C0C0C1C0C0C0E0C0612161C0C0C0C0C0C0C0C0C0C0C06161616161616121616161616161C1816161616161C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0022161E0C0C0C0C0C0C0C0C0C0C081C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0614161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C061216161616161616161228161616161616161610221" \ No newline at end of file diff --git a/game/tiles.fnl b/game/tiles.fnl index 190f155..e2e235b 100644 --- a/game/tiles.fnl +++ b/game/tiles.fnl @@ -15,5 +15,9 @@ (each [_ tile (ipairs tiles)] (org:append [:bytes tile]))) -{: loadtiles : savetiles : appendtiles} +(fn appendmaps [org] + (local map (: (util.readjson "game/map00001.json") :fromhex)) + (org:append :map [:bytes map])) + +{: loadtiles : savetiles : appendtiles : appendmaps} diff --git a/game/tiles.json b/game/tiles.json index c5bf4ab..5f68b53 100644 --- a/game/tiles.json +++ b/game/tiles.json @@ -1 +1 @@ -["000000020A0820404A4020080A02000000010141511005025302051051410100","00000000020A0820404A4020080A020000000101415110050253020510514101","808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980","8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380","8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780","8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780","0000000000000000000000000000000000000000000000000000000000000000","007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979590909000","007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979590909000","D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA","F7F7DDDDF7F7DDDDF7F7DDDDF7F7DDDDEEEEBBBBEEEEBBBBEEEEBBBBEEEEBBBB","F787A5B1B3B3B1B1B3B3B1B1B3B381DDEEE8B2A6E6E6A6A6E6E6A6A6E6E6A0BB","F78785818383818183838181838381DDEEE8B0A0E0E0A0A0E0E0A0A0E0E0A0BB","F7F7CDCDCFCF898183838585878FDDDDEEECA4A4E4E4A0A0E0E0A0A0E0E8BBBB","F7F7CDCDCFCF898123232525878FDDDDEEECA4A4E4E0A0216565252561E8BBBB","F7F781D1D3D3D1D1D3D3D1D1D383DDDDEEEE808ACACE8A8BCACA8A8ACAC0BBBB","F7F7ABFBFBFBFBBBBBFBFBFBFBABDDDDEEEED5DFDFDFDFDDDDDFDFDFDFD5BBBB","F7F72B7B7B7B2B6B6B2B7B7B7B2BDDDDEEEE555F5F5F555757555F5F5F55BBBB","F7F3C58DB7F4D98187B7DDDDB7979DC5EECEA1B1ECECB8BAEEECB9B0E6CE8B9B"] \ No newline at end of file +["000000020A0820404A4020080A02000000010141511005025302051051410100","00000000020A0820404A4020080A020000000101415110050253020510514101","808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980","8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380","8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780","8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780","80808C8080808080B08080808C808080808C80808083B0808080808080868080","007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979590909000","007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979590909000","D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA","FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF","FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF","FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF","FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF","FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF","FFFFABFBFBFBFBBBBBFBFBFBFBABFFFFFFFFD5DFDFDFDFDDDDDFDFDFDFD5FFFF","FFFF2B7B7B7B2B6B6B2B7B7B7B2BFFFFFFFF555F5F5F555757555F5F5F55FFFF","FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"] \ No newline at end of file diff --git a/wrap.fnl b/wrap.fnl index e43cacb..c1bb261 100644 --- a/wrap.fnl +++ b/wrap.fnl @@ -11,7 +11,7 @@ "serial:switch-machine" #(link:switch :serial) }) (command.add #(not= link.name :gsplus) { - "gsplus:switch-machine" #(link.switch :gsplus) + "gsplus:switch-machine" #(link:switch :gsplus) }) (command.add #(link.machine:connected?) { "honeylisp:upload" (fn []