diff --git a/asm/asm.fnl b/asm/asm.fnl index f214da6..f2b7cb7 100644 --- a/asm/asm.fnl +++ b/asm/asm.fnl @@ -117,20 +117,18 @@ (fn parse-dats [block dats] (each [_ dat (ipairs dats)] (if (= (type dat) "string") - (do - (tset block.symbols dat (+ (length block.pdats) 1)) - (when (= (dat:sub 1 2) "G-") - (tset block.globals dat true))) + (do (tset block.symbols dat (+ (length block.pdats) 1)) + (when (= (dat:sub 1 2) "G-") + (tset block.globals dat true))) (let [opcode (. dat 1) parser (. dat-parser opcode) pdat - (if - parser (parser dat block) - (. opcodes opcode) (dat-parser.op dat) - (error (.. "Unrecognized opcode " (fv opcode))))] + (if parser (parser dat block) + (. opcodes opcode) (dat-parser.op dat) + (error (.. "Unrecognized opcode " (fv opcode))))] (table.insert block.pdats pdat) (when (and pdat pdat.globals) - (each [name _ (pairs pdat.globals)] + (each [name _ (pairs pdat.globals)] (tset block.globals name (length block.pdats))))))) block) diff --git a/editor/gfxedit.fnl b/editor/gfxedit.fnl index fe70b7a..7a848c7 100644 --- a/editor/gfxedit.fnl +++ b/editor/gfxedit.fnl @@ -15,21 +15,25 @@ (set self.itile 1) (attach-imstate self)) +(fn GraphicsEditView.reload [self] + (self.tilecache:load (tiles.loadtiles))) + (fn GraphicsEditView.select-rel [self ditile] - (local itile (+ self.itile ditile)) - (when (>= itile 1) (set self.itile itile))) + (when self.itile + (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)) + (love.graphics.draw (self.tilecache:sprite itile) x y 0 self.sprite-scale self.sprite-scale)) (fn GraphicsEditView.draw-tile-selector [self x y w] (var tilex x) (var tiley y) - (local tile-size (* 16 sprite-scale)) + (local tile-size (* 16 self.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))) + (love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 self.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)) diff --git a/editor/imstate.fnl b/editor/imstate.fnl index 0cb6ea0..bf2d182 100644 --- a/editor/imstate.fnl +++ b/editor/imstate.fnl @@ -1,3 +1,9 @@ +(local core (require :core)) +(local command (require :core.command)) +(local keymap (require :core.keymap)) +(local style (require :core.style)) +(local lume (require :lib.lume)) + (fn attach-imstate [view] (set view.imstate {}) (fn view.on_mouse_pressed [self button x y clicks] @@ -6,8 +12,19 @@ (fn view.on_mouse_released [self button x y] (tset self.imstate button :released) (self.__index.on_mouse_released self button x y)) + (fn view.on_key_pressed [self key] + (when (= self.imstate.keys nil) + (set self.imstate.keys [])) + (table.insert self.imstate.keys key)) + (fn view.on_text_input [self text] + (set self.imstate.text (.. (or self.imstate.text "") text)) + (self.__index.on_text_input self text)) (fn view.draw [self] + (set self.cursor nil) (self.__index.draw self) + (when (= self.cursor nil) (set self.cursor :arrow)) + (set self.imstate.keys nil) + (set self.imstate.text nil) (when (= self.imstate.left :released) (set self.imstate.active nil)) (each [_ button (pairs [:left :middle :right])] @@ -17,6 +34,27 @@ :down :down :released nil))))) +(fn register-keys [keys] + (local commands {}) + (local keymaps {}) + (each [_ key (ipairs keys)] + (local command-name (.. "imstate:" key)) + (tset commands command-name #(core.active_view:on_key_pressed key)) + (tset keymaps key command-name)) + (command.add #(not= (-?> core.active_view.imstate (. :focus)) nil) commands) + (keymap.add keymaps)) + +(register-keys [:backspace :delete :left :right :shift+left :shift+right :home :end :shift+home :shift+end]) + +(fn cmd-predicate [p] + (var p-fn p) + (when (= (type p-fn) :string) (set p-fn (require p-fn))) + (when (= (type p-fn) :table) + (local cls p-fn) + (set p-fn (fn [] (core.active_view:is cls)))) + (fn [] (when (= (-?> core.active_view.imstate (. :focus)) nil) + (p-fn)))) + (fn make-tag [tag] (match (type tag) :string tag @@ -36,4 +74,113 @@ (activate view tag x y w h) (and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h))) -{: attach-imstate : mouse-inside : activate : active? : button} +(fn checkbox [view name isset x y ?tag] + (love.graphics.rectangle (if isset :fill :line) x y 12 12) + (local xEnd (renderer.draw_text style.font name (+ x 16) y style.text)) + (love.graphics.setColor 1 1 1 1) + (button view (or ?tag name) x y (- xEnd x) 12)) + +(fn focused? [view tag] (= tag (-?> view.imstate.focus (. :tag)))) +(fn focus [view tag x y w h opts] + (if (activate view tag x y w h) + (set view.imstate.focus + (doto (lume.clone (or opts {})) + (tset :tag tag))) + + (and (= view.imstate.left :released) (focused? view tag) (not (active? view tag))) + (set view.imstate.focus nil)) + (focused? view tag)) + +(local blink_period 0.8) +(fn x-from-i [s i xLeft font] + (if (or (<= i 1) (= s "")) xLeft + (x-from-i (s:sub 2) (- i 1) (+ xLeft (font:get_width (s:sub 1 1))) font))) +(fn i-from-x [s x xLeft font ?i] + (local i (or ?i 1)) + (local w (font:get_width (s:sub 1 1))) + (local xMid (+ xLeft (/ w 2))) + (if (or (<= x xMid) (= s "")) i + (i-from-x (s:sub 2) x (+ xLeft w) font (+ i 1)))) + +(fn textnav [key i text] + (local imax (+ (length text) 1)) + (match key + :left (math.max 1 (- i 1)) + :right (math.min imax (+ i 1)) + :home 1 + :end imax)) + +(fn selection-span [view] + (let [f view.imstate.focus + iStart (math.min f.i f.iAnchor) + iLim (math.max f.i f.iAnchor)] + (values iStart iLim))) + +(fn replace-selection [view s replacement ?iStart ?iLim] + (local (iStart iLim) (if ?iLim (values ?iStart ?iLim) (selection-span view))) + (local text + (.. (s:sub 1 (- iStart 1)) + replacement + (s:sub iLim))) + (local iNew (+ iStart (length replacement))) + (set view.imstate.focus.i iNew) + (set view.imstate.focus.iAnchor iNew) + text) + +(fn textbox [view tag text x y w] + (var textNew text) + (local (h hText xText yText) (values 20 16 (+ x 2) (+ y 2))) + + ; handle key events + (when (focus view tag x y w h {:i 1 :iAnchor 1 :blink (love.timer.getTime)}) + (local f view.imstate.focus) + (when view.imstate.text + (set textNew (replace-selection view textNew view.imstate.text))) + (each [_ key (ipairs (or view.imstate.keys []))] + (set view.imstate.focus.blink (love.timer.getTime)) + (if (= (key:sub 1 6) "shift+") + (set f.i (or (textnav (key:sub 7) f.i textNew) f.i)) + (let [iNav (textnav key f.i textNew)] + (when iNav + (set f.i iNav) + (set f.iAnchor iNav)) + (if (= f.i f.iAnchor) + (set textNew + (match key + :delete (replace-selection view textNew "" f.i (+ f.i 1)) + (:backspace ? (> f.i 1)) (replace-selection view textNew "" (- f.i 1) f.i) + _ textNew)) + (when (or (= key :delete) (= key :backspace)) + (set textNew (replace-selection view textNew "")))))))) + + ; handle mouse events + (when (mouse-inside x y w h) (set view.cursor :ibeam)) + (when (and (focused? view tag) (active? view tag) (mouse-inside x y w h)) + (local mouse-i (i-from-x textNew (love.mouse.getX) x style.font)) + (when (= view.imstate.left :pressed) + (set view.imstate.focus.iAnchor mouse-i)) + (set view.imstate.focus.i mouse-i)) + + ; draw box + (love.graphics.setLineWidth 1) + (love.graphics.rectangle :line x y w h) + (if (focused? view tag) + ; draw text with selection + caret + (let [(iStart iLim) (selection-span view) + xSelect (renderer.draw_text style.font (textNew:sub 1 (- iStart 1)) xText yText style.text) + sSelect (textNew:sub iStart (- iLim 1)) + wSelect (style.font:get_width sSelect) + xTail (+ xSelect wSelect)] + (when (> wSelect 0) + (renderer.draw_rect xSelect yText wSelect hText style.selection) + (renderer.draw_text style.font sSelect xSelect yText style.text)) + (renderer.draw_text style.font (textNew:sub iLim) xTail yText style.text) + (when (or (active? view tag) + (< (% (- (love.timer.getTime) view.imstate.focus.blink) (* blink_period 2)) blink_period)) + (renderer.draw_rect (x-from-i textNew view.imstate.focus.i xText style.font) yText style.caret_width hText style.caret))) + ; just draw the text + (renderer.draw_text style.font textNew xText yText style.text)) + (love.graphics.setColor 1 1 1) + textNew) + +{: attach-imstate : cmd-predicate : mouse-inside : activate : active? : button : checkbox : textbox} diff --git a/editor/init.fnl b/editor/init.fnl index 9ad9d5b..e42e51c 100644 --- a/editor/init.fnl +++ b/editor/init.fnl @@ -1,6 +1,8 @@ (require :editor.lite) +(local util (require :lib.util)) (local TileView (require :editor.tileedit)) (local MapEditView (require :editor.mapedit)) +(local {: cmd-predicate} (util.require :editor.imstate)) (local core (require :core)) (local command (require :core.command)) (local keymap (require :core.keymap)) @@ -15,31 +17,25 @@ ) }) -(command.add :editor.tileedit { - "tileedit:save" (fn [] (core.active_view:save) (core.log "Saved tiles")) - "tileedit:next-tile" #(core.active_view:select-rel 1) - "tileedit:previous-tile" #(core.active_view:select-rel -1) - "tileedit:copy" #(system.set_clipboard (: (core.active_view:tile) :tohex)) +(command.add (cmd-predicate :editor.gfxedit) { + "graphics-editor:save" (fn [] (core.active_view:save) (core.log "Saved")) + "graphics-editor:reload" (fn [] (core.active_view:reload) (core.log "Reloaded")) + "graphics-editor:next-tile" #(core.active_view:select-rel 1) + "graphics-editor:previous-tile" #(core.active_view:select-rel -1) +}) +(command.add (cmd-predicate :editor.tileedit) { + "tileedit:copy" + #(system.set_clipboard (: (core.active_view:tile) :tohex)) "tileedit:paste" #(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" - "right" "tileedit:next-tile" - "ctrl+c" "tileedit:copy" - "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" + "ctrl+s" "graphics-editor:save" + "alt+r" "graphics-editor:reload" + "left" "graphics-editor:previous-tile" + "right" "graphics-editor:next-tile" + "ctrl+c" "tileedit:copy" + "ctrl+v" "tileedit:paste" }) diff --git a/editor/mapedit.fnl b/editor/mapedit.fnl index db09645..9d0af57 100644 --- a/editor/mapedit.fnl +++ b/editor/mapedit.fnl @@ -1,18 +1,21 @@ (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 lume (require :lib.lume)) +(local {: mouse-inside : activate : active? : checkbox : textbox} (util.require :editor.imstate)) (local MapEditView (GraphicsEditView:extend)) - +(local sprite-scale 3) (local mapw 20) (local maph 12) -(local tilew (* GraphicsEditView.sprite-scale 14)) -(local tileh (* GraphicsEditView.sprite-scale 16)) +(local tilew (* sprite-scale 14)) +(local tileh (* sprite-scale 16)) (fn MapEditView.new [self] (MapEditView.super.new self) - (set self.map (string.rep "\0" (* mapw maph)))) + (set self.sprite-scale sprite-scale) + (set self.testtext "Hello") + (self:reload)) ; map is stored bottom-to-top (fn imap-from-xy [mx my] @@ -31,13 +34,21 @@ (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))) + (local enctile (string.byte (self.level.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))) + (set self.level.map (update-map self.level.map mx my itile))) + +(fn MapEditView.iobject-from-xy [self mx my ?iobj] + (local iobj (or ?iobj 1)) + (local obj (. self.level.objects iobj)) + (when obj + (if (and (= obj.x mx) (= obj.y my)) + iobj + (self:iobject-from-xy mx my (+ iobj 1))))) (fn MapEditView.draw-map-editor [self x y] (activate self :map x y (* tilew mapw) (* tileh maph)) @@ -45,20 +56,44 @@ (local tilex (+ x (* (- mx 1) tilew))) (local tiley (+ y (* (- my 1) tileh))) (local itile (self:itile-from-xy mx my)) + (local iobject (self:iobject-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))))) + (when (not= iobject nil) + (love.graphics.setColor 1 0 (if (and (= self.itile nil) (= iobject self.iobject)) 1 0)) + (love.graphics.setLineWidth 3) + (love.graphics.rectangle :line tilex tiley tilew tileh) + (love.graphics.setColor 1 1 1)) + (when (and self.itile (active? self :map) (mouse-inside tilex tiley tilew tileh) (not= itile self.itile)) + (self:set-tile mx my self.itile)) + (when (and (= self.itile nil) (active? self :map) (mouse-inside tilex tiley tilew tileh) (= self.imstate.left :released)) + (if (= iobject nil) + (do (table.insert self.level.objects {:x mx :y my :func ""}) + (set self.iobject (length self.level.objects))) + (set self.iobject iobject)))))) + +(fn MapEditView.reload [self] + (MapEditView.super.reload self) + (local level (util.readjson "game/map00001.json")) + (set self.level + (match (type level) + :string {:map (level:fromhex) :objects []} + :table (doto level (tset :map (level.map:fromhex)))))) (fn MapEditView.save [self] - (util.writejson "game/map00001.json" (self.map:tohex))) + (util.writejson "game/map00001.json" + (doto (lume.clone self.level) + (tset :map (self.level.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)) + (when (checkbox self "Edit objects" (= self.itile nil) (+ self.position.x 10) (+ self.position.y 20 (* tileh maph))) + (set self.itile nil)) + (set self.testtext (textbox self :test self.testtext (+ self.position.x 10) (+ self.position.y 40 (* tileh maph)) 200)) (self:draw-tile-selector (+ self.position.x 10) - (+ self.position.y 20 (* tileh maph)) + (+ self.position.y 65 (* tileh maph)) (- self.size.x 20))) (fn MapEditView.get_name [self] "Map Editor") diff --git a/editor/tiledraw.fnl b/editor/tiledraw.fnl index 5d23778..7d131b6 100644 --- a/editor/tiledraw.fnl +++ b/editor/tiledraw.fnl @@ -60,14 +60,24 @@ (fn TileCache [tiles] {: tiles :tilesprites [] + :tile (fn [self itile] (or (. self.tiles itile) {:flags {}})) :update-tile (fn [self itile tile] - (tset self.tiles itile tile) + (tset self.tiles itile + (-> (self:tile itile) + (doto (tset :gfx tile)))) (tset self.tilesprites itile nil)) + :set-flag + (fn [self itile flag clear] + (tset (. self.tiles itile :flags) flag (if clear nil true))) + :load + (fn [self tiles] + (set self.tiles tiles) + (set self.tilesprites [])) :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)))) + (tset self.tilesprites itile (tile-to-sprite (. self.tiles itile :gfx)))) (. self.tilesprites itile))}) {: tile-to-sprite : pal-from-bit : pal-from-byte : TileCache} diff --git a/editor/tileedit.fnl b/editor/tileedit.fnl index 6a11b44..e1a3374 100644 --- a/editor/tileedit.fnl +++ b/editor/tileedit.fnl @@ -3,7 +3,7 @@ (local tiles (require :game.tiles)) (local tiledraw (require :editor.tiledraw)) (local util (require :lib.util)) -(local {: mouse-inside : activate : active?} (util.require :editor.imstate)) +(local {: mouse-inside : activate : active? : checkbox} (util.require :editor.imstate)) (local TileView (GraphicsEditView:extend)) @@ -42,12 +42,14 @@ (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.tile [self] (or (. self.tilecache.tiles self.itile) (string.rep "\0" 32))) +(fn TileView.tile [self] + (or (-?> self.tilecache.tiles (. self.itile) (. :gfx)) (string.rep "\0" 32))) (fn TileView.draw-tile-editor [self tile x y] (when (not (active? self :tile)) (set self.bit nil)) - (activate self :tile x y (* (+ pixel-size 1) 16) (* (+ pixel-size 1) 16)) + (local editor-size (* (+ pixel-size 1) 16)) + (activate self :tile x y editor-size editor-size) (for [bitx 0 15] (for [bity 0 15] (local (ibyte ibit) (map-bitxy bitx bity)) (local bit (get-bit tile ibyte ibit)) @@ -59,7 +61,18 @@ (when (= self.bit nil) (set self.bit (not bit))) (when (not= self.bit bit) (self:update-tile (set-tile-bit tile ibyte ibit self.bit)))))) - (love.graphics.setColor 1 1 1 1)) + (love.graphics.setColor 1 1 1 1) + editor-size) + +(fn TileView.draw-tile-flag [self flagname x y] + (local flags (-?> self.tilecache.tiles (. self.itile) (. :flags))) + (local flagset (if flags (. flags flagname) false)) + (when (checkbox self flagname flagset x y) + (tset flags flagname (if flagset nil true)))) + +(fn TileView.draw-tile-flags [self x y] + (each [iflag flagname (ipairs tiles.flags)] + (self:draw-tile-flag flagname x (+ y (* (- iflag 1) (+ pixel-size 4)))))) (fn TileView.update-tile [self newtile] (self.tilecache:update-tile self.itile newtile)) @@ -69,7 +82,8 @@ (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) + (local editor-size (self:draw-tile-editor (self:tile) x y)) + (self:draw-tile-flags (+ x editor-size pixel-size) y) (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 e5cfbe8..8e01180 100644 --- a/game/init.fnl +++ b/game/init.fnl @@ -154,7 +154,6 @@ ; 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] diff --git a/game/map00001.json b/game/map00001.json index aa956f3..5159881 100644 --- a/game/map00001.json +++ b/game/map00001.json @@ -1 +1 @@ -"2121212141212121212121212121412121212121610261616102616161026161616161026161612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C081C080C0C0C0024161C0C0C0C0C0C0C0C0C0C0C0C1C0C0C0E0C0612161C0C0C0C0C0C0C0C0C0C0C06161616161616121616161616161C1816161616161C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0022161E0C0C0C0C0C0C0C0C0C0C081C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0614161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C061216161616161616161228161616161616161610221" \ No newline at end of file +{"map":"2121212141212121212121212121412121212121610261616102616161026161616161026161612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0612161C0C0A282C0C0C0A2C0C0C081C080C0C0C2024161C0C0C0C0C0C0C0C0C2C0A2C1A2C0C0E082612161E2C08282C0C0C0C0A2C0C06161616161616121616161616161C1816161616161C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0022161E08282A2C0C0C0C0C0C0C081C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0614161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C061216161616161616161228161616161616161610221","objects":[{"func":"","x":17,"y":8},{"func":"","x":13,"y":9},{"func":"","x":13,"y":8},{"func":"","x":13,"y":4},{"func":"","x":8,"y":6},{"func":"","x":7,"y":6},{"func":"","x":2,"y":4},{"func":"","x":9,"y":1},{"func":"","x":10,"y":1}]} \ No newline at end of file diff --git a/game/tiles.fnl b/game/tiles.fnl index e2e235b..d961e58 100644 --- a/game/tiles.fnl +++ b/game/tiles.fnl @@ -1,23 +1,25 @@ (local util (require :lib.util)) (local lume (require :lib.lume)) -(fn loadtiles [] - (lume.map - (util.readjson "game/tiles.json") - #($1:fromhex))) +(local flags [:walkable :neutable :debris]) -(fn savetiles [tiles] - (util.writejson - "game/tiles.json" - (lume.map tiles #($1:tohex)))) +(fn deserialize [tile] + (match (type tile) + :string {:gfx (tile:fromhex) :flags {}} + :table (doto tile (tset :gfx (tile.gfx:fromhex))))) + +(fn serialize [tile] (doto (lume.clone tile) (tset :gfx (tile.gfx:tohex)))) + +(fn loadtiles [] (lume.map (util.readjson "game/tiles.json") deserialize)) +(fn savetiles [tiles] (util.writejson "game/tiles.json" (lume.map tiles serialize))) (fn appendtiles [tiles org] (each [_ tile (ipairs tiles)] - (org:append [:bytes tile]))) + (org:append [:bytes tile.gfx]))) (fn appendmaps [org] (local map (: (util.readjson "game/map00001.json") :fromhex)) (org:append :map [:bytes map])) -{: loadtiles : savetiles : appendtiles : appendmaps} +{: loadtiles : savetiles : appendtiles : appendmaps : flags} diff --git a/game/tiles.json b/game/tiles.json index 5f68b53..8e0728a 100644 --- a/game/tiles.json +++ b/game/tiles.json @@ -1 +1 @@ -["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 +[{"flags":[],"gfx":"000000020A0820406A4020080A02000000010141511005025702051051410100"},{"flags":[],"gfx":"00000000020A0820406A4020080A020000000101415110050257020510514101"},{"flags":[],"gfx":"808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980"},{"flags":[],"gfx":"8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380"},{"flags":[],"gfx":"8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780"},{"flags":[],"gfx":"8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780"},{"flags":[],"gfx":"80808C8080808080B08080808C808080808C80808083B0808080808080868080"},{"flags":[],"gfx":"007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979584848400"},{"flags":{"neutable":true},"gfx":"007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979584848400"},{"flags":[],"gfx":"D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"},{"flags":[],"gfx":"D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA"},{"flags":{"neutable":true},"gfx":"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},{"flags":[],"gfx":"FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF"},{"flags":{"walkable":true},"gfx":"FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF"},{"flags":{"neutable":true},"gfx":"FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF"},{"flags":{"neutable":true},"gfx":"FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF"},{"flags":[],"gfx":"FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF"},{"flags":{"neutable":true},"gfx":"FFFFAFEBFBFBFBBBBBFBFBFBEBAFFFFFFFFFF5D7DFDFDFDDDDDFDFDFD7F5FFFF"},{"flags":{"neutable":true},"gfx":"FFFF2F2B2B2B6B6B6B6B2B2B2B2FFFFFFFFF755555555757575755555575FFFF"},{"flags":[],"gfx":"FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"},{"flags":[],"gfx":"80808C80808080A8AAAAAAA888888880808C8080808380859595958584848480"},{"flags":{"debris":true},"gfx":"80808C8080A0A0A8AAAA8AA0A8808080808C8081919090848594959585858080"},{"flags":[],"gfx":"8080D0848484D0C0C0D0D4D49090B880808C8AA0A0A08A83838AAAAA88889C80"},{"flags":{"debris":true},"gfx":"808080809890D4D0C0E0E0908484D480808C808682828A8A81808288888A8280"}] \ No newline at end of file diff --git a/thinks.txt b/thinks.txt index 67e2459..049a533 100644 --- a/thinks.txt +++ b/thinks.txt @@ -1,38 +1,6 @@ -GOAL: -live-program an emulator in assembly - -- a program is a graph that is flattened into a set of bytestreams. -- first step: make the damn graph. - -APPROACH: -- program is split into "ROM" and "RAM" - ROM is code that generally doesn't change while the program is running, RAM is program data -- a program is assembled from snippets that refer to other snippets by name -- a code snippet can be marked as a "loop point", a safe spot to pause and replace a running program's code - - this is also be a good spot to take snapshots of "RAM" which we could roll back to - - this assumes an empty stack + no code references in RAM - perhaps a special typed variable is needed for snippet pointers? -- for now, we will depend on gsplus' socket-based remote debugging capabilities to poke the program into emulated memory - -WHAT IS A SNIPPET -- label + block -- block = bytestring, labels (offset into instruction list), fixups (label references) -- can concatenate blocks; snippets are stored "loose" - accessed by absolute JMP or JSR -- other compositional ideas: - - "scopes" - keep labels "alive" only for a short period, for autogenerated loops, if statements, etc - - could also just gensym - -(lda 13) ; immediate -(lda (addr #x2000)) ; absolute -(lda (addr #x20)) ; zero-page -(lda (off-x (addr #x20))) ; zp,x -(lda (off-y (addr #x20))) ; zp,y -(lda (off-x@ (addr #x20))) ; (zp,x) -(lda (@off-y (addr #x20))) ; (zp),y -(lda (off-x (addr #x2000))) ; abs,x -(lda (off-y (addr #x2000))) ; abs,y - -label = lazy address -maybe treat zero-page and absolute as different types? we will always plan what goes into zero-page. zp has addressing modes abs doesn't. - -each opcode is a function that returns a block, usually 0-3 bytes with optionally associated labels + fixups -(fixup is a tuple: local offset, label reference, and whether we're expecting an absolute, zero-page, or relative address) +Neut Tower runtime model: +- before moving, see if an object exists at that location - if so, send it a message +- otherwise, see if the space is "empty" from the current player's perspective - if so, move them there +- lookup table for tiles? rol rol rol to get index, 8 bits of possible data +- objects are kept in two parallel arrays, rather than a linked list