From a6f9dabd886df60292088a203fa59220062df429 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Mon, 3 Mar 2025 19:18:15 -0500 Subject: [PATCH] Burger -> Cart Add several sprite-based ingredients! Centralizing caching in the new ingredients.lua --- Makefile | 2 +- README.md | 2 +- src/assets.lua | 29 ++++++++++++++ src/assets.lua2p | 33 ++++++++++++++++ src/assets/images/CartSprite.png | Bin 0 -> 4521 bytes src/assets/images/CheeseSprite.png | Bin 0 -> 761 bytes src/assets/images/LettuceSprite.png | Bin 0 -> 719 bytes src/assets/images/MushroomSprite.png | Bin 0 -> 701 bytes src/assets/images/TomatoSprite.png | Bin 0 -> 8821 bytes src/burger.lua | 32 --------------- src/cart.lua | 27 +++++++++++++ src/ingredients/booster.lua | 45 --------------------- src/ingredients/cheese.lua | 22 +++++++++++ src/ingredients/ingredients.lua | 50 ++++++++++++++++++++++++ src/ingredients/lettuce.lua | 22 +++++++++++ src/ingredients/mushroom.lua | 22 +++++++++++ src/ingredients/tomato.lua | 46 +++++++--------------- src/main.lua | 56 ++++++++++++++------------- src/systems/collision-detection.lua | 4 +- src/systems/collision-resolution.lua | 22 +++++------ src/systems/draw.lua | 8 ++-- src/systems/filter-types.lua | 16 +++++--- src/systems/offscreen.lua | 20 ++++++++++ 23 files changed, 297 insertions(+), 161 deletions(-) create mode 100644 src/assets.lua create mode 100644 src/assets.lua2p create mode 100644 src/assets/images/CartSprite.png create mode 100644 src/assets/images/CheeseSprite.png create mode 100644 src/assets/images/LettuceSprite.png create mode 100644 src/assets/images/MushroomSprite.png create mode 100644 src/assets/images/TomatoSprite.png delete mode 100644 src/burger.lua create mode 100644 src/cart.lua delete mode 100644 src/ingredients/booster.lua create mode 100644 src/ingredients/cheese.lua create mode 100644 src/ingredients/ingredients.lua create mode 100644 src/ingredients/lettuce.lua create mode 100644 src/ingredients/mushroom.lua create mode 100644 src/systems/offscreen.lua diff --git a/Makefile b/Makefile index e825dcf..d09cc46 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: pdc --skip-unknown src Luncher.pdx assets: - # lua lib/preprocess-cl.lua src/assets.lua2p + lua lib/preprocess-cl.lua src/assets.lua2p check: assets stylua -c --indent-type Spaces src/ diff --git a/README.md b/README.md index 23438e5..a7f765e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Luncher -Build the BIGGEST burger by **lunching** it through *delicious* ingredients. +Load up the BIGGEST cart by **lunching** it through *delicious* ingredients. diff --git a/src/assets.lua b/src/assets.lua new file mode 100644 index 0000000..fd14996 --- /dev/null +++ b/src/assets.lua @@ -0,0 +1,29 @@ +-- GENERATED FILE - DO NOT EDIT +-- Instead, edit the source file directly: assets.lua2p. + +-- luacheck: ignore +---@type pd_image +CartSprite = playdate.graphics.image.new("assets/images/CartSprite.png") + +-- luacheck: ignore +---@type pd_image +CheeseSprite = playdate.graphics.image.new("assets/images/CheeseSprite.png") + +-- luacheck: ignore +---@type pd_image +LettuceSprite = playdate.graphics.image.new("assets/images/LettuceSprite.png") + +-- luacheck: ignore +---@type pd_image +MushroomSprite = playdate.graphics.image.new("assets/images/MushroomSprite.png") + +-- luacheck: ignore +---@type pd_image +TomatoSprite = playdate.graphics.image.new("assets/images/TomatoSprite.png") + + +-- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) +-- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) +-- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value) +-- return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft") +-- end)) diff --git a/src/assets.lua2p b/src/assets.lua2p new file mode 100644 index 0000000..99a0f6c --- /dev/null +++ b/src/assets.lua2p @@ -0,0 +1,33 @@ +!(function dirLookup(dir, extension, newFunc, type, sep, indent, handle) + indent = indent or "" + sep = sep or "\n\n" + handle = handle ~= nil and handle or function(varName, value) + return varName .. ' = ' .. value + end + + local p = io.popen('find src/' .. dir .. ' -maxdepth 1 -type f | sort -h') + + local assetCode = "" + --Loop through all files + for file in p:lines() do + if file:find(extension) then + local varName = file:gsub(".*/(.*)." .. extension, "%1") + file = file:gsub("src/", "") + assetCode = assetCode .. indent .. '-- luacheck: ignore\n' + assetCode = assetCode .. indent .. '---@type ' .. type ..'\n' + assetCode = assetCode .. indent .. handle(varName, newFunc .. '("' .. file .. '")') .. sep + end + end + return assetCode +end +function generatedFileWarning() + -- Only in a function to make clear that THIS .lua2p is not the generated file! + return "-- GENERATED FILE - DO NOT EDIT\n-- Instead, edit the source file directly: assets.lua2p." +end)!!(generatedFileWarning()) + +!!(dirLookup('assets/images', 'png', 'playdate.graphics.image.new', 'pd_image')) +-- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) +-- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) +-- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value) +-- return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft") +-- end)) diff --git a/src/assets/images/CartSprite.png b/src/assets/images/CartSprite.png new file mode 100644 index 0000000000000000000000000000000000000000..d45eebc44ce80c2ddfdeaa0d767f091d4212a122 GIT binary patch literal 4521 zcmeHLe{d639^W>V##TBYMJz?wZcndOHoMtP+H58%mZY?)21{G}V=TSyue58EY`WPt zDINz0N-1}G1w0SAs(32iDThaa8xBN3I0~r9`Gc9`6mO<;Xa~1lJ*5Coa-DRWmsJr_!raTv@ z^Y}cTyAdPk(m|1eB!Q&aCB@||kdu=Phym(NP%@H|kz1kO0_9fFYxcTN(oK5(3beE1 zav#Wfahqh2&EPv7>itkCkTan^0Y&PHjr$SE+GEsTE=6QjQ9vV-+JcsPycI|p^l4*_ z)|wKfOlHzV+W?WItag%yH)^)otspQ+GO}({Dx$@3P4nG0HeYBao*PHn=j*qF{bQ2L zRpD{D(2yegB)^Ct(cYCCon=Swy?xy$+c#jdQ`0xtgx{Oa9a(T}SIzUr*^B>p=9RT4 zUs`qM#T-vtTV_Lg#>m2&I~sc1+e5Qcjx3lFIpXXk@xDcPmc}UwY=x*#)}*J<=%8tx`Xy_ueyAU<#wGp zUY@=CcYm1qz^u}0@5?{U8Q68I^B22ocJ^Ixex2@OR*Fww+_P@uVeBci_|Y|Ym**W_ z@?^&|nd$lVUww16tKpE_^jO24q_S{Z^7Ouoso$;r*Rht_t^D@*oY^VE;XZEIB z9)9BT%Fk_&&qA->(lCgxdMV@WpKWSvl{V&Xle72j3reTvhyG%?r6{W}|3GEWQ$6n* zhMI@H_1nI??X&vJ*Umcn2Ms;j8}F1?uXQ!;x%clEi-x`k4*lbh^_`LH$Z0}(i(CJG zA#CKRR9&amdGELLa=^q2GAEj%fsnqCjz!TB%eRUu%8AWV(1{HlIE0~+;KXXJUeX(K zi7isu3Pr41v9y|B(aJLdwx}r05w!zAKvY>Y8t@0h_NWunaqS>$Y63%b6SdWe)xmai z$%=?tOcoP~mqeuw3M)!O9g5(ySGt$PA)w{NT2wV;Cx}QSVv5ivS!pKB48ss4MNkwD z7I?TbsIpN!7|zuoVi;~Q%qvnzmE<6*VX~aut~xOc`q9z(1wvkL0zMdyvjBV$Q8q-F zO(YQr5aT_ zZF(NJ6Vt}G3o7m{O{DAU(R7WIkicWp z*WkReAo)7~m$i0yPzTtFm@7W3*=d=14%A&0rjavjOiL(WT1-O~AQkhYGO4jK$|tT#WLag7F5mReG$y5xZNs~oxE(p~%Wj5%QRk;h$JUDm(%*Y{YcJ)mzwpoHXn*RXsJ_(rs literal 0 HcmV?d00001 diff --git a/src/assets/images/CheeseSprite.png b/src/assets/images/CheeseSprite.png new file mode 100644 index 0000000000000000000000000000000000000000..5766c77172a6d2acdbfa4571df1be812a6a8c6ba GIT binary patch literal 761 zcmVEX>4Tx04R}tkv&MmP!xqvQ>9WW4t5Z6$WWc^q9Ts96^c+H)C#RSn7s54nlvOS zE{=k0!NH%!s)LKOt`4q(Aov5~E;uQ=NQw6)g%&Yhc)XAE?m4`7A0V`9OtbnDfTr7K zHk}mng;g>1iXa385QZo-%b1s>41DYBo;s=S;yla0@6Q@kixvX{B5{HlrcJy-JiBQd zocD>NtRkz#=fsmHU6A;Z>x##3oXai?JTq$MvMJ&yu~_b5rH5I?)QD$@W2&Z8zL57= z<-EmNt2J2Xp8SQ8qQ0`sby{OcV-ZV`AVNU{Rn%Z3PPP6m>(8*zxhQ$qB|TwshRSGyttDe8gKMs(Wh8$bP%SgQcTj2$?-r&9?m3Ru`5Qd zjhz3*@FrWyq7(8s>x{KOEYEw&uTYk;HZ&n~$USt3$fVVxjJpb!op*^VLS4h~p`@#( zB53joXj6K~X~S8XN%LK?y=R2c@iU6(DRa+UJMElYZd#mzI(E&38fvsQ+Gq+if=v_f rf>P)N5WtCMTAmV_M!H{mI8E>aRAqh{L`CIb00000NkvXXu0mjf#6?GY literal 0 HcmV?d00001 diff --git a/src/assets/images/LettuceSprite.png b/src/assets/images/LettuceSprite.png new file mode 100644 index 0000000000000000000000000000000000000000..793cd72938c3bf6d541a9a8f523c95cc63d86384 GIT binary patch literal 719 zcmV;=0xEX>4Tx04R}tkv&MmP!xqvQ>9WW4t5Z6$WWc^q9Ts96^c+H)C#RSn7s54nlvOS zE{=k0!NH%!s)LKOt`4q(Aov5~E;uQ=NQw6)g%&Yhc)XAE?m4`7A0V`9OtbnDfTr7K zHk}mng;g>1iXa385QZo-%b1s>41DYBo;s=S;yla0@6Q@kixvX{B5{HlrcJy-JiBQd zocD>NtRkz#=fsmHU6A;Z>x##3oXai?JTq$MvMJ&yu~_b5rH5I?)QD$@W2&Z8zL57= z<-EmNt2J2Xp8SQ8qQ0`sby{OcV-ZV`AVNU{Rn%Z3PPK>y4PzIy{yI;mOucFJoN8XpIV#GnXb%%rwf0#B zG>YoWj@E*lsDG$-2{fc2p2wl8Z4FNJQ>WlQ3=hoEY!iZnwu%4%002ovPDHLkV1hTy BDnI}L literal 0 HcmV?d00001 diff --git a/src/assets/images/MushroomSprite.png b/src/assets/images/MushroomSprite.png new file mode 100644 index 0000000000000000000000000000000000000000..bee4471e6f6587c913dde8490f67337e768a1332 GIT binary patch literal 701 zcmV;u0z&EX>4Tx04R}tkv&MmKp2MKrivmJ2MdZgWT-CM!5_r2R-p(LLaorMgUO|T(4-+r zad8w}3l9D)RvlcNb#-tR1i>E=cfm=~MN0fGDYS_3j^iHQ``(wk?*O4*W}4Lz12o+> zQ;E2k$*ziBuL#l{zy!u*W*Kvml!Wj2x<`QTcTt|@U-#$eRdW^t0wQsY8KzCVK|Hf* z8=Uuv!>lN)#OK80CS8#Dk?V@bZ=4G*3p_Jyrc?98VPdh+#!4HrqNx#26Gv1{r+gvf zvC4UivsSLM<~{ifLpgnAnd`KMk-#FBAVGwJDoQBBMwE7)6bmUjkNfzCT)#vvgpt)9ZtvT_HO>D00M0LR%W7L0@Bjb+24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2k8R@001-;>G{|I000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0001#Nkl0(wG@zl5v@F$sv^^rJ}o2k#x~1 zA(conxpY-h$BA;Ms8FPkVfMTBpvyVu{hYVo@Av-m`LU!Gw+^lt~hjKoOqPU?D?U4W7@z!buz-s}#yL zu*ix(PEbOTC(lcqUEFlZMkJz|BG?tk0TCF- zMv*3cLSZL;Lgh)H7DE{`VJ{jPnJ;AZ2^sZWLUJ6_3GF)}_bQ_UOxljrBdtJrsiU(a z90+v-{vZv&4#>*LU}dCbu~@8}oUFWpnxev#DGC~@)0EU^YwBpv*3{C{ool48i(90p zrDb5YU=fi-p-^=6Ev(JSRz}7YG72IgCnu*cMPa6*;!N@!tvTdxK9CzgMHaOQBY^{w zDiRnK38WI}Ks%)+#K*WRsG}GuX&J1noct81P@s%P3L`0nk(QQ{f~~Qz9Z0E2tIi?W z%1m29$KpcO$XoVi%IYo7FH>LnsBf;ZU)WYT`ROxeYG}@zuWztmA;rYh%-n)%XYb&+ z#L0Q7yT_{4o?btAGng!Yb^vERj~^Zp8MQGw{^x{kiQ9K1?c0Cg;GxuC4j(yj^3>_9 zGryiack$BYf-8kZSBuLlDsSGpedq4I$G_G7{-mz{>9e->j^{5ryI#I}-T!Xj{fEJ! z;g2JzU#Opx$GB&I@Jj{yB`GC^k;0;WNk~Sbj;lyX&mqaE+OELTL#N@$TV&N1@6F6F zlhZR^*{ALo_DFvETuR%#e$+LwXaAXFTmMI%eRAxxU(bL7MgmSAMg`EoM^Tc&amoMB zrNGK0tK$4{w$tM`nhskB2WM^6Bx9r_<(=;6ncHl;*zI27eSm6~bb0s6HfF%0JbKYy z2FUjasZ`iwyydk4=A~emt%F5C&9Wa6Am~Ft|2bM)T8s_?Z1Fr10xA%2>sJJ9OYVys z!-PK+_A4P^_DPYZWf=nAE7sB8R?F!*y+@*ITVMXS;h``^|r=PeS3Ug1t}U)&1`_CXs%& z9y7qipGYzQ|Go%Cn{B{}QUv5>Ab^wi@t~mhEdl~+u$xynsDTx}!Nb!;&RyFCJ?eo7 zIB}>1GnkBkeTiofP`{8iHVY38Q(N(!w3=rf0;B}b_q_BS>_@<9RX1#g=)Pcpf`EoI zq9=LB4Nh#9M+6hO&;X;xwo|>#H?v;s2bxf6|Sj` zjxWy}+`%Z9?a-yqoO(Wv`aW)WrLPk0TGr#$M{VHk#3RTf3>gX-JK2>6v%>Cj{&+l}120 zqg~h=CsL*5k7ZYl-L8*$aE;+1Y+hF#(RC)e3juA1<6d(Sa4#4ELC2Md!#*cC&3eNr zr(RJD1kV<+2TJY~UgS1Rx$weCZ;z5pX$k@o=JgGT65fuc7r|UP_;6Ui)pvAGGa(;N zRhyoW{WRubV{BqoQ?aS*^-e8DM07;ny5sVL(@jVG(}U=2oz%cURXcgE{(1umM^}9? zwP0XL?`#CjQ*uSX1&_E9Q}2;YrR&B{3Z7@aLcpLr9MQ1~X0(s?wEV)_QC4RC+9jRd zP3x!k-9Ng$aW`(8hSsjF(W`G)q)0+zJiBdh*!@9NU#s#| zxA;dXT|R1V*!{zo+OS(F4`sSj2cu`Ch6kQ$beS@i%PV+dx-i5SD>b#?-ObpR+*cV5 zo3v}+XIS19hM&69%x!8g%Un}`r`kA;=?Pb81sMUgO$a#9B5L?fTf!kAu$VolzdhVq zzj~mwA`)MCw2(WN>={80O=D}AWPCQz>q34}?T1-`Q_M%Jvd^xZ=^ipGeY-q4N@H&L zxeql_(?m;k;CeKK>+$63%~U0rmCA6{h_g9PWZ~;Ry!=+j_kG+%`bHhp_J#^F7aMqf z{Y+*^i0v!rpM=97%37uVytbC4k~JNMmSakA&76;pUi@%y`^kzObLZ0QwRh2|LrDgh zGLd|YWxwaoF|3Voxg1|+!G71MRiZ~~hk0|E3VPEXxxQH2k8;MJi$p&bvc~hw;Z#w1 zq3?)Ec1CXe?YMVtqst%*_~eag{{FD$lT~Z5TWC-`fW}d%1=&91^c+o{=<(;z4=DW0* z(MjOL(oYOB!9ss?P3-FPP2lFvD=O-HvYYbm>c+YI%ICBF!kp)YIa_s>7!M}aT#lV4 zQhC^uzVKE>wb1qO;4=QsO;+dG0UEblecgSR)IEfpRyTUDWpD@z0hk*GCz1eK;N{a) zk$;Ae4~g*i_tG(KLaV@Hn;i&{(;vK&&7gP19<36tDR&TPb3==Eb?BY>HIEm6>zI0R zQBreDWijQqdu@8jmcxhBciaFncjxvefyRH&?tjhvUsHYEMb{2j`DcyGfSa8o=Ilnm{=p36o>V!b`yaikABU!Cmu}l^ zWi$D_QLH2xch|13ZY&`v?)~~Y+SijAfax9io6!G}_-%CiTSgDiRN?(*bvGoK0v=of zZ{ZTy5!YiF4wr!U)e&)E(cl`|Ev`jCzLj0p`exVk!C6JQF*yy9Js}Oe_+1?uW#>l> zFfEY#vIMVJKq5^=zdy~?%9c^a^YLDMfC&T#% zI}7@yV+F0QAN7xELb6_!Cra`LFDG;G@6KJLkqDSOP$?LcFGj#47hh%129YJa?Qd-N z6-uv(dzqED{m+?|=ka)x&2YBkqx1Z0u{6hkML8XXyH9Ofd2_|$t)aRaH{Pqi;Jab# z^L~b0>7ti5n7*7Rspq`c zySw7M8x6g0?aEw=Ykd=LaZkJXAmr7GB~didmg26lVHnKh8tjD?YvIF`;%xL`N~Sww zs9i^7xwh;xtxod)m*s2WR9$;@ ze5*1x&z8-*~tsWM(=dc}1AHSiDX{@_mxUbnUS;I~`e4*3*pV`=&x`U4# zfZB?`F6x5_7}ejT1aEeEb_gijMH^ieW9tB71&}jZ;vw}1)*zsd0TtAj{O=Tpr23kC zZiWUg;@K|5COg%Wi}&ua)lyz!an>-SPk(g(L&doIg>?vU!1F)z{HmY2h1TTiWmUo= zJf3muH*AfXC%ij+SqIrj5i-om6p@EOxC#Vpsu_8ce7p7O#yhoB^A= zA^pL(5AN#KGr!yYIbz#GnLg_xO}QCwlDW&dvImT zuvg2|xPAlCLm~Dk0thzTF(Iw~M+RHqJ@A<`|Bej4r5$++oQg+Z!|i~0j-8#Gvz?u8 zNLa8xX9Ej>sI=I<)=m{}Y6-6Hr&lhV8lfC|$1T0*1TMKiJ;`lOt$Yskmy-8NM<{a_ z7$t8FEGx^nc`knErQE5xTXlyq?MCJcik)^0%}bb0S{qf8GVsQtBvMEB^7`*Dji_$U zYVbErR~txJMS7p4DBalu-V7&(%CbGWi)}HhYS-y4zqULnVNtq%?C8l{ zUtH?q+=VkOrn@D|JpB-ll)ZiGefre`!h(HLBfeT)3@zDS$=5NgD_OUx{lE)Q&Oq;{Fd zf-p+2jFXI8PH7qDzP!D}dt^9maBxUhct& z4rEv`aWorwt0*c22x9T+x=}$JxIAi(3j&c$Ad~S> z1JB#Y<74mCwMMzA__1b zgeZClfn-D^1O*Yk?7`zZL_m-UgZ{Dy&tqc!BI(H4T)}Re(HgSfXxXC5%+?@{z{Y2@&6pGuWUnG#O{1)2<-j| z_bcs5-^I#M%f*FiAIu0x&2zT5#-Za=nZXPWlPVTX{h4GFBAtZyW11836o#1@-j7Hk z<4F_~3sW;clE1O3$rn)0Tppj!Ww1~v2yVoII4lOym_#?WfE~^J@f1J0Io^W8pySDA zCZ=Q}i{#JpBYy$m8peTHN#F3LRVWk_LNQ513kK5!_O)P=@e~r-81F}>lkq10M6$o1 znK8wbLJ>nT8C1vMupl~|P7ZvtWf4NSY;gk`aH_4Fvo(%vMEqRiwt>#~haIeO-*dR( zQJ)(;I6*9TJ{^rF$&5lGQix;=W1_hQ#lrZr(rQ*14`w2YDc+zKx1iHPh0egh($PGH z0OES+3)L=+Mdt^Hc?1Vf z!Ay?-#=p}>7muzL)Q3~<#Nom5H;SvqSCl&|bo^@kasx-alyr5)i-JmLjJv?2N3fV; zJ0aG16C;4mWwRiAOr+~%J?Ae{fnsc7N-{C0<1NT$es~Iz>4*0-XBy)v6hAWx(Zqsf z?nnO`ofquSkEDmOY}qi5Fjg=<#eW9SH4snKg0HnB16b%Rz<}Y2#_&5CFer-yMwoDz zfO5v9$5w%uw3-FCG(f@n0MPLjN+4fi9JBj&++SL z_QM*v5T_q_08E*N771`9Z6>V5@||5Au&*$f>8grXn4M9uD#zL0*2C%cgM)4In~AbN zTel$Ty{={Rd9M%Q=lH1%r5{?#H-BE5yxG2~={x1irxQ~v&m8fR-u^xhTrrJkvLq_2 z^egD%(zj2qWoP58Brmt8TrybqUQ4t6Dn|M4al={U&9#Il-xZzTIjiEwy$MrAey07W z4vP>M{`_C>b?(LAwLkiz@{aGZJ3UwHAC#w;KW)}g?{lYc7^(`24b>naE@v hJ{=h&WB&V9Fmk~~$!+-sA~YO0J1n=)UA%7VzW}?$vwr{p literal 0 HcmV?d00001 diff --git a/src/burger.lua b/src/burger.lua deleted file mode 100644 index ddfa692..0000000 --- a/src/burger.lua +++ /dev/null @@ -1,32 +0,0 @@ -Burger = {} - -local gfx = playdate.graphics - -function Burger.reset(o) - o.position = { - x = 20, - y = 50, - } - o.velocity = { - x = 50 + (150 * math.random()), - y = 150 * (math.random() - 1), - } - o.size = { - x = 10, - y = 10, - } - o.canBeBounced = { - flat = { x = 0, y = 0 }, - mult = { x = 1, y = 1 }, - } - o.mass = T.marker - return o -end - -function Burger.new() - return setmetatable(Burger.reset({}), { __index = Burger }) -end - -function Burger:draw() - gfx.fillCircleAtPoint(burger.position.x, burger.position.y, 10) -end diff --git a/src/cart.lua b/src/cart.lua new file mode 100644 index 0000000..6dbc90a --- /dev/null +++ b/src/cart.lua @@ -0,0 +1,27 @@ +Cart = {} + +local sizeX, sizeY = CartSprite:getSize() +local size = { x = sizeX, y = sizeY * 0.75 } + +function Cart.reset(o) + o.position = { + x = 20, + y = 50, + } + o.velocity = { + x = 50 + (150 * math.random()), + y = 150 * (math.random() - 1), + } + o.size = size + o.canBeBounced = { + flat = { x = 0, y = 0 }, + mult = { x = 1, y = 1 }, + } + o.mass = T.marker + o.drawAsSprite = CartSprite + return o +end + +function Cart.new() + return setmetatable(Cart.reset({}), { __index = Cart }) +end diff --git a/src/ingredients/booster.lua b/src/ingredients/booster.lua deleted file mode 100644 index 89048d5..0000000 --- a/src/ingredients/booster.lua +++ /dev/null @@ -1,45 +0,0 @@ -Booster = {} - -local function newBooster(x, y) - local size = { x = 40, y = 10 } - return { - score = 1, - expireAfterCollision = true, - size = size, - position = { x = x, y = y }, - canBounce = { - flat = { x = 122, y = 190 }, - mult = { x = 1, y = -0.5 }, - }, - drawAsRectangle = { size = size }, - } -end - -boosterIndex = 1 -boosterCache = {} -for i = 1, 100 do - boosterCache[i] = newBooster(-999, 999) -end - -function Booster.cacheSize() - return #boosterCache -end - --- Boosters should be "initialized" almost always increasing in X value -function Booster.get(x, y) - local booster = boosterCache[boosterIndex] - booster.position.x = x - booster.position.y = y - - boosterIndex = boosterIndex + 1 - if boosterIndex > #boosterCache then - boosterIndex = 1 - end - - return booster -end - --- Assumes that at least one Booster has already been created. -function Booster.newestBooster() - return boosterCache[boosterIndex] -end diff --git a/src/ingredients/cheese.lua b/src/ingredients/cheese.lua new file mode 100644 index 0000000..17ed97d --- /dev/null +++ b/src/ingredients/cheese.lua @@ -0,0 +1,22 @@ +Cheese = {} + +local sizeX, sizeY = CheeseSprite:getSize() +local size = { x = sizeX, y = sizeY } +local expireWhenOffScreenBy = { x = 2000, y = 480 } + +local canBounce = { + flat = { x = 50, y = 390 }, + mult = { x = 0.7, y = -0.5 }, +} + +function Cheese.initialize(o, x, y) + o.score = 5 + o.expireAfterCollision = true + o.size = size + o.position = { x = x, y = y } + o.drawAsSprite = CheeseSprite + o.expireWhenOffScreenBy = expireWhenOffScreenBy + o.canBounce = canBounce + newestBooster = o + return newestBooster +end diff --git a/src/ingredients/ingredients.lua b/src/ingredients/ingredients.lua new file mode 100644 index 0000000..aad9298 --- /dev/null +++ b/src/ingredients/ingredients.lua @@ -0,0 +1,50 @@ +import("ingredients/cheese.lua") +import("ingredients/lettuce.lua") +import("ingredients/mushroom.lua") +import("ingredients/tomato.lua") + +---@class +Ingredients = {} + +local ingredientCache = {} + +local _ingredientCacheIndex = 1 +local maxCache = 100 +for i = 1, maxCache do + ingredientCache[i] = {} +end + +local newestIngredient = {} +function Ingredients.newestIngredient() + assert(newestIngredient.position ~= nil, "All ingredients are implicitly required to have a position component.") + return newestIngredient +end + +function Ingredients.cacheSize() + return maxCache +end + +function Ingredients.getNext(x, y) + local index = _ingredientCacheIndex + _ingredientCacheIndex = _ingredientCacheIndex + 1 + if _ingredientCacheIndex >= maxCache then + _ingredientCacheIndex = 1 + end + + local o = ingredientCache[index] + for key in pairs(o) do + o[key] = nil + end + newestIngredient = o + + local odds = math.random() + if odds > 0.3 then + return Lettuce.initialize(o, x, y) + elseif odds > 0.2 then + return Tomato.initialize(o, x, y) + elseif odds > 0.1 then + return Mushroom.initialize(o, x, 218 + math.random(1, 5)) + else + return Cheese.initialize(o, x, y) + end +end diff --git a/src/ingredients/lettuce.lua b/src/ingredients/lettuce.lua new file mode 100644 index 0000000..f28f284 --- /dev/null +++ b/src/ingredients/lettuce.lua @@ -0,0 +1,22 @@ +Lettuce = {} + +local sizeX, sizeY = LettuceSprite:getSize() +local size = { x = sizeX, y = sizeY / 2 } +local expireWhenOffScreenBy = { x = 2000, y = 480 } + +local canBounce = { + flat = { x = 22, y = 190 }, + mult = { x = 1, y = -0.5 }, +} + +function Lettuce.initialize(o, x, y) + o.score = 1 + o.expireAfterCollision = true + o.size = size + o.position = { x = x, y = y } + o.drawAsSprite = LettuceSprite + o.expireWhenOffScreenBy = expireWhenOffScreenBy + o.canBounce = canBounce + newestBooster = o + return newestBooster +end diff --git a/src/ingredients/mushroom.lua b/src/ingredients/mushroom.lua new file mode 100644 index 0000000..c251e1f --- /dev/null +++ b/src/ingredients/mushroom.lua @@ -0,0 +1,22 @@ +Mushroom = {} + +local sizeX, sizeY = MushroomSprite:getSize() +local size = { x = sizeX, y = sizeY } +local expireWhenOffScreenBy = { x = 2000, y = 480 } + +local canBounce = { + flat = { x = 0, y = 190 }, + mult = { x = 1, y = -2 }, +} + +function Mushroom.initialize(o, x, y) + o.score = 5 + o.expireAfterCollision = true + o.size = size + o.position = { x = x, y = y } + o.drawAsSprite = MushroomSprite + o.expireWhenOffScreenBy = expireWhenOffScreenBy + o.canBounce = canBounce + newestBooster = o + return newestBooster +end diff --git a/src/ingredients/tomato.lua b/src/ingredients/tomato.lua index 8bd8608..f4b65c9 100644 --- a/src/ingredients/tomato.lua +++ b/src/ingredients/tomato.lua @@ -1,36 +1,16 @@ Tomato = {} -local function newTomato(x, y) - local size = { x = 20, y = 20 } - return { - score = 15, - expireAfterCollision = true, - position = { x = x, y = y }, - size = size, - drawAsRectangle = { size = size }, - } -end - -local tomatoIndex = 1 -local tomatoCache = {} -for i = 1, 100 do - tomatoCache[i] = newTomato(-999, 999) -end - -function Tomato.cacheSize() - return #tomatoCache -end - --- Tomatos should be "initialized" almost always increasing in X value -function Tomato.get(x, y) - local tomato = tomatoCache[tomatoIndex] - tomato.position.x = x - tomato.position.y = y - - tomatoIndex = tomatoIndex + 1 - if tomatoIndex > #tomatoCache then - tomatoIndex = 1 - end - - return tomato +local sizeX, sizeY = TomatoSprite:getSize() +local size = { x = sizeX, y = sizeY } +local expireWhenOffScreenBy = { x = 2000, y = 480 } + +function Tomato.initialize(o, x, y) + o.score = 15 + o.expireAfterCollision = true + o.size = size + o.position = { x = x, y = y } + o.drawAsSprite = TomatoSprite + o.expireWhenOffScreenBy = expireWhenOffScreenBy + newestBooster = o + return newestBooster end diff --git a/src/main.lua b/src/main.lua index d7dcc46..32ff6a8 100644 --- a/src/main.lua +++ b/src/main.lua @@ -11,22 +11,22 @@ import 'CoreLibs/utilities/where.lua' import("../lib/tiny.lua") import("tiny-tools.lua") +import("assets.lua") import("systems/filter-types.lua") import("systems/collision-detection.lua") import("systems/collision-resolution.lua") import("systems/draw.lua") import("systems/gravity.lua") import("systems/velocity.lua") -import("ingredients/booster.lua") -import("ingredients/tomato.lua") -import("burger.lua") +import("ingredients/ingredients.lua") +import("cart.lua") local tiny = tiny local gfx = playdate.graphics playdate.display.setRefreshRate(50) gfx.setBackgroundColor(gfx.kColorWhite) -burger = Burger.new() +cart = Cart.new() local floorSize = { x = 10000, y = 10 } floor = { position = { x = 0, y = 235 }, @@ -40,6 +40,7 @@ floor = { } Camera = { + --- The upper-left corner of the Camera is represented by this `pan` value pan = { x = 0, y = 0, @@ -65,38 +66,43 @@ world = tiny.world( velocitySystem, collisionResolution, collisionDetection, - drawSystem, - drawRectanglesSystem, - burger, + drawRectanglesSystem, + drawSpriteSystem, + + cart, floor ) -for i = 1, Booster.cacheSize() do - world:addEntity(Booster.get(i * 60 + (math.random(0, 50)), math.random(50, 200))) +local ingredientsEveryX = 50 + +local function init() + for i = 1, Ingredients.cacheSize() do + world:addEntity(Ingredients.getNext(i * ingredientsEveryX + (math.random(0, 20)), math.random(50, 200))) + end end +init() + function playdate.update() local deltaSeconds = playdate.getElapsedTime() playdate.resetElapsedTime() gfx.clear(gfx.kColorWhite) playdate.drawFPS(5, 5) - Camera.pan.x = math.min(0, -burger.position.x + 200) - Camera.pan.y = math.max(0, -burger.position.y + 120) - local newestX = Booster.newestBooster().position.x - local panX = -Camera.pan.x + Camera.pan.x = math.max(0, cart.position.x - 200) + Camera.pan.y = math.min(0, cart.position.y - 120) + + local newestX = Ingredients.newestIngredient().position.x + local panX = Camera.pan.x + local rightEdge = panX + 400 local offset = 600 - if newestX + 300 < panX then - if math.random() > 0.5 then - world:addEntity(Tomato.get(panX + offset + (math.random(0, 50)), math.random(-500, 150))) - else - -- Implicitly updates cached boosters - Booster.get(panX + offset + (math.random(0, 50)), math.random(-500, 150)) - end + while newestX < (rightEdge + 100) do + newestX = newestX + ingredientsEveryX + world:addEntity(Ingredients.getNext(newestX, math.random(-500, 150))) end - floor.position.x = -Camera.pan.x - offset - gfx.setDrawOffset(Camera.pan.x, Camera.pan.y) + floor.position.x = Camera.pan.x - offset + gfx.setDrawOffset(-Camera.pan.x, -Camera.pan.y) world:update(deltaSeconds) @@ -104,9 +110,7 @@ function playdate.update() Score:draw() if playdate.buttonJustPressed(playdate.kButtonA) then - Burger.reset(burger) - for i = 1, Booster.cacheSize() do - Booster.get(i * 60 + (math.random(0, 50)), math.random(50, 200)) - end + Cart.reset(cart) + init() end end diff --git a/src/systems/collision-detection.lua b/src/systems/collision-detection.lua index 744311a..8e853da 100644 --- a/src/systems/collision-detection.lua +++ b/src/systems/collision-detection.lua @@ -1,8 +1,8 @@ collisionDetection = filteredSystem( { position = T.XyPair, size = T.XyPair, isSolid = Maybe(T.bool) }, - -- Here, the entity, e, refers to some entity that the burger global(!) may be colliding with. + -- Here, the entity, e, refers to some entity that the cart global(!) may be colliding with. function(e, _, system) - local collider = burger + local collider = cart if not collider.velocity then return end diff --git a/src/systems/collision-resolution.lua b/src/systems/collision-resolution.lua index 86379ee..e41a550 100644 --- a/src/systems/collision-resolution.lua +++ b/src/systems/collision-resolution.lua @@ -1,29 +1,29 @@ collisionResolution = filteredSystem({ collisionBetween = T.Collision }, function(e, _, system) - local collider, probablyBurger = e.collisionBetween[1], e.collisionBetween[2] + local collider, probablyCart = e.collisionBetween[1], e.collisionBetween[2] local colliderTop = collider.position.y if collider.isSolid then -- Assumes impact from the top - probablyBurger.position.y = colliderTop - probablyBurger.size.y + probablyCart.position.y = colliderTop - probablyCart.size.y end - if collider.canBounce and probablyBurger.canBeBounced then - probablyBurger.velocity.x = probablyBurger.velocity.x + if collider.canBounce and probablyCart.canBeBounced then + probablyCart.velocity.x = probablyCart.velocity.x + collider.canBounce.flat.x - + probablyBurger.canBeBounced.flat.x + + probablyCart.canBeBounced.flat.x - probablyBurger.velocity.x = probablyBurger.velocity.x + probablyCart.velocity.x = probablyCart.velocity.x * collider.canBounce.mult.x - * probablyBurger.canBeBounced.mult.x + * probablyCart.canBeBounced.mult.x -- abs() makes sure we always push upward - probablyBurger.velocity.y = math.abs(probablyBurger.velocity.y) + probablyCart.velocity.y = math.abs(probablyCart.velocity.y) + collider.canBounce.flat.y - + probablyBurger.canBeBounced.flat.y + + probablyCart.canBeBounced.flat.y - probablyBurger.velocity.y = probablyBurger.velocity.y + probablyCart.velocity.y = probablyCart.velocity.y * collider.canBounce.mult.y - * probablyBurger.canBeBounced.mult.y + * probablyCart.canBeBounced.mult.y end if collider.score then diff --git a/src/systems/draw.lua b/src/systems/draw.lua index fd293a8..229dc2d 100644 --- a/src/systems/draw.lua +++ b/src/systems/draw.lua @@ -1,9 +1,9 @@ local gfx = playdate.graphics -drawSystem = filteredSystem({ draw = T.SelfFunction }, function(e, dt) - e:draw() -end) - drawRectanglesSystem = filteredSystem({ position = T.XyPair, drawAsRectangle = { size = T.XyPair } }, function(e, dt) gfx.fillRect(e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y) end) + +drawSpriteSystem = filteredSystem({ position = T.XyPair, drawAsSprite = T.PdImage }, function(e, dt, system) + e.drawAsSprite:draw(e.position.x, e.position.y) +end) \ No newline at end of file diff --git a/src/systems/filter-types.lua b/src/systems/filter-types.lua index 14c0439..f8c3297 100644 --- a/src/systems/filter-types.lua +++ b/src/systems/filter-types.lua @@ -7,9 +7,11 @@ ---@type Entity local Entity = {} +---@type XyPair +local XyPair = { x = 1, y = 1 } + T = { - ---@type XyPair - XyPair = { x = 1, y = 1 }, + XyPair = XyPair, bool = true, number = 0, numberArray = { 1, 2, 3 }, @@ -20,16 +22,18 @@ T = { --- Actor CanBounce = { isSolid = true, - flat = { x = 1, y = 1 }, - mult = { x = 1, y = 1 }, + flat = XyPair, + mult = XyPair, }, --- Receiver CanBeBounced = { - flat = { x = 1, y = 1 }, - mult = { x = 1, y = 1 }, + flat = XyPair, + mult = XyPair, }, ---@type Collision Collision = { Entity, Entity }, + ---@type pd_image + PdImage = {}, } ---@generic T diff --git a/src/systems/offscreen.lua b/src/systems/offscreen.lua new file mode 100644 index 0000000..67513b9 --- /dev/null +++ b/src/systems/offscreen.lua @@ -0,0 +1,20 @@ +local screenWidth, screenHeight = 400, 240 + +offscreenSystem = filteredSystem({ position = T.XyPair, expireWhenOffScreenBy = T.XyPair }, function(e, dt, system) + -- if Camera.pan.x - e.expireWhenOffScreenBy.x > e.position.x then + -- print("Fell behind") + -- system.world:removeEntity(e) + -- end + -- if Camera.pan.x + screenWidth + e.expireWhenOffScreenBy.x < e.position.x then + -- print("Too far ahead") + -- system.world:removeEntity(e) + -- end + -- if Camera.pan.y - e.expireWhenOffScreenBy.y > e.position.y then + -- print("Too high") + -- system.world:removeEntity(e) + -- end + -- if Camera.pan.y + screenHeight + e.expireWhenOffScreenBy.y < e.position.y then + -- print("Too low") + -- system.world:removeEntity(e) + -- end +end)