First stab at character portraits

This commit is contained in:
Jeremy Penner 2020-11-21 22:50:11 -05:00
parent 998cab3cb8
commit ffdef1485a
9 changed files with 147 additions and 68 deletions

View file

@ -11,12 +11,14 @@
(fn GraphicsEditView.new [self]
(GraphicsEditView.super.new self)
(set self.tilecache (tiledraw.TileCache (tiles.loadtiles)))
(set self.tilecache (tiledraw.TileCache (self:loadgfx)))
(set self.itile 1)
(attach-imstate self))
(fn GraphicsEditView.tilesize [self] (values 16 16))
(fn GraphicsEditView.loadgfx [self] (tiles.loadtiles))
(fn GraphicsEditView.reload [self]
(self.tilecache:load (tiles.loadtiles)))
(self.tilecache:load (self:loadgfx)))
(fn GraphicsEditView.select-rel [self ditile]
(when self.itile
@ -29,16 +31,19 @@
(fn GraphicsEditView.draw-tile-selector [self x y w]
(var tilex x)
(var tiley y)
(local tile-size (* 16 self.sprite-scale))
(var (pixw pixh) (self:tilesize))
(set pixw (* (/ pixw 8) 7))
(local tilew (* self.sprite-scale pixw))
(local tileh (* self.sprite-scale pixh))
(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 self.sprite-scale) 4) (+ tile-size 4)))
(when (button self [:tile itile] tilex tiley tile-size tile-size)
(love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ tilew 4) (+ tileh 4)))
(when (button self [:tile itile] tilex tiley tilew tileh)
(set self.itile itile))
(set tilex (+ tilex tile-size))
(when (>= (+ tilex tile-size) (+ x w))
(set tilex (+ tilex tilew))
(when (>= (+ tilex tilew) (+ x w))
(set tilex x)
(set tiley (+ tiley tile-size 4)))))
(set tiley (+ tiley tileh 4)))))
GraphicsEditView

View file

