(fn pal-from-bit [bit] (if bit (values [20 207 253] [255 106 60]) (values [255 68 253] [20 245 60]))) (fn pal-from-byte [byte] (pal-from-bit (not= 0 (bit.band byte 0x80)))) (fn putpixel [x y color] (when color (love.graphics.setColor (/ (. color 1) 255) (/ (. color 2) 255) (/ (. color 3) 255)) (love.graphics.points (+ x 0.5) (+ y 0.5)))) (fn make-canvas [w h f] (local canvas (love.graphics.newCanvas w h)) (local prevcanvas (love.graphics.getCanvas)) (canvas:setFilter :nearest :nearest) (local scissor [(love.graphics.getScissor)]) (love.graphics.setScissor) (love.graphics.setCanvas canvas) (love.graphics.clear 0 0 0) (f canvas) (love.graphics.setCanvas prevcanvas) (love.graphics.setScissor (table.unpack scissor)) (love.graphics.setColor 1 1 1 1) canvas) (fn draw-byte [bytes ibyte xoffset y ?state ?prevpal] (local byte (string.byte (bytes:sub ibyte ibyte))) (var prevstate nil) (var state (or ?state :off)) (var pal [(pal-from-byte byte)]) (var prevpal (or ?prevpal pal)) (for [bitx 0 6] (local x (+ bitx xoffset)) (local bit (not= 0 (bit.band byte (bit.lshift 1 bitx)))) (local prevart (. prevpal (+ 1 (% x 2)))) (local art (. pal (+ 1 (% x 2)))) (set prevstate state) (set prevpal pal) (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)) (values state pal)) (fn tilestrip-to-sprite [tiles] (make-canvas (* 14 (length tiles)) 16 (fn [canvas] (for [y 0 15] (var state nil) (var prevpal nil) (each [itile tile (ipairs tiles)] (local x (* (- itile 1) 14)) (set (state prevpal) (draw-byte tile (+ y 1) x y state prevpal)) (set (state prevpal) (draw-byte tile (+ y 17) (+ x 7) y state prevpal))))))) (fn tile-to-sprite [tile] (if tile (tilestrip-to-sprite [tile]) (make-canvas 14 16 #nil))) (fn portrait-to-sprite [gfx] (local top (tilestrip-to-sprite [(gfx:sub 1 32) (gfx:sub 65 96)])) (local bottom (tilestrip-to-sprite [(gfx:sub 33 64) (gfx:sub 97 128)])) (make-canvas 28 32 (fn [canvas] (love.graphics.draw top 0 0) (love.graphics.draw bottom 0 16)))) (fn char-to-sprite [gfx] (make-canvas 7 8 (fn [canvas] (for [y 0 7] (draw-byte gfx (+ y 1) 0 y))))) (fn TileCache [tiles ?spritegen] {: tiles :spritegen (or ?spritegen tile-to-sprite) :tilesprites [] :tile (fn [self itile] (or (. self.tiles itile) {:flags {}})) :cachekey (fn [itile ?key] (.. (or ?key :gfx) itile)) :update-tile (fn [self itile tile ?key] (tset self.tiles itile (-> (self:tile itile) (doto (tset (or ?key :gfx) tile)))) (tset self.tilesprites (self.cachekey itile ?key) 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 ?key] (local key (self.cachekey itile ?key)) (when (and (= nil (. self.tilesprites key)) (not= nil (. self.tiles itile))) (tset self.tilesprites key (self.spritegen (. self.tiles itile (or ?key :gfx))))) (. self.tilesprites key))}) {: tile-to-sprite : tilestrip-to-sprite : portrait-to-sprite : char-to-sprite : pal-from-bit : pal-from-byte : TileCache}