Compare commits

..

No commits in common. "main" and "kfest2021" have entirely different histories.

24 changed files with 120 additions and 350 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -30,8 +30,8 @@
(let [maps (icollect [imap _ (ipairs files.game.levels)] (.. :map imap)) (let [maps (icollect [imap _ (ipairs files.game.levels)] (.. :map imap))
map (or action.map (. maps 1)) map (or action.map (. maps 1))
y (+ y style.padding.y) y (+ y style.padding.y)
map (dropdown view [:warp :map i] map maps x y (* 100 SCALE)) map (dropdown view [:warp :map i] map maps x y 100)
(position-string y) (textbox view [:warp :loc i] (string.format "%x" (or action.position 0)) (+ x (* 150 SCALE)) y (* 150 SCALE)) (position-string y) (textbox view [:warp :loc i] (string.format "%x" (or action.position 0)) (+ x 150) y 150)
position (or (tonumber position-string 16) action.position)] position (or (tonumber position-string 16) action.position)]
(set action.map map) (set action.map map)
(set action.position position) (set action.position position)
@ -47,13 +47,13 @@
(let [y (+ y style.padding.y) (let [y (+ y style.padding.y)
x (renderer.draw_text style.font "Set " x y style.text) x (renderer.draw_text style.font "Set " x y style.text)
flag (or action.flag (. files.game.flags 1)) flag (or action.flag (. files.game.flags 1))
flag (dropdown view [:set-flag :flag i] flag files.game.flags x y (* 100 SCALE)) flag (dropdown view [:set-flag :flag i] flag files.game.flags x y 100)
x (renderer.draw_text style.font " to " (+ x (* 100 SCALE)) y style.text) x (renderer.draw_text style.font " to " (+ x 100) y style.text)
options (lume.concat options (lume.concat
[{:label "<Yes>" :value 0xffff} {:label "<No>" :value 0}] [{:label "<Yes>" :value 0xffff} {:label "<No>" :value 0}]
(icollect [_ flag (ipairs files.game.flags)] {:label flag :value (.. :cond- flag)})) (icollect [_ flag (ipairs files.game.flags)] {:label flag :value (.. :cond- flag)}))
rhs (or action.rhs (. options 1)) rhs (or action.rhs (. options 1))
(rhs y) (dropdown view [:set-flag :rhs i] rhs options x y (* 100 SCALE))] (rhs y) (dropdown view [:set-flag :rhs i] rhs options x y 100)]
(set action.flag flag) (set action.flag flag)
(set action.rhs rhs) (set action.rhs rhs)
y)) y))

View file