@ -2,19 +2,22 @@
(local util (require :lib.util))
(local TileView (require :editor.tileedit))
(local MapEditView (require :editor.mapedit))
(local PortraitView (require :editor.portraitedit))
(local {: cmd-predicate} (util.require :editor.imstate))
(local core (require :core))
(local command (require :core.command))
(local keymap (require :core.keymap))
(command.add nil {
"honeylisp:edit-tiles" (fn []
"honeylisp:tile-editor" (fn []
(local node (core.root_view:get_active_node))
(node:add_view (TileView)))
"honeylisp:edit-map" (fn []
"honeylisp:map-editor" (fn []
(local node (core.root_view:get_active_node))
(node:add_view (MapEditView))
)
(node:add_view (MapEditView)))
"honeylisp:portrait-editor" (fn []
(local node (core.root_view:get_active_node))
(node:add_view (PortraitView)))
})
(command.add (cmd-predicate :editor.gfxedit) {

32
editor/portraitedit.fnl Normal file
View file

@ -0,0 +1,32 @@
(local util (require :lib.util))
(local TileView (require :editor.tileedit))
(local tiledraw (require :editor.tiledraw))
(local tiles (require :game.tiles))
(local {: textfield} (util.require :editor.imstate))
(local PortraitView (TileView:extend))
(fn PortraitView.new [self]
(PortraitView.super.new self)
(set self.tilecache.spritegen tiledraw.portrait-to-sprite))
(fn PortraitView.tilesize [self] (values 32 32))
(fn PortraitView.loadgfx [self] (tiles.loadportraits))
(fn PortraitView.save [self] (tiles.saveportraits self.tilecache.tiles))
(fn PortraitView.map-bitxy [self x y]
(local quadrant (+ (if (>= x 16) 2 0) (if (>= y 16) 1 0)))
(local tilex
(if (or (= x 0) (= x 30)) 0
(or (= x 1) (= x 31)) 15
(< x 16) (- x 1)
(- x 15)))
(local tiley (% y 16))
(local (ibyte ibit) (PortraitView.super.map-bitxy self tilex tiley))
(values (+ ibyte (* quadrant 32)) ibit))
(fn PortraitView.draw-tile-flags [self x y]
(local tile (-?> self.tilecache.tiles (. self.itile)))
(when tile
(set tile.label (textfield self "Label" tile.label x (+ y 4) 100 200))))
(fn PortraitView.get_name [self] "Portrait Editor")
PortraitView

View file

@ -11,54 +11,71 @@
(love.graphics.setColor (/ (. color 1) 255) (/ (. color 2) 255) (/ (. color 3) 255))
(love.graphics.points (+ x 0.5) (+ y 0.5))))
(fn tile-to-sprite [tile]
(local canvas (love.graphics.newCanvas 14 16))
(fn make-canvas [w h f]
(local canvas (love.graphics.newCanvas w h))
(canvas:setFilter :nearest :nearest)
(local scissor [(love.graphics.getScissor)])
(love.graphics.setScissor)
(love.graphics.setCanvas canvas)
(love.graphics.clear 0 0 0)
(for [y 0 15]
(local byte1 (string.byte (tile:sub (+ y 1) (+ y 1))))
(local byte2 (string.byte (tile:sub (+ y 17) (+ y 17))))
(local pal1 [(pal-from-byte byte1)])
(local pal2 [(pal-from-byte byte2)])
(var prevstate :off)
(var state :off)
(for [x 0 13]
(local byte (if (< x 7) byte1 byte2))
(local bitx (if (< x 7) x (- x 7)))
(local bit (not= 0 (bit.band byte (bit.lshift 1 bitx))))
(local prevpal (if (< x 8) pal1 pal2))
(local pal (if (< x 7) pal1 pal2))
(local prevart (. prevpal (+ 1 (% x 2))))
(local art (. pal (+ 1 (% x 2))))
(set prevstate state)
(set state
(match [prevstate bit]
[:off false] :off
[:off true] :rising
[:rising false] :falling
[:rising true] :on
[:falling false] :off
[:falling true] :rising
[:on true] :on
[:on false] :falling))
(local white [255 255 255])
(local (prevcolor color)
(match [prevstate state]
[_ :on] (values white white)
[:off :rising] (values nil art)
[:falling :rising] (values prevart art)))
(putpixel (- x 1) y prevcolor)
(putpixel x y color)))
(f canvas)
(love.graphics.setCanvas)
(love.graphics.setScissor (table.unpack scissor))
(love.graphics.setColor 1 1 1 1)
canvas)
(fn TileCache [tiles]
(fn tile-to-sprite [tile]
(make-canvas 14 16 (fn [canvas]
(for [y 0 15]
(local byte1 (string.byte (tile:sub (+ y 1) (+ y 1))))
(local byte2 (string.byte (tile:sub (+ y 17) (+ y 17))))
(local pal1 [(pal-from-byte byte1)])
(local pal2 [(pal-from-byte byte2)])
(var prevstate :off)
(var state :off)
(for [x 0 13]
(local byte (if (< x 7) byte1 byte2))
(local bitx (if (< x 7) x (- x 7)))
(local bit (not= 0 (bit.band byte (bit.lshift 1 bitx))))
(local prevpal (if (< x 8) pal1 pal2))
(local pal (if (< x 7) pal1 pal2))
(local prevart (. prevpal (+ 1 (% x 2))))
(local art (. pal (+ 1 (% x 2))))
(set prevstate state)
(set state
(match [prevstate bit]
[:off false] :off
[:off true] :rising
[:rising false] :falling
[:rising true] :on
[:falling false] :off
[:falling true] :rising
[:on true] :on
[:on false] :falling))
(local white [255 255 255])
(local (prevcolor color)
(match [prevstate state]
[_ :on] (values white white)
[:off :rising] (values nil art)
[:falling :rising] (values prevart art)))
(putpixel (- x 1) y prevcolor)
(putpixel x y color))))))
(fn portrait-to-sprite [gfx]
(print "generating portrait")
(local tl (tile-to-sprite (gfx:sub 1 32)))
(local bl (tile-to-sprite (gfx:sub 33 64)))
(local tr (tile-to-sprite (gfx:sub 65 96)))
(local br (tile-to-sprite (gfx:sub 97 128)))
(make-canvas 28 32 (fn [canvas]
(love.graphics.draw tl 0 0)
(love.graphics.draw bl 0 16)
(love.graphics.draw tr 14 0)
(love.graphics.draw br 14 16))))
(fn TileCache [tiles ?spritegen]
{: tiles
:spritegen (or ?spritegen tile-to-sprite)
:tilesprites []
:tile (fn [self itile] (or (. self.tiles itile) {:flags {}}))
:update-tile
@ -77,7 +94,7 @@
: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 :gfx))))
(tset self.tilesprites itile (self.spritegen (. self.tiles itile :gfx))))
(. self.tilesprites itile))})
{: tile-to-sprite : pal-from-bit : pal-from-byte : TileCache}
{: tile-to-sprite : portrait-to-sprite : pal-from-bit : pal-from-byte : TileCache}

