From e7792002cb3d1e0fa82da738391ed7cead104778 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Wed, 21 Apr 2021 15:15:57 +0200 Subject: [PATCH] add inventory --- src/builtin/touch.png | Bin 16909 -> 16896 bytes src/components/inventory.rs | 342 ++++++++++++++++++++++++++- src/components/stage_select.rs | 12 +- src/engine_constants/mod.rs | 16 ++ src/input/touch_controls.rs | 9 +- src/input/touch_player_controller.rs | 16 +- src/scene/game_scene.rs | 4 +- 7 files changed, 378 insertions(+), 21 deletions(-) diff --git a/src/builtin/touch.png b/src/builtin/touch.png index cd65c51d309f67933012a1e64dbe9cdf1654d5f2..750980eb3d28b0c017c81ce9bd7c010f71bcf788 100644 GIT binary patch delta 11052 zcmV+{E7R1CgaLqr0gxjCF7c5iAAebPB)N`6|GA2{1kS^9IG)ox=;ik{dW57@4pm+C zDk~*rD1uHW0D~C_y4nBxKgay%KmT#A#A;$HHMg8C|HT%Y@BC2h^IyMTosIYF{qOxN z{{6%2=HnNhmjd6z>jU}q{`c$dV}R#d=cn{_p!xd6`0*DlzQ(WL26|m6Xn#hYAJ%K2 z_8KVo=NIlZK!0w_=2pwsTNwNKzTS6IpT9<5Lb+pq4D$Wov9Nk8@nZ0P2Nx_~eTdHl zg8n)aIzL3d@(5@WPLanLob& z@^zPfz4+!X@s}%y`ElhRUVrb-&+oVM{(H`<=A8Z9U5}Y1&99q!-^%@oHx8CO+>d4c z6#gcDF85F4Pc?Y&7PJNPqQa~`uC7u|B*9k=iI=_XT*e*40A?ap&zv=`Qg5&-edi*MJ4nUFOOSb~~OSMshFTk{^X@=)fBj-=DB> zWxWPqiMV!RGA>{Nn_WmQJ6pUj&asXa`*a4X1dShhwfRhO_q{&( z=VdSpL!^*H!8C*vwttEM8~y{r;X^%z6jMq$l~hwpJ%=1~$~l)T@arX%SW?NQlv-Np zHPl#B&9&5OYOB5Z768Z8ax1O2)_Uinosm1A?!2M*;YS#8q>)D%b+pkZ?la>|GtV-s znQivvS6JZ0%B!rp+UnbFTxrLhcHU*z-F82?+6gC~bn+>uo_}`wht-^U%=*)xzi&17 zwwk||(i_W%)%a*B?;)JvB*|u2%twdCi!6Xcd)drZ7o#^aoor^C7oK@$nPi;hWHBrl zxAW<^58HiO?gzV>82^>s{M&Lyru%PL&d7AXvE0vg`-Rn(vdy%?Tni}-wWu}_e#dda z1@h!tL!4^>F_S$5b{jS79TV7QDPwXB;8qQZsp-S!e){js=~tira+A&j9s#hk?E^jm ze}6MS^O|5fBeVnhwI0^&Z9B|a*Dkf4xK|`%@x4_vM#@AqGzxrSCEaNiqG3k0oj9JW zgn{Q{$T4OJeFA|vYXUO(;Mx2S5`-`Jw*aKk;|`!+*v8v4!#;cQi;hX-jUE@m4s%v+ zPyZql;eo}^365j{wy?6eFSFdtV-#P^5$c|4T+ zgaIp)vIlK{2)OsE+}){}FoyJ$X+Xq<*+_B)zbVQXqIer`ZTNz+phcOLC`yy3|o8CRGHAw-7^vz0U zAs)Hqrw@L9F4Y0GHYZg@foJjy`nwWVg%yEs@Oao1VMPQGiwt6U%kG1-TgLX_aP+%TLB zATAT{VtEqWsv!!Xv*aF_CJwyO%(I&d62fDDsB1a|xt~M_3Ixu!=Vb0~imI2smu03F zjp7kojkF!Oj4LILR5yA}WOjCOX?_enFXsP#iPd_&2%B5Y)fsQvviEn`K)0xX2WnYt zmzR=OAqZ4lXn5y^Q11Uy3dm_kLhPW7YjO7=l%JW~_JG)sM;bCQF+GUfJ!7a7x&`Ea zGGveIffF>DzbfVOaBq6Wy8QCI1FeAo#FtWNc@wnQ%Y25CM1~V_@?JU@DZC2(_&P z1^APJcCfIRI=d#Bnu#=W2bmIj?_CLhlXVLUvyiIzQh}I=+C_2Z$qgcoaV0|lR}>dc z-BI(11}8D%BdJTTPV)2QWx{!ZMyw?a0L*WE1|-5Y(c*w&HVcYPIzC5eEF_VYAXfHx zyJLp3ATJWHx z!(C`>2MDniUI9+p+?eYA#w1>;d6|+!u8i05V!+c9s`% z$zL!M{bZXd*c#{Mp8+BGh}{jnR35euDd(~fuJDq<0Ne=jQLrD4v$;oy{xh&PAQv0M z(BX-A7(q!Otu~GXe_~Ywu|cSR-5ftktsgRRyx1ITYq$lNT3a4J&g8e&N$*W^2@eBy z0;;j4v|Q|ilsDig%mISp28d2}YU_bovR{4$z)K3}@TL(Y40i#RREI+)u(yLY(Ao+o zg=yKvI3z~copDeMpsJAiz=IBjlUgcWz_2Vq7QA`g}dVOq@2%yP?{UGHA zR?QM(2m&w*sOl>6WJ}n{yE8T-9XyGYbPWLQ6t_{DVVJOx0YD)+vq;!Ka;A3%;%3X( z1P$77oLghH1-^f-AX`dBGfXf7A7e zz&*eS68B(5Jld0VfIcQ?B(Q3VD3GvF24jF{Bp4DBL=2$apu`Z=4xh!O5F-Ila1Cc9 zA86^e*ri8)$$Pmev?d}WWbhkqq%;XTgBwH9U~DQV!6E#AQJD*dt*8qA$@iFf6IyG5 zCkM1EtRu_d(S4CshgGvCi4+KzFqkVNlTkWF$sfXpbqOsNj`ZfZX;vj7^@smidm}z} zdia$2`YM8N5M#kXIS^hpJn8t_3|SVQd@M{yw^xYtXvk&c6%J<*u1CgKvEf{LQSra0 z0s*@iVi$OS+&3Ou@#Xxk%uIbF)8Z*#Qll!ux3Gsh0$WJ*9M?eY3jqj8rXU0e%APRuK_>xiJ@v$4BylC7%m%!Z3t}LoNjX zU`+VzRPBxQhCpPQ057yq?+XIIRNNXU;j>g#O2F5Dmm4;hx%Y-N;I&wRzzWw+ZGe@i z@}e?J%~zB`U>}BEQ8o`xOQLD;Nny;>8TI1zBV{_zhzZ;zeU)xT>*V%PP z<2-7AC6cm9RJ;+60mL1oa~dnpSbKIgZfN=<-4w;vX0j<;e!sDRN{zX$Lx^y3yx%em z0s#G`I3XD#9U$q*K;VECWLaSTij7VTHl^C-h~4+Qjo!}PXN+95*8%lY#l?+YmlR*@ zeZc2pCxbqGCEq$%@~(cZe35A_*8aI%4>0+E&wACXTm|m3IKg?=u+~e;T!x;>A-B?+ zYGw?M>IWB4L4%}J6I6do^dl5O`=H7&@r>|=m!2PLIz1vGf=D56zdLEH#3BT62z(qa z%jUiW6K?~UwLJ`F2h=OtUj9jTVSj7OAeIwb-@<^EJ zZ~azsJe&opKD_QSEpGM%18p26efTnw2SODLG68n0%)LQwXydR|s`u880VA>yYvl&- zP}Kq>6dw#3okc{D5+|vu22+7NC!hw#T$@Uastg?Ey;8y$8-#<%RB|95`&!SY zK}81H2M3DsnnglI#`4mCGWbbJDxfY;C}CT_v^S{Fw$$2-mO^&=Gnn>#Z~51V0}pA( zq7C6Qgs^aT&0tL|0};C$a!b)L`-PBkRGwYY-7=y|Q*Ij};YK%>lbX^q%n22~F(warz&Z}CkTAUPr0`cY*bxdn1+(JXp zHJC#eTd~Ms2*ECfWu64!kgIuQDw&0_I59G5?4qg(m{geq)S6IWu+t8l6IlaO1IAnZ zU~KzKHR@e@YJD{(Mmmd@P!Ok8>7&h+5=0v#kV}?~4~Gw|5$;S*|0h`yh#-U1otj@Z zn7d7z#w{|E1_sN2FrnU6f+dQ{j!MD=vXF2vs~WVkA(48ML)2yhH#ma{mP@avw8W&p zY?(YeCOhNP`b@?zwG*JqC_*A%(U6z*^_gJzYVa`P;I5@hdkX~b(+T77-aeEA^m z3q`^ca0KjT(Rkk3M&g8KI4Q$La((6c}D%eiWLXc~_iELh> z<;pi!MX08YQiaSE{qM*k5^R)EGORh$aafBqfSorx;G1jS_lg_`HA2*;y(fNw0B=NJ zRfUd-tyTMfP&mtiA9eUC9_LWM7ZOwi2$(K;F-zT&WIZ4ahb1ISw5&cV0EIo3$i~6? zryDNp4$-TPUV6C^ z#;Ui#VYnXfrWQ?5ganHr5^G0(Mff`SHKKE%rh-o%0v;6>1g)$!ucIWcz@-KM1E*dC z5G5*qU>_>ikqHP;sE@Y1d?PL*1LvH9pb3pM@wOF_Siu~Xx$Dpd(n{!c^{`<#z!vw> zQbXEdPZeZ|FvVQ8U8kZNOFxYuVj||bjm{l&3w$;oSylI6)T5)VKJ6Nli3v@vLVz{x z=Cb}kjka5>@weL8AgzJb=-O&jMRau)!+>&s1g-4U0;Fh@ofC@Rf|D5C8>eK;?j@+6X0ZRTTTM2%_iB0cL$|KMq`G8F-uum0Am@)|T$j|ET(u z2uT>h6nPoC#DzZG+94sADt%~VqG43B)p2I3B$q#YLS0>-+n>4OE^8|q;X5x1LgplY zImvay7ONnxK{(@7RE;1QuIjJWfEx6MnUj#cEr*(QRdvYVGhv~DAYBsC5Rj-+H?pUg zT2!cKJ%U|GyBHVQg)9T~%nB+Bk^EEt&^|&1tspLG=hEwoN@Q(L7#kkqTYFWbTu2iJ zWJyKLx~SJzK0ty6DN&3mL5zyTCd3DS(S#zN@VTnq8uDsi1U=KlIKok)D66=}t+XXo zh~w>k_wMp(jhPKq{Sn0wnsDnn1rhUIZz1;ZU;8sTWrwd^1O6kP`$JURjc9wvm4-{x7lYy2c8df z=5!vF?J-%8y6>e0UNzPb=$jxn>CbXs5n!fsYn@2yRB zn;v2{T@UkBuDUO7qt`Hff>XqQmb^#X7H#XQp@3KpWZ6UpQ$Ve=??pl)7S?M1>#WVU zX=6;-lr$FMB1OWQO%>>tb{t`&m)c8q0uROq)>=V0sIiJTOJwSgg2xT~0Q0VYOPfNfmMihA z-L8WTm9W!SToO3s6|1LwK?WlRelzrs9KZ7F?&Y+#T*tGH3DG1umM!OA)Qp< zgQWs&PDM1Vu10KiKdIWu1Of2D>N)7kPEl4(&}!|`6{Qf;N7@kIr~PV_L>8&p;l+7D z5ejIoE^aV22A2>u18*RI={Tv7@TcxO^T+l(VEZyf)eO*Hp1UKjgsPe-8CXJ6+icKu zFY1>dWGoHuI;wQuKwWBXAo-7&M!n13<;1J*M%7qN=KWeLO zO^plDg@ziG-o>I-QWTk5v~8h|i!lR$5(U%{3KkiJhaojgJfJRtHHJ5>sDj2yXuhdp zsOoKdnUTn!Axl36l};CI6>Qz5gGjlGPe$#dAc{r*VR5XbyX}*rEJOU02_$rX0wlqQbmTr(`wY2zafULV~(~t5?hT2dNV^WKvhH0YgPH z{7`%5l4^HJ0-Y&2cS%#m$s!h34^{&qOVJ+kbgzwkYYjA*Xe4hRHLIoU;TS*=33H!b zh{=Gm!D*o%FfxSBQU}wX$ZjW>fyvBJN=MY-x*~e7EXcU$0t$+`c!0}^yRu4&uK@%k zA7-2Yr6mr3BtbhNxXvuJF_d#NfHv5)l+Uzap{gG{CG1(@WLO-X(0e0d0Q1vqg~LN93^pQNB6mZC zQc7owgJ<=#&8CJ4I4a6P#TNW z3JFT>NT4w#Ov+v9ox4|J<&wxcRS0rMjneo(bO+_1!E2Ns2Fa`wK|9qOg(1pk2Qq}7 zb^L|^X_}zX69S)*T55aiwSYWaHIpHh_G7v#RVdO3Jhsw^O%m}CRt~jQ5ZLjqkyWFx zBPVr#kQunt_H!n2poh7X>d?%&-oB}=mW_%eC07=>YaHqufKB#dTvek?$6j!4K1M<% zCupMqtg$LPVK)L9-$d&4^J)qnIx%#M8akQAck}+?%lEBn$g9<4X@Ar{)JEH#DoraO zU*RZb`S22RW3oi`3{=N$N3U{DB6*H`?e|81o807XwcXA8pv`;IZzQ=t4W|YS`@_x} zSA5O$OL_jAD_&1bMtJht{{PAySX42k{eEKy#gcf`nUlN+#dOe!sg@L{L}m?16rQ^n zFUIB_5J(D-gXk>kzUCh_dTAv14**nVgiw{L5~2Y{gz(&w`OQ5I6|R44P3N7+b5v;xIBS0+dDw^=DSngv9q<&8ou8_+Ygea=yBO#o z$w0?(vcTq(0Uv+?NV9?;Bm)dzv*Rl_LUBI$xcNqtvLZLLglUEVV&hY1BP**$s17rC{m-> zaAd#LQz8C!)r>aPb$D>9i80}t@)+Qus06*fmkr-lL-TLThVQDO`L|`mch%6m%Z79R z!@A+CY-oO}8}46AWq=j}Wmvk@fp-TO{>mdAn5VQhw9k^3q9y@EUc+pi$k6)!u={ z7DIaYBhE|KRk4O_uM~|_4owd*y}bV^UugH~ZV{t>#gCvID}O3UExa(ozRKS}ztEop zpD0jMRA51X<@G8cLSv#TKgf&=5n_khfG{wy;n)BR2@HVy2dRg z?aZCqaX#=dSbx~o{zblTi6XAA6QMdcLCQWl1f|9@rkJgGr`uIW=ydE^P0}n`>Duj7 zy_cX*Thw9{?ZWcrhE(Vq@b4?%JJRN1RjcBy^-R39> zj3{jupMxjr?A~>1Un-TXU5})m9dQ9dLG4W89;?o`*?&>JuT77v=+aYg0Ua9bY8t$H zj`)Dd*0U9*I((rgL^LF>_VCr-AnQ8G+~hG}tv@EVv46?^P!ZtCG0_a)&~co^Lgi>P@M5*& zMt)kV3gu{=3Kuxy+=K;KHzQD}wj)(_7AcUWu7Ke{k&>qqzZC@Tqdo_8>${|Bo+jac zU(z(a{Hdg=PDY|$c$~w}CCw!Tcb}aAi2$JjY(LzbGjz7u)H)!`< zcYjt5N0pwc@IK0AJ(C!=K?(BCsXYXV+AC20i9Ru(0wp9SwB##rcqHX}@BjM)2%vFb z7c>+10evy9i>m=6J(D}R{o8pFDha!89g)_lKjM<$lPgcJ`bm73Bz*Rd-W+P)A`KYU zf2hET`wz1rbwIBnRM9Y8z00qYAo(yiRC$JzfH$q!VVSVI7H%R)4qL z2s@~T3U|GdoAm4t!}8yL5^!C|Shm_b;byJ^mOyM)$ZUa7o=uwP=u8n-dTgjRNlEX8 zs3FbzZ!;Q+Zy0LH-}a50Qymx@hMne=B*x)glZxD#xUysV*qz|r<0z5 zp_{sm*y-KQsUF@K#5H>OHmZLfI)71<(Xd#oCY^610a|SxH6;%ORSLhG&2u84k!7EA zW=Ds-@QLei>Xi)tbV&0#=D!=#{A!y2WJvSFG(~kpjvUM(M5hh@Qx^%|NtrOrbswpf zE?Wh3rc8zK>ZY#rbP>KXOU-%!6qvPj*g{>?5#Ea^#8-wIbco9;H3LxT{C|mdli)ev zk(!IunJ-eU;*`#&W;ozd|Hu);M)9f_j)Wdn>Yfq!2O^|r5jX)pLlhc#UDEDN^E$f$ z5rtlmrtoZ?354Ed7VER+~)!Ci_ZC^5qgnv&Uxfn1*g|J_qO8MpYqD>oBY(YbiO(g@U<}#{k54B*a zH?5pOk|uH>WO`PP;@say6@Zdk%{Q!zKDwUGs4khDyjoLCL&1Y>I&|vPdj5WH4Qu$c z>VG`BW;ykIy`EgNbn^N2}hR+hVG9THcm zR^5(|agz`44FhZ5KY#p_?;;~Lt1)&Qvz-o^UQASdo#jK~>nNVcFiKj_gm@hqc1(01 z(!UK;$5)@TZmin^xf$r}VOv&iI~i>u%+GP?q%)csT4dE+g{tU#c{Q1LHGIyZZTTDI z2t!=jFlaz%+eKWd9)*J)b$_WzTTdZVGZ|{y&!{7=*Wc6`j(>rxO$u_nP6au0`@~^~ zOWjkOxXMe^11T@9$emSHbF22s8d=PtV^JZuiISIssBe(d7&UJ-9fx`L^^#Y`Qbj39 zN}W0gPvGRL1980d+*T1VU|+RY3Q?}(ZhF`h*&eWKPk)V`&h_-OeFl{dQ}*ZJwwg9! zjd1##@bM|#iho+j;gFobL6shK}QcB-1o*slk~sR!{vEjO2_@vGe!7o1cD>RL55Vr{4B^wSGJJ zpU&pM+kdrPx$jwC)X6=hU89UX3?D@9iN5ZtV{dm8aj)0Ys8|f0WKj*HdOb$-IcQxX z@v~>snO+?N*lj~b)$6{s)hC+jkJAGrQ2CH)-qatz8^VA=B#>;Y4yX^WvkzoBot4s= zS%NluwLT&hYfNf*e2-N3B-zOapOJ_QQDO;GRe#fG)wZY7j*b^DGtp{JCqW!~7B+5g z=>`;XcT@EOD;iE+l5c3Z55#~q>jaBVz2Gg;o2iy#JvhW6&f2Xou`~d^+U?cQ#wP^` zgzS{I)EUNskV!fjh#_D5%mO6?!4(NnjUy{ zn}5d0>^e6#haSff%qIQlQ2ZbcAw?*btxh8rGD``jC>3g9!zt_JuVdj#x;;C3BGpi< zBst5w2mDD-A%5>e`Tu=4f8&iq&str2mMa!TROuX&TGCl*e|pjL^=2|^xL0{!Vjn^(B5n9Fv`gp{iXyHX4p+#x+g+5SuM1eMH1U?e>Tg}vb+8n2c&gw8P z0$eTpf@P0RoaI*8Js7PgJ{1YYmQ=Dd>A25GTHum?TKABGj=^%3N}lS9sHAR{I`m8~ zJyB6lG|+jMPWtjm4-!m6rn<>6Eh9t$sQE)9d__0`ZaB)O z&;^MfxvseU#<}RQz%wI8IyFxmAr^}rtaLCd87lDPFL=9Bb#TZ zXIlOJ01?!3fD|$#mH+?^>SDW`K~#9!?VH<Cz}mG0P8@)Uzz*swMMJPZX-uDn z0HaSpU~&3*0zm3_6WG9lYvcO81n}6I&i5yTejkC2?L=z%aalhm$R?_P0yNTA^do|P zfHKEkH@DqV+46cWM|Ip-1to;+Xfr~i)`QZIs2KTE)}`k6iy;Aw;abl$6{SC<>0mEK}=uH5^tC743KzUV=S#4=qc2aVG|A?i@#l*x|7b=Ze z3t+T1YXSTr00OWWz}Z)C-&2A z{k1*7XW1mh(E$LZT>;Pv;Bsvm0RZ0n2eJgwu9{q;!1gNFx(%Rpw%#}YHlG)I2|DNh zuU6j;kPvjoA9#R&bk|Jh{68&%0f2yDB>plqw}0))ON7>44-C6HB7#_FKLJo4fT_J71c`nM0G6u& zE`mfq1yHR2)R)os0nZWiT%Vk8Am93P?JR-S`pXE8@?S@A)&DAjr~R!V2;2V>f~fz6 mgV98Qp#LubP(P9Xac93#j6D`0vLQDB0000U_6Qm{nU@S#v!gyC!O zU_-j?s@L6Fk)Lt8ik>Px6fCtQ=gjNYo6v#8+e3=?pb?HvZO^{T14rlg;KLZF;&2X$Zrg2j?5Q43XP0O7k}|l=?1g4)_ay z3)hE}2!I~*+#E;v^W~lMZW23g=rYH9#hs9P*71wwiO{^v2dB)G;&p*0fJ=FN_B5Ix z)NK0s>ZPmc+>D{Iy?`WW_1kRSbWky*ZAbw zytfm|dR=`faOK?t5Ce6C?-`a2{niGHkMpi`_PdX=PS3kTK5Gc%THX90=zlK}(%rPA z8GNmy?@e`*BGMm;uV3@s#cFe){?(fO+^lP3O6^_GrPrqg5qQW_-?!|y6p1Z#z$e*c zQ^;6iIX*B@h-x8q|0dJl64QS(G~*ol^IPzXh98;%=Z0IM~#`UeOM+erP79VA~gq#3`U%MNN1(Y7R()^KjtEUp=w9k*|WxxLnK1{hsEY z5S*H@GT_9%JMPB#@zT7m;m5=E%JT7{Yd=x-?#)t&W+BA7$NcP;q@HbXqkYf>g$cEz zh95I@%ySU#_nwhVfisA!93lbZOCoSWhV$Ky$=VBbTOTd1_IUUp^zmZ)*uVJI2Qmvo z4%O0j4kHc)e9kQnRO2kfT7!Bq!f?LrBs*wu&R$brXTff{-()7Hv85&^hU;%mKW|6= z##z3mPCBbMG;qzeN5~T?9wu492SpTo>GFzzG*ta$44OakM9}1L**(j(EbhCP8>_gI zPeHMa5n}182GZg#2Yw#HDsY304Gh<_4c!j7;yLWFd}rG|&t+807^F}2C1Q!+?%O`W zc|t)2LD&%@p?Dx|2(Ex+%CJrMM;#tZ)MKUva4bq&+8%PKP6n6k75^M8LC|&vtQ<0} z6aw~D){zRdmnKRPXbC1L+L8!cGLN~ZeQTPW#qj7Jj)+lk0bgVslPwgNUkd@qE>zi?Fy>po<4rG{JFnp=^Ms58FSuYpD~7hb76%9lOu=5o5U% zQ{s|R6J|&ypa^gx%yKESsq=~L?=Bh&>f$o4y(hssi=JnZxlBrIlUk4trtm6EuN~j6 z43)XLpviAcVn|qI%Kx3lm8pi*JzZ@?m197+zMlwPECCbUwZ^|Lrap|StPKkX$LNEi z75>9(*n=C~t@irgL+#vtz*xzUJC2Wx+)#Sm zC6=lm;im#qsbY-?>T@=)y>lIKtB2uJwR2P4DC+yeH^myX54bCT*7Bou=(#EN4j6eeBb-pGg$Mwud{@S_)h2hF-R%VYkB)!)8dp zwVGzsi=F7W+Zym|gF{v)zw&IH=;z1DY?P1s{OJJIWj4lX>AIgPa8}e#1f#hO0ie`yOD<%m%LoS>t(b=?z58{$6G?@DfHMoG@_BL#>N>uq!^LL`cp`JyFg z+#zk%&}^Iz7*xE0xK>#>7i0tQk=rzW0yo-$-^D8mrlh-vRN!GeXvP%=LwUa*kdr;m z4y=JqTu^0V7=Bv9(uK9J31UCT>7k9lmjZs?&x{?R<0DsA-VGmi@GYEN1D^#UTSg3h z0uywisNa!lzGTgNwP0v(g3CD(5aUTGg;#4oAUI8gKHz~kmPpwod}X+MvKrm?K%zct9=f zX5*-6&tL_~Aq|fHdMQODkzuT;0du6U5}2c91kGfa;wzgzt)3DXmn+*;vDsrhL1>%L z>Voq1#hR%?WCXdB$XhWF-Z`ZvLZBHJT#bU|d5VQ{*6Wn=#S-p_SQq*(K7A3&oONF(Dnk^16fZ=AXie+V(l9HSP4^B|$Dj|ZW#$;}MgeDyCHG8% z3)&Am&EKu01k{FYK^$%oi~9E*NE&*d2yqOgdB7xv!*G&6OuFeJJc1DC5_hg&VO3qCRSyzgNRK~)3}6B(BQTS_Fs$shL4BUA zRtk_@X}Ju)oc@*X=!vPu3?QWO1oWvyvm>IGO=1Hp9RFE6@)DPgi z=U&uS7@+S!G>YpHcvlV@^H7gD1!)6yOl6Wo(nN_+MQIj_ikMtrzX)s@O_5-Hh;$;X zs=2(_#MD9e?zDN@U#M=VauF@HC9pAEM8+q|FV- zq)h$H4z0U{l8PL_@Bh_2KdXH{TaO9K94L1CZgQ|mG7ny{f`eu; z5$S-^FPlu5WaTs0f)5KJ^pjf^6=jR78im;5*xAoB+{0Hw7+U6SXhx}ODYR_lh6pSq zD2K?bcRuR%?BnmYA!}w-T>#J`x!>zf(Eq6Qv; zK#-|+aLXN3aY7;L<7H;>sma90$DZGERUHOTD_&v)djPOlZ?@0ukv)p^wJo~CO#6WQ zMisp$b6Jp^vBam;D*@g!K1h`$MWdEV&#r-9-AG*%Q()T|cfpVtFcy>f`@Fa3D!tMip@ zRPfU`%mB>t3iF2R9_+ILVfbK+)Rjz5>U;@YNjg8bQ>a4Y9z}4W!1@}Wh6UCQI(>^M=(I*U}KW@FoPG%p#Fm=D^0U4E#9 zX;B6&0s%2~_=KhR7UM^()ZrO|N_u=b$a_Lie4Gbsx>mZj+l&{P*k8U=lFHJ@FyP?S zV**4l1mjP17ju{KXE5erx=NhiKQk_D1s(S}UcZ>W9aN!IkiJ-Qe8AB5VC5mgS>)bh z3ZMcHhPd^Fp}wcZ;c?q&cKu+xZI1o<`l&T@wJ3mkmvU#!WB`uV{3p(u`gia}YHDqR zWmN=kqKip>k}hdtV8Rc=XD+A{o-fP7McAqX!-?I^&Y`)dSqPfZY~2EjK{ zw%N}&E8GIkLeB&#wu+XJ$aJ1mi{Nq#i3~Ac#hFg#PanJu3pL(D&Q8}9=o=Z6k{v)q z;>tk{&ld}oC8`k-a45?yMXStA1Kq+KreGz6a$|iAQ-%`fj7ayn1IMqT>TA*alA5^6 zpi$$+WkSksl4n_}RV9TrNlA2<#a8plv~dlZZDFe`H!fHz3k4miB9Y9eq)c+^%5bliQugvj{B{Yt?05|XYfX-^F~Np7qRe5F)c zp|s1}!G(jEU&iW^1Buvg)@MR@Pt}jr5w!+08mGNDv92U5_!9aH-*uRD2r>b%KWA7@ za+bBbqoPZkIb+y6tQwD|F6@zF^&(FdQclv2HZULl`_E|y=OGMkl%0-eHuW<9syRil*} zQwqLTgzvKpr++?wlCcdf8fq3`Dcx5OtAYz5%Zx;_q1v&~=X0=^q5eZ3Q!@kW<^hkx znr)`x7^eiRaR>UT`hBVXlbdMn#2}fe6)D?4E|*h1@tnt3PQ`J0$}Eg1#kN zZWIMjqI4@gn~^g)4vv>{{qSwSpxJkh_B$G?o&|!gLl9IxBr|aB9T)<%0ac)O=;=u2yzphjtWi;7v`Nh2f#hKcix-ZhOmM$fj!NfR+Khr8LAP8T$Mv8xF>N3i83(og= zx$wHZKi-!otlxx=*$EoRH{zAT!e)(DY#@8U+d17{iTxUuhb$h57@%u_+1|SRDLK6x zIvf8PqaX-PGNT3nht!xT&{Im5im(0tozxwRTHp;IPR~0(@ipizcIk)?EH zX*hZVWW27Rg60?_rk6@LgzLTJR~YZa`obF?8<%s)FYG_fcDWjCqqhNQr6hMgwmYlR z)ARNqLoK)GPd&o$t+{>pvgKqQ(GIU)?p&{h_iafJ6=o8^YH!s+Ni9?JQ)lH*jl7-T zbe@UiCCn;w)byD3eJi`JUZAIq&xH+j88^7VcB{yL54Z)p4t zaVt;@lbZpUP--OUG=TF&8zQPMbAlc8&;vT)7fS@D3nG8H3N1F&*U7*aBcY(d9;e4f zgJm;&)5Jy>%cR9lv3^OfjdqW-+Ypu5>uYMo?iD}A++s01z|Q!3*9r(V6rpO+&l#~~|o*_|M&Z!)k^ zQd)zRj>bk8D!r!j$ES8m^fNxG_VQkA<6+7M9wN8$lbN>#|>uvaZpZ^*HVZlNni9aP60L0xhJ;P>0ta04Q|AXa*Cci2imDHgaaG9 zrCI;F*xt2YmBf0es-gvvfC+oqrB1S|eHW3WZ_%t3C%{y$qPPN~k=V87BOcW-9N`AG zA-R%RDk*DMJM6UD#?iB+x|FCF9Ix6Jf-svJlXon5UCYQrQb~FvhSWL$uBh8KLXJOR zx`wOWVG?J4=11mI(-5`BaybV-loyyK&4wJ_FvB%l_qz=wx0J`4yvlRJanL+ag9W;d zLM!=+c3c5X!HQ?$&0J>b%V$;pq_m_?j|j%lpOrHAi*I!b*LO~7WQ3>1eYix%v`!wZqULoF~Rd zKxD7Ypf!7?A5u4owHvCVGNz*S$0p=CGJna8#ExIk(Fvt}MgBn(n5PV3KeGbBGQpo& z2)NtdYCd%G@v+O21rS0TUut3765BX^>x>d+|AGoq#?_QzG_b)Wk6z@w0{6l$6K=Mb zArrHdK2*h*)^(lP%2NZ;tS`8_!luo7&A!>_)cefhL>(#NjQB4xqb*tIof`42s8<^F zsdFz#1>n$u-nxSXS;e|c13f?pi#4&1&4G_Z1$zyD;&X`<{8P+wz0?l&iEVnf^R*@)uQvC1M7377@(stFOB%3V10piO<7kM+6+$P z6^%wP(eXC-rMJ^`OXumZ!a82(=~amkIo1a926*YLGO@j5Gm?j8Vh7G|iksq2`YNl# zTwqG<1Mxmg2$XHag0zH%4Ps#>dX-q(hB`Y8B)2ppxn|H;?#9e8)pHgO7uWj=l#SzW zn~7}>gQzGzEeNHoLJBB``$>Bg8ah}r9@>Fio4ps-Hr}*Wmf#7`VXGpj(xLd)#lO>$ zfk^Zwpso>k+GAi|2E$KYYn^J>J>0a#7s8|JLVsm6+ebkxJ$Ev18pc&>S zD$c=mtREvSV+T#xmkdrO|4RRJv$#wZ>Qh~+aUwqD-M2Zi3;@1KE0mD7O&#`3*Bv*S zQ9?MC>ZW0r09J7UHmL~nK5|j}hjA0!-cDUEYD+uCf?ln3n*4T4ro2mfY)rFP&4=)T zWdEcF;wUnqS|DP2pt7@=Ck{qzx>7gB?(3i1zk9|my0lC^tpldJnp+^3R)XC+Vq4+c zaOZ0-Y-S-T5;Th>y;Y=-SmXEf+SSGHbS~%ON{tuiCV2bv?=Xt{-SuS5KG3T?mEV@~ zubt~U8bLiED{xK4Wap4T=<4iCgxy4fGQF`Uyw{yS3jk|-^#1i{Zkq_Mn~+eNi5Evf zK8x=Ze#_lIor{Vmugy)af~>fQAS<_T_U8j-@l0oTBqEGiBjsNU_QV*gBIH#&Dg^1c zofXS2*GB`m_%Fbc+5x1p_F8v*Z#CakXa)gLNq9R|8d5G7yo$PZ#CoK~B$1!H0|Gnr z0%&`{4*2;ywhjs#bgubyuwJ3gyLcJ7D|-TcYxA+xo3yRR@lnnZF)=87ku$tXLP<$j zsOpQfZllZ%2AOjHT}Iq^@0l+HzOXwVn3XoNPB#-Yw13)Och#7_?wX|i=b2w&!^m1^ z1r|T8G0Dnb#fmQSFl$=ij#sz)bvf^=NZMh|JhI2~tNia~EI#dE$Sc_;ZhE1FuKh}* zI-Wn*oK$*P@~%zT3xYoQaw=9vv2*dJm7f8%pag z`BJW!WHy}kqOTEkzoN&prn|B;SWEvU(s|Mv98-pU^Jv5${0?pAGaE^Nee}Ur7TT7c z%r!g7*B6Y_=%&`vhf23@fFl#w@E?`UG%uG$i;lj68&`o+$9ITEu<7^(ayog26k|kI z-UaaMFWAjvQSK05a4Ic0s1<$LE+?n5dQW|Nx6!G1GWFZ9cCqrgs&Bs%0=vU^5-(NW zOHkhjlfV{zbE!~}-B53Zwra*iTuqusZV?ptrqe%nzOX?p{}fLlC8Q7NrW*xVMuud5 z20}|E5X7}gs%i$pK~txClCg-tqkhw*j(%=`Pc1}J1S!y~6g#WMrS>lX9ir#w8-Dp& zwKhxHLCO~`?W`Ty1R+i^8m8L1i$jR{g=9=;YpY1Kn%!|LlQFaJCW4;Z-5=DHZcr;6 zy6%%?th$yf(zP4BZQTqse|Sj<-olnMF=vqWbqmi3@j+BhvQ_0WzEbb1Po6ve-j-Kk z*gD_wqc(^`s<^XelyNO;e+I2~PGEcMUB7?D%y6Aq%wSM0jvEV;D+1M#6iLzCYtB+w zgv-YnEo?%qHCAy1jm6cz)5U&WX2Xwv-?Jh=p(DfBa)-q93*Fm*@*wkka>H+x)!Wd* zyx*621OAX+K|wy)vnc!COKZeBD4Lw@)DN2b5LsMzuLp7K&9A0w#7zcI>N+6KN1ou; zEyV9w=8>W?hOPE(Rs^Ntc1Je{0O>@`VUU1AH@Bz^N)mYS;GoCAUy%LpW~H1 zid@7`RBUv7&nA_88epz!*kOFzIyC$*AK)z}B4QP)YFANW!8iyV+vrU&d@^DrM1dzX zP6$;y?OPn{4P_2a(^P5#zHl9LF-ua*zUe&^)&oX>x{Eacc`BtIfLNCi^_T7n#zjqj zv)dkZ8cTX^*TtLsCWy!GG17yC((EQ*qUowocfzVosbUH>97av2!4S%VxULX_ezfeb zv>>WB^wwYD81$f{q*ItE+jl7#W3G~?f_yG60)-7F4fj2CfX%l+5Ic&M6P32cpn?p@ zfN`5U?>Pq=h?AMc^malrrh@3XTq3ad3U%HiVt2eNdBzE`3PsFF&6!JY8rVt8xafOp z!k`3y2{WBjT}QYX?PhO;PrOk*-@A1`l&hir)$1#3RQ(#O60XrG+IPZmWtx7uDiP#e z6PUnjVenQ8&2X+ji+OK_r+4-X*+-kKC7A7farzbD)8wSFBJDs_U>hqpmTN&XtJPjp zLs_S3qJ{PYMC+r#Am-D!dDiVqs`4`3Lrt8OvLvTwz^i@)(@Rn^i+!78<`k}pZjNBF;mOE>-mAjPJu=afeK z(h3^^8(uWON{E@)|0ui7w@IK*0Z&Q;zGT*`P8X5+J;(;oErwKWaMFSNjz#4>at6mO zrE9cweFSCEyrl=mYLD11|C;V2`{vy>u0oIr+M>|tBuYpH^teX6=RZE^ve-f-ihwoyBD5fq`ut5Hy ztR&5p_~CRidf*Pu%FZGS(d%*Q!C20lo8t9H$5#l|jK%`)5|)q`XAEW`|GkDOZ2*Jq z5a&urg?_IK-drv>-cWsh@BD(?{of7AQz%V~|mHl$Z$H1_Qp z1Xb8!$hy=iC;d7bS?g{8T}hL(zsf=6dw@i4X|5tIdMC@LOw`*oAvY#IhC_3)7|~{> z?Wi{5u?5cyR%SaDsoO_nD1QRJGYqBd$p(ZDJVf*PCS@%?tQ9U@zlN#v1XDiNX_C)z!M1UlCx8&S4+w+-N_4bi1pL?cC54h zq5GL6Ow~~R%@J^`iEpz1UE^pb`s}t)PbY&1eFjSVC^;wh3cDOn9u!R)xsAWBUj2~g z2WlmJr-?9o^ixm0`W5&T=X4NNs6@hweR=&0{SVCrzmIU!vi-0VY~f_!ZGGtVM(|z2 z+i#J)tb1C;-1tRbA5&N7cYo}ERcq7m3d&T=7E?FpId#m+#BhEgAJ?3ht(DiHliaIB znms&^shdN4HWj`ZN+2;BQ(3CtLTrsAP)ylgzdZRi6ymem&A{W<<%An0|AZRXH{%E@L7OCV3UBGTbv8?S4ja6VP z>;WMQ=c>2;oiU3R$eCRVBiEugNHRRRidx2i1`b8LLG{e_uJ2jPltezSGc^9LMfGZ( z=Sdg=ol6U5Z88+cx4!O!<57#8b3kFTqwq!9Z34Wwoo@xZx{?m)iy>=gP$Pe9F%}g2Q?m?NUWeujXJ)p9BBu#Tn(mEls=g%`%5@I zno@j1`L>bArFF~6_Rog;hNxEA+}#Iw!3F9?{fK*5&qGQGM_@*cDevzMRtaVip&X2oAKaJ1Iv<@?F>v!?Di zgTqEtU&!5ac~Wor69Zr=Slz_xU3kEWZ7_mO8>^`)hh+Ob_FEmqic0Rulj1G)G<&=< zwH{VJ8BVuE%I{?xxcq3$A^`~P&_(S^9wzJtCxS{%OSHTTF098K3qXVR+sf__EWQ>8 zkQ*bF1ahd59|NPlDmu5|DKd-8iBz@K%y8bQVDbQoa`#DSm@diLycJ__ifRnWyk6x^ z5JJp=Ls;ud$mYhz=8wD%t-q>uvjwp?_*!Z0tDx$~d^#IUy?C0uV-SPDnU+FRisTub{1ffE}BawXF>sFZbVz zr41)P8;>QAm9>x%H#esxH^hQR6EeXg#>gqiBg8An$0r~l$j{A3jZ8^Nsi35$DXeen zLOh&2JiMH2+=6^uY`nYzLTr}SJp63@ zw!ECY+&o;iJhoO4G(Js;BtI2EDf*9@6jpMzw71pq_3&_UwDtP8o7S=Q{6A0e|H1v6 z{-2ZJ{{NN#I|lrhT*loa(96-@!AHa2?SJh5AHe@|P<6Dnb@ToooBul^%JGjiB5T{` z$S;71aZ^NY0|J5gHC1)xkdToeP2xPTgi3CnkOOf+U=I}s6IVdhLBI_Jf=*D9mC_AZ zJIgywj-*75QhG!w+j-gYTk^zBrJj@aZxhQ^^Ygh3UPsnT(yCqC>udka8g|zTn=b^y z3A?xvh>o%NtX(XD0X142Hn8w~3@dr#PJbB|ZvFE50oLP`)qk2H93Tlx@ugmRCcH~Q zYK@8qK$-1uZ?Pq0pu_J^2lKX>u1!xKi({FlU@997nisgteVQltj%F=MG_OE#-;h-O zW7w(KJhbPpsPHLF(4|skDK8=d$fbO=y3~;#WV1Ui3zlBbhvmG61}IAGn+6QcDz*RY zy9AHscb!g;w!GNOke0mz6C)|X`T)dGF%m!&ce zBwrY?aG$F&abFlPZS3^~FI$gMD5NeL?A~L~k?G|W!D5yXPeDN1x^NpyR$aCXcoG0R zm61uMHd>$7aRDp1ZFvHklmbo@WC>PtZ}VgYZ&dxfW#U4;fWE`V`rXBmy0x4oQTHjN zLFm=Rk(V;%V(Q`U$0?LT=HKH$G!VEC57YrN{$NT68n}K5W0ktmS8LQP>6`lS0j6f- zL)Y2ojngpw@GmcK){6o#w6HS|2xI_dh;xBf~4de1n99b)BgRX@p)F*3C0Ar z@S&PUU_fau{|#Pk?hL^8IVdK88hoQX`U>3H1`v!E--d!;6d@d$%9Yx+x^Kp(y=7Z= zPz~R*<{9 diff --git a/src/components/inventory.rs b/src/components/inventory.rs index dda8e85..faf890c 100644 --- a/src/components/inventory.rs +++ b/src/components/inventory.rs @@ -1,11 +1,15 @@ +use crate::common::Rect; +use crate::components::draw_common::{Alignment, draw_number}; use crate::entity::GameEntity; use crate::frame::Frame; use crate::framework::context::Context; use crate::framework::error::GameResult; +use crate::input::touch_controls::TouchControlType; use crate::inventory::Inventory; use crate::player::Player; use crate::shared_game_state::SharedGameState; use crate::text_script::ScriptMode; +use crate::weapon::{WeaponLevel, WeaponType}; #[derive(Copy, Clone, PartialEq, Eq)] #[repr(u8)] @@ -15,41 +19,240 @@ enum InventoryFocus { Items, } +#[derive(Copy, Clone)] +struct InvWeaponData { + wtype: WeaponType, + level: WeaponLevel, + ammo: u16, + max_ammo: u16, +} + pub struct InventoryUI { - text_y_pos: usize, tick: usize, - current_script: usize, + text_y_pos: u16, + current_script: u16, + selected_weapon: u16, + selected_item: u16, + weapon_count: u16, + item_count: u16, + weapon_data: [InvWeaponData; 8], + item_data: [(u16, u16); 32], focus: InventoryFocus, } impl InventoryUI { pub fn new() -> InventoryUI { - InventoryUI { text_y_pos: 24, tick: 0, current_script: 0, focus: InventoryFocus::None } + InventoryUI { + text_y_pos: 16, + tick: 0, + current_script: 0, + selected_weapon: 0, + selected_item: 0, + weapon_count: 0, + item_count: 0, + weapon_data: [InvWeaponData { wtype: WeaponType::None, level: WeaponLevel::None, ammo: 0, max_ammo: 0 }; 8], + item_data: [(0u16, 0u16); 32], + focus: InventoryFocus::None, + } + } + + fn get_item_event_number(&self, inventory: &Inventory) -> u16 { + inventory.get_item_idx(self.selected_item as usize).map(|i| i.0 + 5000).unwrap_or(5000) + } + + fn get_item_event_number_action(&self, inventory: &Inventory) -> u16 { + inventory.get_item_idx(self.selected_item as usize).map(|i| i.0 + 6000).unwrap_or(6000) } } -impl GameEntity<(&mut Player, &mut Inventory)> for InventoryUI { +impl GameEntity<(&mut Context, &mut Player, &mut Inventory)> for InventoryUI { fn tick( &mut self, state: &mut SharedGameState, - (player, inventory): (&mut Player, &mut Inventory), + (ctx, player, inventory): (&mut Context, &mut Player, &mut Inventory), ) -> GameResult<()> { + let (off_left, off_top, off_right, _) = crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + let mut slot_rect = + Rect::new_size(state.canvas_size.0 as isize - 34 - off_right as isize, 8 + off_top as isize, 26, 26); + + state.touch_controls.control_type = TouchControlType::None; + if state.control_flags.control_enabled() - && (player.controller.trigger_inventory() || player.controller.trigger_menu_back()) + && (player.controller.trigger_inventory() + || player.controller.trigger_menu_back() + || (state.settings.touch_controls && state.touch_controls.consume_click_in(slot_rect))) { self.focus = InventoryFocus::None; + inventory.current_item = 0; + self.text_y_pos = 16; state.textscript_vm.reset(); state.textscript_vm.set_mode(ScriptMode::Map); + player.controller.update_trigger(); return Ok(()); } + if self.text_y_pos > 8 { + self.text_y_pos -= 1; + } + + self.weapon_count = 0; + for (idx, weapon) in self.weapon_data.iter_mut().enumerate() { + if let Some(weapon_data) = inventory.get_weapon(idx) { + weapon.wtype = weapon_data.wtype; + weapon.level = weapon_data.level; + weapon.ammo = weapon_data.ammo; + weapon.max_ammo = weapon_data.max_ammo; + + self.weapon_count += 1; + } else { + weapon.wtype = WeaponType::None; + break; + } + } + + self.item_count = 0; + for (idx, (item_id, amount)) in self.item_data.iter_mut().enumerate() { + if let Some(item_data) = inventory.get_item_idx(idx) { + *item_id = item_data.0; + *amount = item_data.1; + self.item_count += 1; + } else { + *item_id = 0; + break; + } + } + + fn get_weapon_event_number(inventory: &Inventory) -> u16 { + inventory.get_current_weapon().map(|w| w.wtype as u16 + 1000).unwrap_or(1000) + } + + self.selected_item = inventory.current_item; + self.selected_weapon = inventory.current_weapon; + + let count_x = state.constants.textscript.inventory_item_count_x as u16; + match self.focus { InventoryFocus::None => { self.focus = InventoryFocus::Weapons; - state.textscript_vm.start_script(1004); + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } + InventoryFocus::Weapons if state.control_flags.control_enabled() => { + if player.controller.trigger_left() { + state.sound_manager.play_sfx(4); + inventory.prev_weapon(); + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } + + if player.controller.trigger_right() { + state.sound_manager.play_sfx(4); + inventory.next_weapon(); + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } + + if player.controller.trigger_up() || player.controller.trigger_down() { + self.focus = InventoryFocus::Items; + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + } + InventoryFocus::Items if self.item_count != 0 && state.control_flags.control_enabled() => { + if player.controller.trigger_left() { + state.sound_manager.play_sfx(1); + + if (self.selected_item % count_x) != 0 { + self.selected_item -= 1; + } else { + self.selected_item += count_x - 1; + } + + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + + if player.controller.trigger_right() { + match () { + _ if self.selected_item == self.item_count + 1 => { + self.selected_item = count_x * (self.selected_item / count_x); + } + _ if (self.selected_item % count_x) + 1 == count_x => { + self.selected_item = self.selected_item.saturating_sub(count_x) + 1; + } + _ => self.selected_item += 1, + } + + state.sound_manager.play_sfx(1); + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + + if player.controller.trigger_up() { + if self.selected_item < count_x { + self.focus = InventoryFocus::Weapons; + + state.sound_manager.play_sfx(4); + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } else { + self.selected_item -= count_x; + + state.sound_manager.play_sfx(1); + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + } + + if player.controller.trigger_down() { + if self.selected_item / 6 == self.item_count.saturating_sub(1) / 6 { + self.focus = InventoryFocus::Weapons; + + state.sound_manager.play_sfx(4); + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } else { + self.selected_item += count_x; + + state.sound_manager.play_sfx(1); + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + } + + if player.controller.trigger_menu_ok() { + state.textscript_vm.start_script(self.get_item_event_number_action(inventory)); + } + + self.selected_item = self.selected_item.min(self.item_count - 1); + inventory.current_item = self.selected_item; + } + _ => {} + } + + if state.settings.touch_controls && state.control_flags.control_enabled() { + let x = ((((state.canvas_size.0 - off_left - off_right) - 244.0) / 2.0).floor() + off_left) as isize; + let y = 8 + off_top as isize; + + for i in 0..self.weapon_count { + slot_rect = Rect::new_size(x + 12 + i as isize * 40, y + 16, 40, 40); + + if state.touch_controls.consume_click_in(slot_rect) { + self.focus = InventoryFocus::Weapons; + state.sound_manager.play_sfx(4); + self.selected_weapon = i; + inventory.current_weapon = i; + state.textscript_vm.start_script(get_weapon_event_number(inventory)); + } + } + + for i in 0..self.item_count { + slot_rect = + Rect::new_size(x + 12 + (i % count_x) as isize * 32, y + 68 + (i / count_x) as isize * 16, 32, 16); + + if state.touch_controls.consume_click_in(slot_rect) { + state.sound_manager.play_sfx(1); + + if self.focus == InventoryFocus::Items && inventory.current_item == i { + state.textscript_vm.start_script(self.get_item_event_number_action(inventory)); + } else { + self.selected_item = i; + inventory.current_item = self.selected_item; + self.focus = InventoryFocus::Items; + state.textscript_vm.start_script(self.get_item_event_number(inventory)); + } + } } - InventoryFocus::Weapons => {} - InventoryFocus::Items => {} } self.tick = self.tick.wrapping_add(1); @@ -58,7 +261,10 @@ impl GameEntity<(&mut Player, &mut Inventory)> for InventoryUI { } fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, _frame: &Frame) -> GameResult<()> { - let mut y = 8.0; + let mut tmp_rect = Rect { left: 0, top: 0, right: 0, bottom: 0 }; + let (off_left, off_top, off_right, _) = crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + let x = (((state.canvas_size.0 - off_left - off_right) - 244.0) / 2.0).floor() + off_left; + let y = 8.0 + off_top; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?; for i in 0..=18 { @@ -68,12 +274,124 @@ impl GameEntity<(&mut Player, &mut Inventory)> for InventoryUI { _ => &state.constants.textscript.inventory_rect_middle, }; - batch.add_rect(((state.canvas_size.0 - 244.0) / 2.0).floor(), y, rect); - y += 8.0; + batch.add_rect(x, y + i as f32 * 8.0, rect); + } + + batch.add_rect(x + 12.0, y + self.text_y_pos as f32, &state.constants.textscript.inventory_text_arms); + + batch.add_rect(x + 12.0, y + 52.0 + self.text_y_pos as f32, &state.constants.textscript.inventory_text_item); + + let (item_cursor_frame, weapon_cursor_frame) = match self.focus { + InventoryFocus::None => (1, 1), + InventoryFocus::Weapons => (1, self.tick & 1), + InventoryFocus::Items => (self.tick & 1, 1), + }; + + batch.add_rect( + x + 12.0 + self.selected_weapon as f32 * 40.0, + y + 16.0, + &state.constants.textscript.cursor_inventory_weapon[weapon_cursor_frame], + ); + + let count_x = state.constants.textscript.inventory_item_count_x as usize; + batch.add_rect( + x + 12.0 + (self.selected_item as usize % count_x) as f32 * 32.0, + y + 68.0 + (self.selected_item as usize / count_x) as f32 * 16.0, + &state.constants.textscript.cursor_inventory_item[item_cursor_frame], + ); + + for (idx, weapon) in self.weapon_data.iter().enumerate() { + if weapon.wtype == WeaponType::None { + break; + } + + // lv + batch.add_rect(x + 12.0 + idx as f32 * 40.0, y + 32.0, &Rect::new_size(80, 80, 16, 8)); + // per + batch.add_rect(x + 12.0 + idx as f32 * 40.0, y + 48.0, &Rect::new_size(72, 48, 8, 8)); + + if weapon.max_ammo == 0 { + batch.add_rect(x + 28.0 + idx as f32 * 40.0, y + 40.0, &Rect::new_size(80, 48, 16, 8)); + batch.add_rect(x + 28.0 + idx as f32 * 40.0, y + 48.0, &Rect::new_size(80, 48, 16, 8)); + } } batch.draw(ctx)?; + let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "ArmsImage")?; + for (idx, weapon) in self.weapon_data.iter().enumerate() { + if weapon.wtype == WeaponType::None { + break; + } + + tmp_rect.left = (weapon.wtype as u16 % 16) * 16; + tmp_rect.top = (weapon.wtype as u16 / 16) * 16; + tmp_rect.right = tmp_rect.left + 16; + tmp_rect.bottom = tmp_rect.top + 16; + + batch.add_rect(x + 12.0 + idx as f32 * 40.0, y + 16.0, &tmp_rect); + } + + batch.draw(ctx)?; + + let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "ItemImage")?; + + for (idx, (item_id, amount)) in self.item_data.iter().enumerate() { + if *item_id == 0 { + break; + } + + tmp_rect.left = (*item_id % 8) * 32; + tmp_rect.top = (*item_id / 8) * 16; + tmp_rect.right = tmp_rect.left + 32; + tmp_rect.bottom = tmp_rect.top + 16; + + batch.add_rect( + x + 12.0 + (idx % count_x) as f32 * 32.0, + y + 68.0 + (idx / count_x) as f32 * 16.0, + &tmp_rect, + ); + } + + batch.draw(ctx)?; + + let batch = (); // unbind batch to make borrow checker happy + + for (idx, weapon) in self.weapon_data.iter().enumerate() { + if weapon.wtype == WeaponType::None { + break; + } + + draw_number(x + 44.0 + idx as f32 * 40.0, y + 32.0, weapon.level as usize, Alignment::Right, state, ctx)?; + + if weapon.max_ammo != 0 { + draw_number( + x + 44.0 + idx as f32 * 40.0, + y + 40.0, + weapon.ammo as usize, + Alignment::Right, + state, + ctx, + )?; + draw_number( + x + 44.0 + idx as f32 * 40.0, + y + 48.0, + weapon.max_ammo as usize, + Alignment::Right, + state, + ctx, + )?; + } + } + + if state.settings.touch_controls { + let close_rect = Rect { left: 110, top: 110, right: 128, bottom: 128 }; + let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/touch")?; + + batch.add_rect(state.canvas_size.0 - off_right - 30.0, 12.0 + off_top, &close_rect); + batch.draw(ctx)?; + } + Ok(()) } } diff --git a/src/components/stage_select.rs b/src/components/stage_select.rs index 9c6b015..e0d6885 100644 --- a/src/components/stage_select.rs +++ b/src/components/stage_select.rs @@ -32,8 +32,8 @@ impl StageSelect { } } -impl GameEntity<(&Player, &Player)> for StageSelect { - fn tick(&mut self, state: &mut SharedGameState, (player1, player2): (&Player, &Player)) -> GameResult { +impl GameEntity<(&mut Context, &Player, &Player)> for StageSelect { + fn tick(&mut self, state: &mut SharedGameState, (ctx, player1, player2): (&mut Context, &Player, &Player)) -> GameResult { state.touch_controls.control_type = TouchControlType::None; let slot_count = state.teleporter_slots.iter() @@ -97,8 +97,8 @@ impl GameEntity<(&Player, &Player)> for StageSelect { } } - - slot_rect = Rect::new_size(state.canvas_size.0 as isize - 34, 8, 26, 26); + let (_, off_top, off_right, _) = crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + slot_rect = Rect::new_size(state.canvas_size.0 as isize - 34 - off_right as isize, 8 + off_top as isize, 26, 26); if state.touch_controls.consume_click_in(slot_rect) { state.sound_manager.play_sfx(5); @@ -157,10 +157,12 @@ impl GameEntity<(&Player, &Player)> for StageSelect { batch.draw(ctx)?; if state.settings.touch_controls { + let (_, off_top, off_right, _) = crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + let close_rect = Rect { left: 110, top: 110, right: 128, bottom: 128 }; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/touch")?; - batch.add_rect(state.canvas_size.0 - 30.0, 12.0, &close_rect); + batch.add_rect(state.canvas_size.0 - off_right - 30.0, 12.0 + off_top, &close_rect); batch.draw(ctx)?; } diff --git a/src/engine_constants/mod.rs b/src/engine_constants/mod.rs index afe3ca8..343d136 100644 --- a/src/engine_constants/mod.rs +++ b/src/engine_constants/mod.rs @@ -180,6 +180,8 @@ pub struct TextScriptConsts { pub inventory_rect_top: Rect, pub inventory_rect_middle: Rect, pub inventory_rect_bottom: Rect, + pub inventory_text_arms: Rect, + pub inventory_text_item: Rect, pub get_item_top_left: Rect, pub get_item_bottom_left: Rect, pub get_item_top_right: Rect, @@ -187,6 +189,9 @@ pub struct TextScriptConsts { pub get_item_bottom_right: Rect, pub stage_select_text: Rect, pub cursor: [Rect; 2], + pub cursor_inventory_weapon: [Rect; 2], + pub cursor_inventory_item: [Rect; 2], + pub inventory_item_count_x: u8, } #[derive(Debug)] @@ -1362,6 +1367,8 @@ impl EngineConstants { inventory_rect_top: Rect { left: 0, top: 0, right: 244, bottom: 8 }, inventory_rect_middle: Rect { left: 0, top: 8, right: 244, bottom: 16 }, inventory_rect_bottom: Rect { left: 0, top: 16, right: 244, bottom: 24 }, + inventory_text_arms: Rect { left: 80, top: 48, right: 144, bottom: 56 }, + inventory_text_item: Rect { left: 80, top: 56, right: 144, bottom: 64 }, get_item_top_left: Rect { left: 0, top: 0, right: 72, bottom: 16 }, get_item_bottom_left: Rect { left: 0, top: 8, right: 72, bottom: 24 }, get_item_top_right: Rect { left: 240, top: 0, right: 244, bottom: 8 }, @@ -1372,6 +1379,15 @@ impl EngineConstants { Rect { left: 80, top: 88, right: 112, bottom: 104 }, Rect { left: 80, top: 104, right: 112, bottom: 120 }, ], + cursor_inventory_weapon: [ + Rect { left: 0, top: 88, right: 40, bottom: 128 }, + Rect { left: 40, top: 88, right: 80, bottom: 128 }, + ], + cursor_inventory_item: [ + Rect { left: 80, top: 88, right: 112, bottom: 104 }, + Rect { left: 80, top: 104, right: 112, bottom: 120 }, + ], + inventory_item_count_x: 6, }, title: TitleConsts { intro_text: "Studio Pixel presents".to_string(), diff --git a/src/input/touch_controls.rs b/src/input/touch_controls.rs index 585b888..cc7806a 100644 --- a/src/input/touch_controls.rs +++ b/src/input/touch_controls.rs @@ -83,7 +83,7 @@ impl TouchControls { let batch = texture_set.get_or_load_batch(ctx, constants, "builtin/touch")?; let color = (255, 255, 255, 160); - let (left, _, right, bottom) = screen_insets_scaled(ctx, scale); + let (left, top, right, bottom) = screen_insets_scaled(ctx, scale); for x in 0..3 { for y in 0..3 { @@ -117,6 +117,13 @@ impl TouchControls { &Rect::new_size(3 * 32, 0, 32, 32), ); + batch.add_rect_tinted( + canvas_size.0 - (4.0 + 48.0) + 8.0 - right, + 4.0 + 8.0 + top, + color, + &Rect::new_size(0, 3 * 32, 32, 32), + ); + batch.draw(ctx)?; } diff --git a/src/input/touch_player_controller.rs b/src/input/touch_player_controller.rs index 2af38bb..a80a270 100644 --- a/src/input/touch_player_controller.rs +++ b/src/input/touch_player_controller.rs @@ -58,9 +58,10 @@ impl PlayerController for TouchPlayerController { } } TouchControlType::Controls => { - let (left, _, right, bottom) = screen_insets_scaled(ctx, state.scale); + let (left, top, right, bottom) = screen_insets_scaled(ctx, state.scale); let left = 4 + left as isize; + let top = 4 + bottom as isize; let bottom = 4 + bottom as isize; let right = 4 + right as isize; @@ -180,6 +181,19 @@ impl PlayerController for TouchPlayerController { .is_some(), ); + self.state.set_inventory( + self.state.inventory() + || state + .touch_controls + .point_in(Rect::new_size( + state.canvas_size.0 as isize - 48 - right, + top, + 48, + 48, + )) + .is_some(), + ); + self.state.set_jump( self.state.jump() || state diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 7650697..f03357a 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -1470,8 +1470,8 @@ impl Scene for GameScene { match state.textscript_vm.mode { ScriptMode::Map if state.control_flags.tick_world() => self.tick_world(state)?, - ScriptMode::StageSelect => self.stage_select.tick(state, (&self.player1, &self.player2))?, - ScriptMode::Inventory => self.inventory_ui.tick(state, (&mut self.player1, &mut self.inventory_player1))?, + ScriptMode::StageSelect => self.stage_select.tick(state, (ctx, &self.player1, &self.player2))?, + ScriptMode::Inventory => self.inventory_ui.tick(state, (ctx, &mut self.player1, &mut self.inventory_player1))?, _ => {} }