@ -95,18 +95,17 @@
(activate view tag x y w h) (activate view tag x y w h)
(values (and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h)) (+ y h style.padding.y))) (values (and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h)) (+ y h style.padding.y)))
(fn textbutton [view label x y ?font] (fn textbutton [view label x y]
(let [font (or ?font style.font)] (local (w h) (values (+ (style.font:get_width label) style.padding.x) (+ (style.font:get_height) style.padding.y)))
(local (w h) (values (+ (font:get_width label) style.padding.x) (+ (font:get_height) style.padding.y)))
(renderer.draw_rect x y w h style.selection) (renderer.draw_rect x y w h style.selection)
(renderer.draw_text font label (+ x (/ style.padding.x 2)) (+ y (/ style.padding.y 2)) style.text) (renderer.draw_text style.font label (+ x (/ style.padding.x 2)) (+ y (/ style.padding.y 2)) style.text)
(values (button view label x y w h) (+ y h)))) (values (button view label x y w h) (+ y h)))
(fn checkbox [view name isset x y ?tag] (fn checkbox [view name isset x y ?tag]
(love.graphics.rectangle (if isset :fill :line) x y (* 12 SCALE) (* 12 SCALE)) (love.graphics.rectangle (if isset :fill :line) x y 12 12)
(local xEnd (renderer.draw_text style.font name (+ x (* 16 SCALE)) y style.text)) (local xEnd (renderer.draw_text style.font name (+ x 16) y style.text))
(love.graphics.setColor 1 1 1 1) (love.graphics.setColor 1 1 1 1)
(button view (or ?tag name) x y (- xEnd x) (* 12 SCALE))) (button view (or ?tag name) x y (- xEnd x) 12))
(fn focused? [view tag] (= (make-tag tag) (-?> view.imstate.focus (. :tag)))) (fn focused? [view tag] (= (make-tag tag) (-?> view.imstate.focus (. :tag))))
(fn focus [view tag x y w h opts] (fn focus [view tag x y w h opts]

View file

@ -66,7 +66,7 @@
level-count (length files.game.levels) level-count (length files.game.levels)
_ (do (for [i 1 level-count] (tset options i i)) _ (do (for [i 1 level-count] (tset options i i))
(table.insert options :New)) (table.insert options :New))
(ilevel yNext) (dropdown self :map-selector self.ilevel options (+ x (* 50 SCALE)) y (* 100 SCALE))] (ilevel yNext) (dropdown self :map-selector self.ilevel options (+ x 50) y 100)]
(when (not= ilevel self.ilevel) (when (not= ilevel self.ilevel)
(set self.ilevel (if (= ilevel :New) (+ level-count 1) ilevel)) (set self.ilevel (if (= ilevel :New) (+ level-count 1) ilevel))
(self:load-level)) (self:load-level))
@ -170,13 +170,13 @@
(var istep-to-delete nil) (var istep-to-delete nil)
(when (not object.steps) (set object.steps [])) (when (not object.steps) (set object.steps []))
(each [istep step (ipairs object.steps)] (each [istep step (ipairs object.steps)]
(when (textbutton self "X" (+ x (* 280 SCALE)) y) (when (textbutton self "X" (+ x 280) y)
(set istep-to-delete istep)) (set istep-to-delete istep))
(set step.condition (. (dropdown self [:code-condition istep] (condition-label step.condition) (condition-options) (set step.condition (. (dropdown self [:code-condition istep] (condition-label step.condition) (condition-options)
(+ x (* 100 SCALE) style.padding.x) y (* 100 SCALE)) (+ x 100 style.padding.x) y 100)
:flag)) :flag))
(set (step.action y) (dropdown self [:code-action istep] (or step.action (. actions.actionlist 1)) actions.actionlist x y (* 100 SCALE))) (set (step.action y) (dropdown self [:code-action istep] (or step.action (. actions.actionlist 1)) actions.actionlist x y 100))
(set y (actions.edit step self x y (* 300 SCALE) istep)) (set y (actions.edit step self x y 300 istep))
(set y (+ y style.padding.y))) (set y (+ y style.padding.y)))
(when istep-to-delete (table.remove object.steps istep-to-delete)) (when istep-to-delete (table.remove object.steps istep-to-delete))
(let [(do-new y) (textbutton self "+ New Step" x (+ y style.padding.y))] (let [(do-new y) (textbutton self "+ New Step" x (+ y style.padding.y))]
@ -186,15 +186,14 @@
(fn advanced? [object] (fn advanced? [object]
(or object.advanced (or object.advanced
(and (= object.advanced nil) (and (= object.advanced nil)
(not= object.func "") object.func)))
(not= object.func nil))))
(fn MapEditView.draw-object-advanced-editor [self object x y] (fn MapEditView.draw-object-advanced-editor [self object x y]
(let [(func y) (textfield self "Word" object.func x y (* 100 SCALE) (* 200 SCALE)) (let [(func y) (textfield self "Word" object.func x y 100 200)
(name y) (textfield self "Name" object.name x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE)) (name y) (textfield self "Name" object.name x (+ y style.padding.y) 100 200)
(linkword y) (textfield self "Link word" object.linkword x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE)) (linkword y) (textfield self "Link word" object.linkword x (+ y style.padding.y) 100 200)
(do-unlink y) (if object.link (textbutton self "Unlink" x (+ y style.padding.y)) (values false y)) (do-unlink y) (if object.link (textbutton self "Unlink" x (+ y style.padding.y)) (values false y))
(linkentity y) (if object.link (values object.linkentity y) (textfield self "Link entity" object.linkentity x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE)))] (linkentity y) (if object.link (values object.linkentity y) (textfield self "Link entity" object.linkentity x (+ y style.padding.y) 100 200))]
(lume.extend object {: func : name : linkword : linkentity}) (lume.extend object {: func : name : linkword : linkentity})
(when do-unlink (set object.link nil)) (when do-unlink (set object.link nil))
y)) y))
@ -204,10 +203,10 @@
y (if (advanced? object) y (if (advanced? object)
(self:draw-object-advanced-editor object x y) (self:draw-object-advanced-editor object x y)
(self:draw-object-code-editor object x y)) (self:draw-object-code-editor object x y))
new-flag-name (textbox self :new-flag-name self.new-flag-name x (+ y style.padding.y) (* 200 SCALE)) new-flag-name (textbox self :new-flag-name self.new-flag-name x (+ y style.padding.y) 200)
(mk-new-flag y) (textbutton self "+ New Flag" (+ x (* 200 SCALE) style.padding.x) (+ y style.padding.y)) (mk-new-flag y) (textbutton self "+ New Flag" (+ x 200 style.padding.x) (+ y style.padding.y))
do-delete (textbutton self "Delete" x (+ y (* style.padding.y 2))) do-delete (textbutton self "Delete" x (+ y 40))
(do-advanced y) (textbutton self (if (advanced? object) "Simple" "Advanced") (+ x (* 150 SCALE)) (+ y (* style.padding.y 2)))] (do-advanced y) (textbutton self (if (advanced? object) "Simple" "Advanced") (+ x 150) (+ y 40))]
(set self.new-flag-name new-flag-name) (set self.new-flag-name new-flag-name)
(when mk-new-flag (when mk-new-flag
(when (= files.game.flags nil) (when (= files.game.flags nil)
@ -237,16 +236,14 @@
(self:draw_background style.background) (self:draw_background style.background)
(self:draw_scrollbar) (self:draw_scrollbar)
(local ytop y) (local ytop y)
(local editor-on-side (> self.size.x (+ (* tilew mapw) (* 300 SCALE))))
(set y (+ y (self:draw-map-selector x y) style.padding.y)) (set y (+ y (self:draw-map-selector x y) style.padding.y))
(self:draw-map-editor x y) (self:draw-map-editor x y)
(set y (+ y (* tileh maph) style.padding.y)) (set y (+ y (* tileh maph) style.padding.y))
(set y (+ y (self:draw-tile-selector x y (if editor-on-side (* tilew mapw) (set y (+ y (self:draw-tile-selector x y (- self.size.x (* style.padding.x 2)))))
(- self.size.x (* style.padding.x 2))))))
(set (self.level.tickword y) (textfield self "Tick word" self.level.tickword x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE))) (set (self.level.tickword y) (textfield self "Tick word" self.level.tickword x (+ y style.padding.y) 100 200))
(set (self.level.moveword y) (textfield self "Move word" self.level.moveword x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE))) (set (self.level.moveword y) (textfield self "Move word" self.level.moveword x (+ y style.padding.y) 100 200))
(set (self.level.loadword y) (textfield self "Load word" self.level.loadword x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE))) (set (self.level.loadword y) (textfield self "Load word" self.level.loadword x (+ y style.padding.y) 100 200))
(let [(checked y-new) (checkbox self "Edit objects" (= self.itile nil) x (+ y style.padding.y)) (let [(checked y-new) (checkbox self "Edit objects" (= self.itile nil) x (+ y style.padding.y))
_ (when checked _ (when checked
(set self.itile nil) (set self.itile nil)
@ -263,11 +260,11 @@
(when checked (tset self.level levelflag (not (. self.level levelflag)))) (when checked (tset self.level levelflag (not (. self.level levelflag))))
(set y y-new))) (set y y-new)))
(when self.iobject (when self.iobject
(set y (math.max y (if editor-on-side (set y (math.max y (if (> self.size.x (+ (* tilew mapw) 300))
(self:draw-object-editor (+ x (* tilew mapw) style.padding.x) ytop) (self:draw-object-editor (+ x (* tilew mapw) style.padding.x) ytop)
(self:draw-object-editor x (+ y style.padding.y)))))) (self:draw-object-editor x (+ y style.padding.y))))))
(set self.scrollheight (+ y (- self.position.y) self.scroll.y style.padding.y))) (set self.scrollheight (- y (+ self.position.y style.padding.y (- self.scroll.y)))))
(fn MapEditView.get_name [self] (.. "Map " self.ilevel)) (fn MapEditView.get_name [self] (.. "Map " self.ilevel))

View file

@ -88,7 +88,8 @@
(self:draw-screen-editor (+ self.position.x 10) (+ self.position.y 10)) (self:draw-screen-editor (+ self.position.x 10) (+ self.position.y 10))
(self:draw-tile-selector (+ self.position.x 10) (+ self.position.y 20 (* screenh screen-scale)) (- self.size.x 20))) (self:draw-tile-selector (+ self.position.x 10) (+ self.position.y 20 (* screenh screen-scale)) (- self.size.x 20)))
(fn ScreenEditView.resource-key [self] "brushes") (fn ScreenEditView.filename [self] "editor/brushes.json")
(fn ScreenEditView.spritegen [self] char-to-sprite)
(fn ScreenEditView.tilesize [self] (values 8 8)) (fn ScreenEditView.tilesize [self] (values 8 8))
(fn ScreenEditView.get_name [self] (.. "Screen: " self.screenfilename)) (fn ScreenEditView.get_name [self] (.. "Screen: " self.screenfilename))