View file

@ -7,9 +7,10 @@
(local TileView (GraphicsEditView:extend))
(local pixel-size 24)
(set TileView.pixel-size 24)
(local pixel-size TileView.pixel-size)
(fn map-bitxy [x y]
(fn TileView.map-bitxy [self x y]
(when (and (>= x 0) (< x 16) (>= y 0) (< y 16))
(local ibyte (if (< x 8) y (+ y 16)))
(local ibit
@ -18,6 +19,8 @@
(- x 8)))
(values ibyte ibit)))
(fn TileView.tilesize [self] (values 16 16))
(fn get-byte [tile ibyte]
(: (tile:sub (+ ibyte 1) (+ ibyte 1)) :byte))
(fn get-bit [tile ibyte ibit]
@ -43,18 +46,21 @@
(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) (. :gfx)) (string.rep "\0" 32)))
(local (w h) (self:tilesize))
(or (-?> self.tilecache.tiles (. self.itile) (. :gfx)) (string.rep "\0" (/ (* w h) 8))))
(fn TileView.draw-tile-editor [self tile x y]
(when (not (active? self :tile))
(set self.bit nil))
(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 (w h) (self:tilesize))
(local editor-w (* (+ pixel-size 1) w))
(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) (self:map-bitxy bitx bity))
(local bit (get-bit tile ibyte ibit))
(local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1)))))
(if (or (= bitx 0) (= bitx 15))
(if (= ibit 7)
(draw-bit-color bit px py)
(draw-bit bit px py (= (% bitx 2) 1)))
(when (and (active? self :tile) (mouse-inside px py pixel-size pixel-size))
@ -62,7 +68,7 @@
(when (not= self.bit bit)
(self:update-tile (set-tile-bit tile ibyte ibit self.bit))))))
(love.graphics.setColor 1 1 1 1)
editor-size)
(values editor-w editor-h))
(fn TileView.draw-tile-flag [self flagname x y]
(local flags (-?> self.tilecache.tiles (. self.itile) (. :flags)))
@ -86,9 +92,9 @@
(fn TileView.draw [self]
(self:draw_background style.background)
(local (x y) (values (+ self.position.x 10) (+ self.position.y 10)))
(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)))
(local (editor-w editor-h) (self:draw-tile-editor (self:tile) x y))
(self:draw-tile-flags (+ x editor-w pixel-size) y)
(self:draw-tile-selector x (+ y editor-h pixel-size) (- self.size.x 20)))
(fn TileView.get_name [self] "Tile Editor")

View file

@ -187,6 +187,12 @@
:itile-at :lookup-tile
:drawtile)
(vm:word :draw-portrait ; pgfx
0x2252 :over :drawtile
0x2352 :over 32 :+ :drawtile
0x2254 :over 64 :+ :drawtile
0x2354 :swap 96 :+ :drawtile)
(vm:def :last-key ; -- key
(vm:reserve)
[:lda :0xc000]
@ -257,7 +263,8 @@
] [:drop]))
(vm:word :full-redraw :cleargfx :drawmap :jaye-yx :get :draw-jaye-yx)
(tile.appendtiles (tile.loadtiles) tiles)
(tile.append-gfx tiles)
; thought:
; hotswap-safe debug stub at root of call stack

