real bomb-dropping logic

This commit is contained in:
Jeremy Penner 2023-10-28 21:52:36 -04:00
parent 945614d3b4
commit 8f687bbf80
3 changed files with 64 additions and 50 deletions

View file

@ -51,7 +51,4 @@
(each [type _ (pairs cache.caches)] (each [type _ (pairs cache.caches)]
(cache.destroy type))) (cache.destroy type)))
(import :CoreLibs/sprites)
(cache.register-asset :sprite #(doto (playdate.graphics.sprite.new) (: :add)) #($1:remove))
cache cache

View file

@ -4,10 +4,10 @@
(local iter (require :meta.iter)) (local iter (require :meta.iter))
(local state (require :state)) (local state (require :state))
(local cache (require :cache)) (local cache (require :cache))
(local {: make-image : defsprite : sprite : with-image : with-collision} (require :sprite))
(local gfx playdate.graphics) (local gfx playdate.graphics)
(local draw (defmulti #$1))
(local update (defmulti #$1)) (local update (defmulti #$1))
(local children (defmulti #$2)) (local children (defmulti #$2))
(local scene (defmulti #$1)) (local scene (defmulti #$1))
@ -23,7 +23,6 @@
(each [_ index (ipairs (tbl.sorted indexes #(> $1 $2)))] (each [_ index (ipairs (tbl.sorted indexes #(> $1 $2)))]
(destroy-item type (get-id ?f-id index ctx type) ctx index))) (destroy-item type (get-id ?f-id index ctx type) ctx index)))
(draw:defmethod :default #nil)
(update:defmethod :default #nil) (update:defmethod :default #nil)
(children:defmethod :default (fn [val] (iter.ivalues val))) (children:defmethod :default (fn [val] (iter.ivalues val)))
(scene:defmethod :default #nil) (scene:defmethod :default #nil)
@ -41,14 +40,8 @@
:bombs [] :bombs []
:bucket {:count 3} :bucket {:count 3}
:level 1 :level 1
:state :waiting
:scene :ingame})) :scene :ingame}))
(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 iter.reverse-ipairs) (children:defmethod :bombs iter.reverse-ipairs)
(when (= state.level nil) (when (= state.level nil)
@ -57,22 +50,6 @@
(local screenw (playdate.display.getWidth)) (local screenw (playdate.display.getWidth))
(local screenh (playdate.display.getHeight)) (local screenh (playdate.display.getHeight))
(fn make-image [w h f]
(let [image (gfx.image.new w h)]
(gfx.pushContext image)
(f image w h)
(gfx.popContext)
image))
(fn defsprite [type f] (cache.register-initializer :sprite type f))
(fn sprite [type ?id] (cache.get :sprite type ?id))
(fn with-image [spr image center-x center-y]
(doto spr (: :setImage image) (: :setCenter center-x center-y)))
(fn with-collision [spr groupmask collidemask ?colliderect]
(doto spr (: :setGroupMask groupmask) (: :setCollidesWithGroupsMask collidemask)
(: :setCollideRect (if ?colliderect ?colliderect (values 0 0 (spr:getSize))))))
(let [bucketw 50 bucketh 10 radius 4 (let [bucketw 50 bucketh 10 radius 4
xoffset (/ bucketw 2) xoffset (/ bucketw 2)
buckety 200 buckety 200
@ -82,33 +59,53 @@
(fn lose-life [ctx] (fn lose-life [ctx]
(let [count ctx.bucket.count] (let [count ctx.bucket.count]
(set ctx.bucket.count (- count 1)) (set ctx.bucket.count (- count 1))
(set ctx.bomber.bombs-left 0)
(cache.destroy :bucket count) (cache.destroy :bucket count)
(destroy-all :bombs ctx) (destroy-all :bombs ctx)
(set ctx.bombs []) (set ctx.bombs [])))
(set ctx.state :waiting)))
(update:defmethod :bucket (fn [_ bucket] (update:defmethod :bucket (fn [_ bucket]
(let [crank (playdate.getCrankPosition) (let [crank (playdate.getCrankPosition)
ratio (if (> crank 180) (/ (- 360 crank) -130) (/ crank 130)) ratio (if (> crank 180) (/ (- 360 crank) -130) (/ crank 130))
clamped (if (< ratio -1) -1
(> ratio 1) 1
ratio)
x (* (/ (+ ratio 1) 2) screenw)] x (* (/ (+ ratio 1) 2) screenw)]
(for [ibucket 1 bucket.count] (for [ibucket 1 bucket.count]
(let [buckety (- 220 (* (- ibucket 1) 25))] (let [buckety (- 220 (* (- ibucket 1) 25))]
(doto (sprite :bucket ibucket) (: :moveTo x buckety))))))) (doto (sprite :bucket ibucket) (: :moveTo x buckety)))))))
(fn drop-bomb [ctx]
(table.insert ctx.bombs {:x ctx.bomber.x :y 30}))
(let [image (make-image 20 30 #(gfx.fillRoundRect 0 0 20 30 6))] (let [image (make-image 20 30 #(gfx.fillRoundRect 0 0 20 30 6))]
(defsprite :bomber #(with-image $1 image 0.5 0)) (defsprite :bomber #(with-image $1 image 0.5 0)))
(draw:defmethod :bomber (fn [_ {: x}]
(doto (sprite :bomber) (: :moveTo x 5)))))
(update:defmethod :bomber (fn [_ _ _ ctx] (fn bomberspeed [ctx] (* (+ ctx.level 4) 2))
(fn bombervelocity [ctx dx]
(let [sign (if (< dx 0) -1 1)
speed (math.min (bomberspeed ctx) (math.abs dx))]
(* speed sign)))
(fn bombspeed [ctx] (+ ctx.level 3))
(fn bombcount [ctx] 50)
(fn bombdropframecount [ctx]
(math.ceil (/ 18 (bombspeed ctx))))
(fn drop-bomb [ctx]
(when (> ctx.bomber.bombs-left 0)
(table.insert ctx.bombs {:x ctx.bomber.x :y 30})
(set ctx.bomber.bombs-left (- ctx.bomber.bombs-left 1))
(set ctx.bomber.bombframes (bombdropframecount ctx))
true))
(update:defmethod :bomber (fn [_ bomber _ ctx]
(when (> bomber.bombs-left 0)
(when (or (= bomber.target-x nil) (= bomber.x bomber.target-x))
(set bomber.target-x (math.random 10 (- screenw 10))))
(set bomber.x (+ bomber.x (bombervelocity ctx (- bomber.target-x bomber.x))))
(set bomber.bombframes (- bomber.bombframes 1))
(when (<= bomber.bombframes 0)
(drop-bomb ctx)))
(doto (sprite :bomber) (: :moveTo bomber.x 5))
(when (playdate.buttonJustPressed :a) (when (playdate.buttonJustPressed :a)
(set ctx.state :bombing) (set bomber.bombs-left (bombcount ctx))
(drop-bomb ctx)) (drop-bomb ctx))
(when (playdate.buttonJustPressed :b) (when (playdate.buttonJustPressed :b)
(set ctx.bucket.count 3)))) (set ctx.bucket.count 3))))
@ -118,19 +115,15 @@
(let [image (make-image 14 14 #(gfx.fillCircleAtPoint 7 7 7))] (let [image (make-image 14 14 #(gfx.fillCircleAtPoint 7 7 7))]
(defsprite :bombs #(doto $1 (with-image image 0.5 0.5) (with-collision 2 1) (tset :bomb $3)))) (defsprite :bombs #(doto $1 (with-image image 0.5 0.5) (with-collision 2 1) (tset :bomb $3))))
(fn bombspeed [ctx] (+ ctx.level 3))
(update:defmethod :bombs (fn [_ bomb ibomb ctx] (update:defmethod :bombs (fn [_ bomb ibomb ctx]
(when (= ctx.state :bombing) (let [spr (doto (sprite :bombs bomb) (: :moveTo bomb.x bomb.y))
(let [spr (doto (sprite :bombs bomb) (: :moveTo bomb.x bomb.y)) (_ y _ count) (spr:moveWithCollisions bomb.x (+ bomb.y (bombspeed ctx)))]
(_ y _ count) (spr:moveWithCollisions bomb.x (+ bomb.y (bombspeed ctx)))] (if (> count 0) (destroy-item :bombs bomb ctx ibomb)
(if (> count 0) (destroy-item :bombs bomb ctx ibomb) (> y screenh) (lose-life ctx)
(> y screenh) (lose-life ctx) (set bomb.y y)))))
(set bomb.y y))))))
(fn scene-update [keys ctx] (fn scene-update [keys ctx]
(do-to-children keys update ctx) (do-to-children keys update ctx))
(do-to-children keys draw ctx))
(scene:defmethod :ingame #(scene-update [:bomber :bombs :bucket] $2)) (scene:defmethod :ingame #(scene-update [:bomber :bombs :bucket] $2))

24
src/sprite.fnl Normal file
View file

@ -0,0 +1,24 @@
(local cache (require :cache))
(import :CoreLibs/sprites)
(cache.register-asset :sprite #(doto (playdate.graphics.sprite.new) (: :add)) #($1:remove))
(local gfx playdate.graphics)
(fn make-image [w h f]
(let [image (gfx.image.new w h)]
(gfx.pushContext image)
(f image w h)
(gfx.popContext)
image))
(fn defsprite [type f] (cache.register-initializer :sprite type f))
(fn sprite [type ?id] (cache.get :sprite type ?id))
(fn with-image [spr image center-x center-y]
(doto spr (: :setImage image) (: :setCenter center-x center-y)))
(fn with-collision [spr groupmask collidemask ?colliderect]
(doto spr (: :setGroupMask groupmask) (: :setCollidesWithGroupsMask collidemask)
(: :setCollideRect (if ?colliderect ?colliderect (values 0 0 (spr:getSize))))))
{: make-image : defsprite : sprite : with-image : with-collision}