View file

@ -74,18 +74,16 @@
(fn TileView.draw-tile-flag [self flagname x y] (fn TileView.draw-tile-flag [self flagname x y]
(local flags (-?> self.tilecache.tiles (. self.itile) (. :flags))) (local flags (-?> self.tilecache.tiles (. self.itile) (. :flags)))
(local flagset (if flags (. flags flagname) false)) (local flagset (if flags (. flags flagname) false))
(let [(checked yNew) (checkbox self flagname flagset x y)] (when (checkbox self flagname flagset x y)
(when checked (tset flags flagname (if flagset nil true))) (tset flags flagname (if flagset nil true))))
yNew))
(fn TileView.draw-tile-flags [self x y] (fn TileView.draw-tile-flags [self x y]
(local tile (-?> self.tilecache.tiles (. self.itile))) (local tile (-?> self.tilecache.tiles (. self.itile)))
(var y y)
(when tile (when tile
(set (tile.word y) (textfield self "Default word" tile.word x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE))) (set tile.word (textfield self "Default word" tile.word x y 100 200))
(set (tile.label y) (textfield self "Label" tile.label x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE)))) (set tile.label (textfield self "Label" tile.label x (+ y pixel-size 4) 100 200)))
(each [iflag flagname (ipairs (tiles.flags))] (each [iflag flagname (ipairs (tiles.flags))]
(set y (self:draw-tile-flag flagname x (+ y style.padding.y))))) (self:draw-tile-flag flagname x (+ y (* (+ iflag 1) (+ pixel-size 4))))))
(fn TileView.update-tile [self newtile] (fn TileView.update-tile [self newtile]
(self.tilecache:update-tile self.itile newtile self.tilekey)) (self.tilecache:update-tile self.itile newtile self.tilekey))