1
game/portraits.json Normal file
View file

@ -0,0 +1 @@
[{"gfx":"8080808080E0E0F0F8FC2CBCACACACAC80809CFEFFFFFFD7D5D5555D4F5D55D5BCB8B8B8F8F8F8F8FCBC9E9E86D0D0D095D5D585D5D5D5D0C090D0D0AAAAAAAA808086BFFFFFFFFAEAAA2A2E3C2E2AAA80808080808183878787058F8D8D8D8FAAAAAAA8AAEAEAEAC2888A8AD5D5D5D58F8F8787878F8F8F9F9FBCB8808A8A8A","label":"pjaye","flags":[]}]

View file

@ -16,10 +16,18 @@
(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]
(fn loadportraits [] (lume.map (util.readjson "game/portraits.json") deserialize))
(fn saveportraits [p] (util.writejson "game/portraits.json" (lume.map p serialize)))
(fn appendtiles [org tiles]
(each [_ tile (ipairs tiles)]
(when tile.label (org:append tile.label))
(org:append [:bytes tile.gfx]))
(org:append [:bytes tile.gfx])))
(fn append-gfx [org]
(local tiles (loadtiles))
(appendtiles org tiles)
(appendtiles org (loadportraits))
(org:append :tileflags)
(each [_ tile (ipairs tiles)]
(var flags 0)
@ -31,5 +39,5 @@
(local map (util.readjson "game/map00001.json"))
(org:append :map [:bytes (map.map:fromhex)]))
{: loadtiles : savetiles : appendtiles : appendmaps : flags : flag-to-bit}
{: loadtiles : savetiles : appendtiles : append-gfx : appendmaps : flags : flag-to-bit : loadportraits : saveportraits}

View file

@ -1 +1 @@
[{"gfx":"7F7F1F03090923436943230909031F7F7F7F784111104542174245101141787F","word":"","label":"neut1","flags":[]},{"gfx":"7F1F03090923436943230909031F7F7F7F784111104542174245101141787F7F","word":"","label":"neut2","flags":[]},{"gfx":"808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980","word":"","label":"jaye-e","flags":[]},{"gfx":"8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380","word":"","label":"jaye-w","flags":[]},{"gfx":"8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780","word":"","label":"jaye-s","flags":[]},{"gfx":"8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780","word":"","label":"jaye-n","flags":[]},{"gfx":"80808C8080808080B08080808C808080808C80808083B0808080808080868080","word":"","label":"","flags":{"walkable":true}},{"word":"term","gfx":"007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979584848400","flags":[]},{"gfx":"007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979584848400","word":"term","label":"","flags":{"neutable":true}},{"gfx":"D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","word":"","label":"","flags":[]},{"word":"","gfx":"D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA","flags":[]},{"gfx":"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","word":"","label":"","flags":{"neutable":true}},{"word":"door","gfx":"FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF","flags":[]},{"gfx":"FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF","word":"door","label":"","flags":{"walkable":true}},{"word":"switch","gfx":"FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF","flags":{"neutable":true}},{"word":"switch","gfx":"FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF","flags":{"neutable":true}},{"flags":[],"gfx":"FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF"},{"word":"scan","gfx":"FFFFAFEBFBFBFBBBBBFBFBFBEBAFFFFFFFFFF5D7DFDFDFDDDDDFDFDFD7F5FFFF","flags":{"neutable":true}},{"word":"scan","gfx":"FFFF2F2B2B2B6B6B6B6B2B2B2B2FFFFFFFFF755555555757575755555575FFFF","flags":{"neutable":true}},{"flags":[],"gfx":"FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"},{"flags":[],"gfx":"80808C80808080A8AAAAAAA888888880808C8080808380859595958584848480"},{"flags":{"debris":true},"gfx":"80808C8080A0A0A8AAAA8AA0A8808080808C8081919090848594959585858080"},{"word":"","gfx":"00005054545450404054545010383800000C0A2A2A2A0A03032A2A0A081C1C00","flags":[]},{"word":"","gfx":"0000001C1C10545040606010545454000030070702020A0A0100020A080A0200","flags":{"debris":true}},{"word":"","gfx":"80A0A8AA92D2D2AAC2C2AA92D2AA808080959595949494959494959494858080","flags":[]},{"word":"","gfx":"80808C808080A8C292AAAAAAAA8AC0D0808C80808083959290959194948580A8","flags":{"debris":true}},{"word":"","gfx":"80806008282A0800202880A8A8A8A08080980000141501051511819595958580","flags":[]},{"word":"","gfx":"80808C808080A0A8AAAA8AA2AAAAAA80808C0000000330010105051511010514","flags":{"debris":true}},{"gfx":"0000000000000000000000000000000000000000000000000000000000000000","word":"","label":"","flags":[]}]
[{"gfx":"7F7F1F03090923436943230909031F7F7F7F784111104542174245101141787F","word":"","label":"neut1","flags":[]},{"gfx":"7F1F03090923436943230909031F7F7F7F784111104542174245101141787F7F","word":"","label":"neut2","flags":[]},{"gfx":"808080C0C0C0E0C0D0C8C04040404080808083058585828A9282820A08081980","word":"","label":"jaye-e","flags":[]},{"gfx":"8080C020A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380","word":"","label":"jaye-w","flags":[]},{"gfx":"8080E030B0B098C0D0D0C840404060808080870D8D8D99828A8A920202020780","word":"","label":"jaye-s","flags":[]},{"gfx":"8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780","word":"","label":"jaye-n","flags":[]},{"gfx":"80808C8080808080B08080808C808080808C80808083B0808080808080868080","word":"","label":"","flags":{"walkable":true}},{"word":"term","gfx":"007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979584848400","flags":[]},{"gfx":"007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979584848400","word":"term","label":"","flags":{"neutable":true}},{"gfx":"D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","word":"","label":"","flags":[]},{"word":"","gfx":"D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA","flags":[]},{"gfx":"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","word":"","label":"","flags":{"neutable":true}},{"word":"door","gfx":"FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF","flags":[]},{"gfx":"FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF","word":"door","label":"","flags":{"walkable":true}},{"word":"switch","gfx":"FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF","flags":{"neutable":true}},{"word":"switch","gfx":"FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF","flags":{"neutable":true}},{"flags":[],"gfx":"FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF"},{"word":"scan","gfx":"FFFFAFEBFBFBFBBBBBFBFBFBEBAFFFFFFFFFF5D7DFDFDFDDDDDFDFDFD7F5FFFF","flags":{"neutable":true}},{"word":"scan","gfx":"FFFF2F2B2B2B6B6B6B6B2B2B2B2FFFFFFFFF755555555757575755555575FFFF","flags":{"neutable":true}},{"flags":[],"gfx":"FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"},{"flags":[],"gfx":"80808C80808080A8AAAAAAA888888880808C8080808380859595958584848480"},{"flags":{"debris":true},"gfx":"80808C8080A0A0A8AAAA8AA0A8808080808C8081919090848594959585858080"},{"word":"","gfx":"00005054545450404054545010383800000C0A2A2A2A0A03032A2A0A081C1C00","flags":[]},{"word":"","gfx":"0000001C1C10545040606010545454000030070702020A0A0100020A080A0200","flags":{"debris":true}},{"word":"","gfx":"80A0A8AA92D2D2AAC2C2AA92D2AA808080959595949494959494959494858080","flags":[]},{"word":"","gfx":"80808C808080A8C292AAAAAAAA8AC0D0808C80808083959290959194948580A8","flags":{"debris":true}},{"word":"","gfx":"80806008282A0800202880A8A8A8A08080980000141501051511819595958580","flags":[]},{"word":"","gfx":"80808C808080A0A8AAAA8AA2AAAAAA80808C0000000330010105051511010514","flags":{"debris":true}},{"gfx":"0000000000000000000000000000000000000000000000000000000000000000","word":"","label":"","flags":[]}]