building out the engine
This commit is contained in:
parent
c2860399fa
commit
d097c53d20
99
src/explosion.fnl
Normal file
99
src/explosion.fnl
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
(local reload (require :meta.reload))
|
||||||
|
(local {: defmulti} (require :meta.multimethod))
|
||||||
|
(local tbl (require :meta.table))
|
||||||
|
(local iter (require :meta.iter))
|
||||||
|
(local state (require :state))
|
||||||
|
|
||||||
|
(local gfx playdate.graphics)
|
||||||
|
|
||||||
|
(local draw (defmulti #$1))
|
||||||
|
(local update (defmulti #$1))
|
||||||
|
(local children (defmulti #$2))
|
||||||
|
(local cleanup (defmulti #$1))
|
||||||
|
|
||||||
|
(draw:defmethod :default #nil)
|
||||||
|
(update:defmethod :default #nil)
|
||||||
|
(children:defmethod :default (fn [val] (iter.ivalues val)))
|
||||||
|
|
||||||
|
(fn descend [t k] (children (. t k) k t))
|
||||||
|
|
||||||
|
(fn do-to-children [keys f ?t]
|
||||||
|
(each [_ key (ipairs keys)]
|
||||||
|
(each [id child (descend (or state ?t) key)]
|
||||||
|
(f key child id (or state ?t)))))
|
||||||
|
|
||||||
|
(fn restart []
|
||||||
|
(tbl.extend state
|
||||||
|
{:bomber {:x 200 :active false}
|
||||||
|
:bombs []
|
||||||
|
:bucket {:x 200 :count 3}
|
||||||
|
:bombspeed 5}))
|
||||||
|
|
||||||
|
(fn hotload []
|
||||||
|
(tbl.extend state
|
||||||
|
{:draw [:background :bomber :bombs :bucket]
|
||||||
|
:update [:bomber :bombs :bucket]
|
||||||
|
:cleanup [:bombs]}))
|
||||||
|
|
||||||
|
(fn children-keylist [keys _ t]
|
||||||
|
(iter.coro-iter #(each [_ key (ipairs keys)]
|
||||||
|
(each [k v (descend t key)]
|
||||||
|
(coroutine.yield k v)))))
|
||||||
|
|
||||||
|
(children:defmethod :bombs ipairs)
|
||||||
|
|
||||||
|
(when (= state.bombspeed nil)
|
||||||
|
(restart))
|
||||||
|
(hotload)
|
||||||
|
|
||||||
|
(local screenw (playdate.display.getWidth))
|
||||||
|
(local screenh (playdate.display.getHeight))
|
||||||
|
|
||||||
|
(update:defmethod :bucket (fn [_ bucket]
|
||||||
|
(let [crank (playdate.getCrankPosition)
|
||||||
|
ratio (if (> crank 180) (/ (- 360 crank) -130) (/ crank 130))
|
||||||
|
clamped (if (< ratio -1) -1
|
||||||
|
(> ratio 1) 1
|
||||||
|
ratio)
|
||||||
|
x (* (/ (+ ratio 1) 2) screenw)]
|
||||||
|
(set bucket.x x))
|
||||||
|
))
|
||||||
|
|
||||||
|
(let [bucketw 50 bucketh 10 radius 4
|
||||||
|
xoffset (/ bucketw 2)
|
||||||
|
buckety 220]
|
||||||
|
(draw:defmethod :bucket (fn [_ {: x}]
|
||||||
|
(gfx.drawRoundRect (- x xoffset) buckety bucketw bucketh radius))))
|
||||||
|
|
||||||
|
(fn drop-bomb []
|
||||||
|
(table.insert state.bombs {:x state.bomber.x :y 30}))
|
||||||
|
|
||||||
|
(draw:defmethod :bomber (fn [_ {: x}]
|
||||||
|
(gfx.fillRoundRect (- x 10) 5 20 30 6)))
|
||||||
|
|
||||||
|
(update:defmethod :bomber (fn []
|
||||||
|
(when (playdate.buttonJustPressed :a)
|
||||||
|
(drop-bomb))))
|
||||||
|
|
||||||
|
(draw:defmethod :background (fn []
|
||||||
|
(gfx.drawLine 0 33 screenw 33)))
|
||||||
|
|
||||||
|
(draw:defmethod :bombs (fn [_ {: x : y}]
|
||||||
|
(gfx.fillCircleAtPoint x y 7)))
|
||||||
|
|
||||||
|
(update:defmethod :bombs (fn [_ bomb ibomb s]
|
||||||
|
(set bomb.y (+ bomb.y 5))))
|
||||||
|
|
||||||
|
(cleanup:defmethod :bombs #(tbl.remove-matching state.bombs #(> $1.y screenh)))
|
||||||
|
|
||||||
|
(fn playdate.update []
|
||||||
|
(do-to-children state.update update)
|
||||||
|
(each [_ key (ipairs (or state.cleanup []))]
|
||||||
|
(cleanup key))
|
||||||
|
|
||||||
|
(gfx.clear)
|
||||||
|
(do-to-children state.draw draw)
|
||||||
|
|
||||||
|
(gfx.sprite.update)
|
||||||
|
(playdate.timer.updateTimers)
|
||||||
|
(reload.check))
|
17
src/main.fnl
17
src/main.fnl
|
@ -4,18 +4,5 @@
|
||||||
(import :CoreLibs/timer)
|
(import :CoreLibs/timer)
|
||||||
(import :package)
|
(import :package)
|
||||||
|
|
||||||
(local reload (require :meta.reload))
|
(require :meta.reload)
|
||||||
|
(require :explosion)
|
||||||
(local test (require :test))
|
|
||||||
(local gfx playdate.graphics)
|
|
||||||
|
|
||||||
(let [font (gfx.getSystemFont gfx.font.kVariantNormal)]
|
|
||||||
(fn _G.drawtext [text x y] (font:drawText text x y)))
|
|
||||||
|
|
||||||
(fn playdate.update []
|
|
||||||
(drawtext test.x 5 5)
|
|
||||||
(drawtext "Hello from Fennel!" 5 25)
|
|
||||||
(gfx.sprite.update)
|
|
||||||
(playdate.timer.updateTimers)
|
|
||||||
(reload.check)
|
|
||||||
)
|
|
||||||
|
|
20
src/meta/multimethod.fnl
Normal file
20
src/meta/multimethod.fnl
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
(local mm {})
|
||||||
|
|
||||||
|
; this indirection allows us to hook a single multimethod pre-dispatch
|
||||||
|
(set mm.__index mm)
|
||||||
|
(fn mm.__call [multi ...] (multi:call ...))
|
||||||
|
|
||||||
|
(fn mm.call [{: dispatcher : methods} ...]
|
||||||
|
(let [key (dispatcher ...)
|
||||||
|
method (or (. methods key) methods.default)]
|
||||||
|
(method ...)))
|
||||||
|
|
||||||
|
(fn mm.defmulti [dispatcher]
|
||||||
|
"Creates a new multimethod that uses `dispatcher` to determine which method to call."
|
||||||
|
(setmetatable {: dispatcher :methods {}} mm))
|
||||||
|
|
||||||
|
(fn mm.defmethod [{: methods} key method]
|
||||||
|
"Defines the method for a given key."
|
||||||
|
(tset methods key method))
|
||||||
|
|
||||||
|
mm
|
|
@ -39,10 +39,14 @@
|
||||||
|
|
||||||
(set package.watches {})
|
(set package.watches {})
|
||||||
|
|
||||||
(fn reload.modtime [modname]
|
(fn watchmeta [modname]
|
||||||
(playdate.file.modtime (package.pdzfilename modname)))
|
(let [filename (package.pdzfilename modname)]
|
||||||
|
(if (playdate.file.exists filename)
|
||||||
|
{:modtime (playdate.file.modtime filename)
|
||||||
|
:size (playdate.file.getSize filename)}
|
||||||
|
{})))
|
||||||
|
|
||||||
(fn reload.modtime= [time1 time2]
|
(fn modtime= [time1 time2]
|
||||||
(and (= time1.year time2.year)
|
(and (= time1.year time2.year)
|
||||||
(= time1.month time2.month)
|
(= time1.month time2.month)
|
||||||
(= time1.day time2.day)
|
(= time1.day time2.day)
|
||||||
|
@ -50,23 +54,29 @@
|
||||||
(= time1.minute time2.minute)
|
(= time1.minute time2.minute)
|
||||||
(= time1.second time2.second)))
|
(= time1.second time2.second)))
|
||||||
|
|
||||||
|
(fn should-reload? [watch1 watch2]
|
||||||
|
(and watch1.modtime watch2.modtime
|
||||||
|
(not= watch1.size watch2.size)
|
||||||
|
(not (modtime= watch1.modtime watch2.modtime))))
|
||||||
|
|
||||||
(fn reload.watch [modname]
|
(fn reload.watch [modname]
|
||||||
(when (and (= nil (. package.watches modname))
|
(when (and (= nil (. package.watches modname))
|
||||||
(playdate.file.exists (package.pdzfilename modname)))
|
(playdate.file.exists (package.pdzfilename modname)))
|
||||||
(tset package.watches modname {:modtime (reload.modtime modname)})))
|
(tset package.watches modname (watchmeta modname))))
|
||||||
|
|
||||||
(fn reload.check []
|
(fn reload.check []
|
||||||
(each [modname watch (pairs package.watches)]
|
(each [modname watch (pairs package.watches)]
|
||||||
(let [newmodtime (reload.modtime modname)]
|
(when watch.modtime
|
||||||
(when (not (reload.modtime= watch.modtime newmodtime))
|
(let [newmeta (watchmeta modname)]
|
||||||
(print (.. "Plugin reload: " modname))
|
(when (should-reload? watch newmeta)
|
||||||
(set watch.modtime newmodtime)
|
(print (.. "Plugin reload: " modname))
|
||||||
(reload.reload modname)))))
|
(tset package.watches modname newmeta)
|
||||||
|
(reload.reload modname))))))
|
||||||
|
|
||||||
(reload.watch :meta.proxy)
|
(reload.watch :meta.proxy)
|
||||||
(reload.watch :meta.iter)
|
(reload.watch :meta.iter)
|
||||||
(reload.watch :meta.table)
|
(reload.watch :meta.table)
|
||||||
|
|
||||||
(let [oldrequire _G.require]
|
(let [oldrequire _G.require]
|
||||||
(fn _G.require [modname]
|
(fn _G.require [modname]
|
||||||
(when (= nil (. package.loaded modname))
|
(when (= nil (. package.loaded modname))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(local {: ivalues} (require :meta.iter))
|
(local {: ivalues : reverse-ipairs} (require :meta.iter))
|
||||||
(local tbl {})
|
(local tbl {})
|
||||||
|
|
||||||
; Naming convention: Verb means mutation, noun / adjective means no mutation
|
; Naming convention: Verb means mutation, noun / adjective means no mutation
|
||||||
|
@ -45,6 +45,12 @@
|
||||||
(icollect [_ v (ipairs t-concat) &into t] v))
|
(icollect [_ v (ipairs t-concat) &into t] v))
|
||||||
t)
|
t)
|
||||||
|
|
||||||
|
(fn tbl.remove-matching [t f]
|
||||||
|
(let [indexes (icollect [i v (ipairs t)] (when (f v i) i))]
|
||||||
|
(each [i _ (reverse-ipairs indexes)]
|
||||||
|
(table.remove t i)))
|
||||||
|
t)
|
||||||
|
|
||||||
(fn tbl.extended [...]
|
(fn tbl.extended [...]
|
||||||
(tbl.extend {} ...))
|
(tbl.extend {} ...))
|
||||||
|
|
||||||
|
|
1
src/state.fnl
Normal file
1
src/state.fnl
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -1 +0,0 @@
|
||||||
{:x :suppery :z 3}
|
|
Loading…
Reference in a new issue