View file

@ -29,13 +29,13 @@
(fn deserialize [key value root] (fn deserialize [key value root]
(match key (match key
(where (or :tiles :portraits :font :brushes)) (tile-deserialize value root) (where (or :tiles :portraits :font)) (tile-deserialize value root)
:levels (do (set value.map (value.map:fromhex)) value) :levels (do (set value.map (value.map:fromhex)) value)
_ value)) _ value))
(fn serialize [key value root] (fn serialize [key value root]
(match key (match key
(where (or :tiles :portraits :font :brushes)) (tile-serialize value root) (where (or :tiles :portraits :font)) (tile-serialize value root)
:levels (do (set value.map (value.map:tohex)) value) :levels (do (set value.map (value.map:tohex)) value)
_ value)) _ value))
@ -66,7 +66,6 @@
(fn new-cache [game key] (fn new-cache [game key]
(let [spritegen (match key (let [spritegen (match key
:font tiledraw.char-to-sprite :font tiledraw.char-to-sprite
:brushes tiledraw.char-to-sprite
:portraits tiledraw.portrait-to-sprite :portraits tiledraw.portrait-to-sprite
_ tiledraw.tile-to-sprite) _ tiledraw.tile-to-sprite)
gfx (. game key)] gfx (. game key)]

View file

@ -143,7 +143,7 @@
[:jmp (if (= (or map.moveword "") "") :move-noop map.moveword)] [:jmp (if (= (or map.moveword "") "") :move-noop map.moveword)]
[:jmp (if (= (or map.loadword "") "") :next map.loadword)])) [:jmp (if (= (or map.loadword "") "") :next map.loadword)]))
(vm.code:append :map-ptr [:db 0] [:hot-preserve :map-page [:db 0]]) (vm.code:append :map-ptr [:db 0] :map-page [:db 0])
(vm:word :map :lit :map-ptr :get) (vm:word :map :lit :map-ptr :get)
(vm:word :entity-count :map 240 :+ :bget) (vm:word :entity-count :map 240 :+ :bget)
(vm:word :map-jaye-yx :map 241 :+ :get) (vm:word :map-jaye-yx :map 241 :+ :get)

File diff suppressed because one or more lines are too long

View file

@ -52,7 +52,7 @@
[:vm :hires [:vm :hires
:lit :level1 :load-level :lit :level1 :load-level
(vm:forever (vm:forever
(vm:hotswap-sync :full-redraw) (vm:hotswap-sync :lit :level6 :load-level)
:interactive-eval-checkpoint :interactive-eval-checkpoint
:handle-key :handle-key
) )

View file

@ -3,15 +3,12 @@
(local {: walkable : neutable : debris : sittable} (tile.flag-to-bit)) (local {: walkable : neutable : debris : sittable} (tile.flag-to-bit))
(vm:word :either= ; target val1 val2 -- f
:>rot :over := :>rot := :|)
(vm:word :movement-dir ; key -- dyx (vm:word :movement-dir ; key -- dyx
(vm:ifchain [:dup (string.byte "I") 0x0b :either=] [:drop 0xff00] (vm:case [(string.byte "I") 0xff00]
[:dup (string.byte "J") 0x08 :either=] [:drop 0x00ff] [(string.byte "J") 0x00ff]
[:dup (string.byte "K") 0x15 :either=] [:drop 0x0001] [(string.byte "K") 0x0001]
[:dup (string.byte "M") 0x0a :either=] [:drop 0x0100] [(string.byte "M") 0x0100]
[:drop 0x0000])) [:else 0x0000]))
(vm:def :yx+ ; yx yx -- yx (vm:def :yx+ ; yx yx -- yx
[:lda vm.TOP :x] [:lda vm.TOP :x]

View file

@ -2,14 +2,11 @@
(local core (require :core)) (local core (require :core))
(local command (require :core.command)) (local command (require :core.command))
(local keymap (require :core.keymap)) (local keymap (require :core.keymap))
(local style (require :core.style))
(local SlideshowView (require :presentation.engine)) (local SlideshowView (require :presentation.engine))
(fn set-scale [multiplier] (fn set-scale [multiplier]
(set _G.SCALE (* (love.graphics.getDPIScale) multiplier)) (set _G.SCALE (* (love.graphics.getDPIScale) multiplier))
(util.hotswap :core.style) (util.hotswap :core.style))
(when (= multiplier 1)
(set style.code_font (renderer.font.load (.. EXEDIR "/data/fonts/monospace.ttf") 15))))
(command.add nil { (command.add nil {
"presentation:start" (fn [] "presentation:start" (fn []
@ -24,14 +21,11 @@
"presentation:prev" #(core.active_view:back) "presentation:prev" #(core.active_view:back)
"presentation:next-slide" #(core.active_view:next-slide) "presentation:next-slide" #(core.active_view:next-slide)
"presentation:prev-slide" #(core.active_view:prev-slide) "presentation:prev-slide" #(core.active_view:prev-slide)
"presentation:toggle-timer" #(core.active_view:toggle-timer)
"presentation:reset-timer" #(core.active_view:reset-timer)
}) })
(keymap.add { (keymap.add {
"left" "presentation:prev" "left" "presentation:prev"
"right" "presentation:next" "right" "presentation:next"
"ctrl+left" "presentation:prev-slide" "ctrl+left" "presentation:prev-slide"
"ctrl+right" "presentation:next-slide" "ctrl+right" "presentation:next-slide"
"alt+t" "presentation:toggle-timer"
}) })

View file

@ -2,7 +2,6 @@
(local style (require :core.style)) (local style (require :core.style))
(local common (require :core.common)) (local common (require :core.common))
(local View (require :core.view)) (local View (require :core.view))
(local {: attach-imstate : textbutton} (require :editor.imstate))
(local SlideshowView (View:extend)) (local SlideshowView (View:extend))
(fn SlideshowView.parse [slides] (fn SlideshowView.parse [slides]
@ -11,59 +10,31 @@
(icollect [_ elem (ipairs slide)] (icollect [_ elem (ipairs slide)]
(match (type elem) (match (type elem)
(where :table elem.style) (do (set style elem) nil) (where :table elem.style) (do (set style elem) nil)
:table (if elem.button (lume.merge style elem) elem) :table elem
:string (lume.merge style {:text elem}))))) :string (lume.merge style {:text elem})))))
(fn slides-target [slides]
(var target 0)
(each [_ slide (ipairs slides)]
(each [_ elem (ipairs slide)]
(when elem.target (set target (+ target elem.target)))))
target)
(fn SlideshowView.new [self slides] (fn SlideshowView.new [self slides]
(SlideshowView.super.new self) (SlideshowView.super.new self)
(attach-imstate self)
(set self.slides slides) (set self.slides slides)
(set self.total-target (slides-target slides))
(set self.imagecache {}) (set self.imagecache {})
(set self.islide 1) (set self.islide 1)
(set self.ielem 0) (set self.ielem 0)
(set self.cleanup {})
(self:cleanup-slide)
(self:advance)) (self:advance))
(fn SlideshowView.cleanup-slide [self]
(each [_ f (pairs self.cleanup)] (f))
(set self.cleanup {})
(set self.current-target (slides-target (lume.slice self.slides 1 self.islide)))
(set self.sections (icollect [_ slide (ipairs self.slides)]
(let [{: section} (or (lume.match slide #$1.section) {})] section)))
(var isection-current 0)
(set self.islide-to-isection (icollect [_ slide (ipairs self.slides)]
(let [{: section} (or (lume.match slide #$1.section) {})]
(when section (set isection-current (+ isection-current 1)))
isection-current))))
(fn SlideshowView.next-slide [self] (fn SlideshowView.next-slide [self]
(set self.islide (if (>= self.islide (length self.slides)) 1 (+ self.islide 1))) (set self.islide (if (>= self.islide (length self.slides)) 1 (+ self.islide 1)))
(set self.ielem 0) (set self.ielem 0)
(self:cleanup-slide)
(self:advance)) (self:advance))
(fn SlideshowView.prev-slide [self] (fn SlideshowView.prev-slide [self]
(set self.islide (if (<= self.islide 1) (length self.slides) (- self.islide 1))) (set self.islide (if (<= self.islide 1) (length self.slides) (- self.islide 1)))
(set self.ielem (+ 1 (length (. self.slides self.islide)))) (set self.ielem (+ 1 (length (. self.slides self.islide))))
(self:cleanup-slide)
(self:back)) (self:back))
(fn SlideshowView.ielemNext [self ielem di] (fn SlideshowView.ielemNext [self ielem di]
(let [slide (. self.slides self.islide) (let [slide (. self.slides self.islide)
elem (. slide ielem)] elem (. slide ielem)]
(when elem (when elem
(when elem.action
(if (= di 1) (tset self.cleanup ielem (elem:action))
(. self.cleanup ielem) ((. self.cleanup ielem))))
(if elem.pause-after ielem (if elem.pause-after ielem
(self:ielemNext (+ ielem di) di))))) (self:ielemNext (+ ielem di) di)))))
@ -106,16 +77,7 @@
lines)) lines))
(fn SlideshowView.render-element [self element y] (fn SlideshowView.render-element [self element y]
(if element.button (if element.text
(let [(pressed yNext) (textbutton self
element.text
(+ self.position.x (self:justify element (element.font:get_width element.text)))
y
element.font)]
(when pressed (element:button))
(self:next-y element (- yNext y) y))
element.text
(let [lines (self:word-wrap element) (let [lines (self:word-wrap element)
line-height (element.font:get_height) line-height (element.font:get_height)
full-height (+ (* line-height (length lines)) (* style.padding.y (- (length lines) 1)))] full-height (+ (* line-height (length lines)) (* style.padding.y (- (length lines) 1)))]
@ -140,47 +102,6 @@
(each [ielem element (ipairs (. self.slides self.islide)) :until (> ielem self.ielem)] (each [ielem element (ipairs (. self.slides self.islide)) :until (> ielem self.ielem)]
(set y (self:render-element element (self:this-y element y))))) (set y (self:render-element element (self:this-y element y)))))
; timer
(fn SlideshowView.elapsed [self]
(if self.elapsed-time self.elapsed-time
self.start-time (- (system.get_time) self.start-time)
0))
(fn SlideshowView.toggle-timer [self]
(if (= self.start-time nil)
(set self.start-time (system.get_time))
(= self.elapsed-time nil)
(set self.elapsed-time (self:elapsed))
(do (set self.start-time (- (system.get_time) self.elapsed-time))
(set self.elapsed-time nil))))
(fn SlideshowView.reset-timer [self]
(set self.elapsed-time nil)
(set self.start-time nil))
(fn time [seconds]
(let [sign (if (< seconds 0) "-" "")
seconds (math.abs seconds)
m (math.floor (/ seconds 60))
s (% seconds 60)]
(string.format "%s%d:%02d" sign m s)))
; status bar
(fn SlideshowView.status_items [self {: separator : separator2}]
(let [full (renderer.font.load "presentation/font/PrintChar21.ttf" (* 14 SCALE))
thin (renderer.font.load "presentation/font/PRNumber3.ttf" (* 14 SCALE))
elapsed (self:elapsed)
left [full "\xE2\x8C\xA5 " thin]
right [thin (time (- self.total-target elapsed))
full " \xE2\x8C\x9B "
thin (time (- self.current-target elapsed))]]
(each [isection section (ipairs self.sections)]
(when (> isection 1) (lume.push left style.dim " > "))
(lume.push left (if (= isection (. self.islide-to-isection self.islide)) style.text style.dim) section))
(values left right)))
(fn SlideshowView.get_name [self] "] KFest 2021") (fn SlideshowView.get_name [self] "] KFest 2021")
SlideshowView SlideshowView

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View file

@ -1,214 +1,91 @@
(local util (require :lib.util)) (local util (require :lib.util))
(local lume (require :lib.lume)) (local lume (require :lib.lume))
(local {: parse} (util.require :presentation.engine)) (local {: parse} (util.require :presentation.engine))
(local core (require :core))
(local style (require :core.style)) (local style (require :core.style))
(local TileEditView (require :editor.tileedit))
(local MapEditView (require :editor.mapedit))
(local PortraitEditView (require :editor.portraitedit))
(local FontEditView (require :editor.fontedit))
(local ScreenEditView (require :editor.screenedit))
(local files (require :game.files))
(local link (require :link))
(local h (local h
{:style true {:style true
:font (renderer.font.load "presentation/font/PrintChar21.ttf" 64) :font (renderer.font.load "presentation/font/PrintChar21.ttf" (* 64 SCALE))
:color style.caret :color style.caret
:justify :center :justify :center
:topPadding 14 :topPadding (* style.padding.y 2)
:lowerPadding 64}) :lowerPadding 64})
(local ** (local **
{:style true {:style true
:font (renderer.font.load "presentation/font/PRNumber3.ttf" 32) :font (renderer.font.load "presentation/font/PRNumber3.ttf" (* 32 SCALE))
:color style.text :color style.text
:justify :left :justify :left
:lowerPadding 7
:pause-after true}) :pause-after true})
(fn p [style ?text] (lume.merge style {:pause-after true} (if ?text {:text ?text :style false}))) (fn p [style] (lume.merge style {:pause-after true}))
(fn np [style ?text] (lume.merge style {:pause-after false} (if ?text {:text ?text :style false}))) (fn np [style] (lume.merge style {:pause-after false}))
(fn bgimg [filename] {:image filename :justify :center :overlay true :alpha 0.3 :topPadding 0}) (fn bgimg [filename] {:image filename :justify :center :overlay true :alpha 0.3 :topPadding 0})
(fn view-cleanup [view]
(let [root core.root_view.root_node
node (root:get_node_for_view view)]
(when node (node:close_active_view root))))
(fn split-and-open [self f]
(let [focused-view core.active_view
focused-node (core.root_view:get_active_node)
_ (when self.split (focused-node:split self.split))
view (f self)
node (core.root_view:get_active_node)]
(when (= (core.root_view.root_node:get_node_for_view view) nil) (node:add_view view))
(when self.split (core.set_active_view focused-view)) ; don't switch focus
#(view-cleanup view)))
(fn openview [f ?extra] (lume.merge {:action #(split-and-open $1 f)} (or ?extra {})))
(fn openfile [filename ?extra]
(openview #(let [ldoc (core.open_doc filename)
view (core.root_view:open_doc ldoc)]
(when $1.line (view:scroll_to_line $1.line))
view)
?extra))
(fn boot-game []
(let [p (util.reload :game)]
(util.in-coro (fn [] (link:switch :mame)
(link.machine:run)
(util.waitfor #(link.machine:connected?))
(p:upload link.machine)
(link.machine:launch p)))
nil))
(fn vm-eval [...]
(let [prg (require :game)
overlay (prg.vm:gen-eval-prg [:vm ...])]
(link.machine:overlay overlay)
nil))
(parse [ (parse [
[h "" "" "" [h "" ""
"Honeylisp" "Honeylisp" ""
"" "" ""
(np **) "Jeremy Penner" (np **) "Jeremy Penner"
"https://spindleyq.itch.io/" "https://spindleyq.itch.io/"
"https://blog.information-superhighway.net/" "https://blog.information-superhighway.net/"
"https://bitbucket.org/SpindleyQ/honeylisp" "https://bitbucket.org/SpindleyQ/honeylisp"
"https://gamemaking.social/@SpindleyQ" "https://gamemaking.social/@SpindleyQ"
"https://twitter.com/SpindleyQ" "https://twitter.com/SpindleyQ"
{:pause-after true} {:pause-after true}]
{:target 30 :section :Intro}] [(bgimg "presentation/pics/pete286.jpeg")
[h "Honeylisp is hard to explain" h "Some Background"
** "It is an experimental programming environment designed to enable a productive Apple // game development workflow" ** "In 2019 I built a 16-bit MS-DOS game engine."
"* Built with https://fennel-lang.org/" "* Built on hardware"
"* Extends the lite text editor https://github.com/rxi/lite" "* Using only period-appropriate software (Turbo C, NeoPaint)"
{:image "presentation/pics/assembly-markup.png" :justify :center} "* Powered by Forth"
"* Built all tools from scratch from the assembler up" "* Integrated custom tools"
"* Not command-line driven - all tools, including the assembler / compiler, run _inside_ the editor" "* Interactive development via serial terminal"]
(openfile :presentation/slides.fnl {:split :right :line 89})
" * Including this presentation!"
{:target 150}]
[(bgimg "presentation/pics/boot-tower.jpeg")
{:action #(files.reload :neuttower/game.json)}
h "Neu] [ower"
** "A small puzzle adventure game!"
"Magic Trick #1: Assemble the game and poke it directly into emulated RAM"
{:action boot-game}
"--== D E M O ==--"
{:target 240}]
[h "Explain this voodoo!"
** "Directly inspired by Dagen Brock's 2016 KFest talk on GSPlus"
"Ended up using MAME - Lua plugin system exposes EVERYTHING"
"Use Jeejah nREPL server library with custom nREPL client"
"The assembler running inside the editor means the output is a rich object, not a file"
{:target 60}]
[h "Hot-Code Reload"
** "What if I could preserve the current runtime state but rewrite the code?"
(openfile :neuttower/level1.fnl {:split :right :line 59})
"Magic Trick #2: Areas of memory can be marked as 'preserved' when new code is uploaded"
{:target 180}]
[(bgimg "presentation/pics/ggj2020.jpeg") [(bgimg "presentation/pics/ggj2020.jpeg")
h "Interactive Execution" h "Neut Tower"
** "What if I could interactively try out new code while my game was running?" ** "In 2020, I did the Global Game Jam on my 286."
(np **) "Magic Trick #3" "Finished 'Shareware Episode 1' a couple of months later."]
{:button #(vm-eval :mixed) :text ":mixed"} [h "The Idea"
{:button #(vm-eval :hires) :text ":hires"} ** "What if I took a similar DIY approach with modern tools?"
{:button #(vm-eval 1 2 :+ :.) :text "1 2 :+ :."} "* I'd done Forth; what about Lisp?"
{:button #(vm-eval :jaye-yx :get :.) :text ":jaye-yx :get :."} "* How far can I push fast iterative development?"
{:button #(vm-eval :earthquake) :text ":earthquake"} "* Could I integrate an editor?"
{:pause-after true} "* How can I leverage emulation?"]
{:target 180}] [h "Honeylisp"
[h "The Tools" ** "* Written in Fennel, a Lisp that compiles to Lua"
** {:image "presentation/pics/retro-game-dev-quote.png" :justify :center :pause-after true} "* Assembler"
{:action #(files.reload :neuttower/game.json)} "* Forth-like 'virtual machine' / inner interpreter"
"14x16 tile editor" "* 'lite' editor, ported to love2d"
(openview #(TileEditView)) " * Integrated custom editors"
"Font editor" "* MAME integration"
(openview #(FontEditView)) " * Upload new builds directly into RAM"
"Portrait editor" " * Interactive code injection"
(openview #(PortraitEditView)) " * Hot code reload"
"Map editor" "* Tape upload"
(openview #(MapEditView)) "* ProDOS disk image generation"]
"Full-screen bitmap editor" ;; DEMO before tech dive
(openview #(ScreenEditView :neuttower/title.screen) {:pause-after true}) [h "Assembler"
{:target 300 :section "Tooling"}] ** "Represent instructions using Fennel data literals"
[h "Editing Editors With My Editor" " [:lda 0xff]"
** "Lua provides a very dynamic environment" "Represent labels with Fennel strings"
(openview #(MapEditView)) " :loop [:bne :loop]"
(openfile :editor/mapedit.fnl {:split :right :line 235}) "Lexical scope with nested blocks"
"Downside:" " [:block :loop (generate-loop-code) [:bne :loop]]"]
{:image "presentation/pics/bsod.png" :justify :center :pause-after true} [h "Wait WTF Is An Assembler"
{:target 180}] ** "It's just converting mnemonics to bytes, right?"
[(bgimg "presentation/pics/bitsy.png") {:image "presentation/pics/assembly-markup.png" :justify :center :pause-after true}
{:action #(files.reload :bitsy/game.json)} "Whoooops, actually the hard part is converting labels to addresses"
h "8-Bitsy" "Zero-page instructions are a different size, which messes up data layout!"
** "Bitsy is a popular free, accessible, web-based game-making tool" "Initial pass is needed to gather all symbols to determine sizes"
{:action boot-game} "What about data?"
"Spring Lisp Game Jam - 10 days to hack" " [:db 123] [:dw 12345] [:bytes \"HELLO WORLD\"] [:ref :hello]"
"Could I make my tools a little less... programmer-y?" "Must be able to line up bytes on page boundaries"
(openview #(MapEditView) {:pause-after true}) " [:align 0x100]"]
{:target 180 :section "Branching Out"}] [h "Virtual Machine"
[h "Thanks!" {:image "presentation/pics/thinkhard.png" :justify :center}
(openfile :neuttower/level6.fnl {:split :right :line 164}) ** "Not super keen on writing a complicated compiler"
(np **) "Questions?" "I'm already very comfortable with Forth"
{:topPadding 128} "Let's build a stack machine!"
"Jeremy Penner" "\"Direct threaded\" inner interpreter"
"https://spindleyq.itch.io/" "\"Immediate words\" can be Fennel functions that generate code!"]
"https://blog.information-superhighway.net/" [h "Extensible Assembler??"
"https://bitbucket.org/SpindleyQ/honeylisp" ** "How do you turn code into bytes?"
"https://gamemaking.social/@SpindleyQ" " [:vm 1 2 :+ :.]"]
"https://twitter.com/SpindleyQ"
{:pause-after true :section "Thanks!"}]
]) ])
; [(bgimg "presentation/pics/pete286.jpeg")
; h "Some Background"
; ** "2019: Built a 16-bit MS-DOS game engine, using only retro hardware and software."
; " * Driven by a custom Forth interpreter"
; {:target 90}]
; [(bgimg "presentation/pics/ggj2020.jpeg")
; h "Neut Tower"
; ** "2020: Created Neut Tower as part of two game jams.
; * Global Game Jam - One weekend - Feb 2020 - First two rooms
; * MS-DOS Game Jam - 1.5 months - April 2020 - 'Shareware Episode 1'"
; {:target 60}]
; [h "What is this unholy abomination?"
; ** "Lisp and Forth?!"
; {:image "presentation/pics/thinkhard.png" :justify :center}
; "Not super keen on writing a complicated compiler"
; " * \"Direct threaded\" inner interpreter"
; "Forth allows efficient, composable, interactive code"
; {:target 60}]
; [h "Wait WTF Is An Assembler"
; ** "It's just converting mnemonics to bytes, right?"
; "Whoooops, actually the hard part is converting labels to addresses"
; "Zero-page instructions are a different size, which messes up data layout!"
; "Initial pass is needed to gather all symbols to determine sizes"
; {:target 60}]
; [h "Step 5: Running on Hardware"
; ** "I have a IIgs with a serial cable - I can poke bytes in directly from the monitor"
; "]IN#2\n]PR#2\n]CALL-151"
; "Easy to send bytes faster than the monitor can process them"]
; [h "Audio"
; ** "I have a II+ with a cassette port"
; "LÖVE2D is a game engine - my editor can generate audio and play it back immediately"
; "Need to generate a BASIC program to bootstrap my machine code"
; (openfile :asm/tape.fnl {:split :right})
; " [:basic [10 :call :2061]]"
; "Future work: Apple Game Server fastloader"]
; [(bgimg "presentation/pics/beneath-apple-prodos.png")
; h "ProDOS"
; ** "Disk image is a must-have for distribution"
; (openfile :asm/prodos.fnl {:split :right :line 132})
; "Of course I wrote my own disk image generation code!"
; "Start with a blank ProDOS disk and add to it"
; "Fun bugs!"
; "* Accidentally implemented undelete instead of inserting new files at first"
; "* Read the free space bitmap backwards and overwrote the OS"
; "* Tried to name a volume starting with a number"]

View file

@ -1,12 +0,0 @@
local core = require "core"
local get_items = core.status_view.get_items
core.status_view.get_items = function (self)
if core.active_view and core.active_view.status_items then
return core.active_view:status_items(self)
else
return get_items(self)
end
end

View file

@ -8,7 +8,7 @@ if package.path:find("vendor/jeejah/") == nil then
local fennel = require "fennel" local fennel = require "fennel"
fennel.path = './?.fnl;' .. modpath .. "/../../../vendor/jeejah/?.fnl" fennel.path = './?.fnl;' .. modpath .. "/../../../vendor/jeejah/?.fnl"
table.insert(package.loaders or package.searchers, fennel.make_searcher({correlate=true})) table.insert(package.searchers, fennel.make_searcher({correlate=true}))
end end
local fennel = require "fennel" local fennel = require "fennel"

View file

@ -1 +0,0 @@
../../../../support/lite/plugins/statusoverride.lua