From 50414ee26e5642e2bd242aff5209890f23da280d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 2 Oct 2021 14:44:06 -0400 Subject: [PATCH] Fix wonky physics issues --- game/assets/default-texture.png | Bin 73763 -> 47431 bytes game/src/character/collisions.rs | 28 +++++++++++------- game/src/character/mod.rs | 39 +++++++++++++++---------- game/src/character/render.rs | 14 ++++++++- game/src/lib.rs | 15 +++++++++- game/src/scenes/ingame_scene/mod.rs | 2 +- game/src/scenes/ingame_scene/update.rs | 13 ++++----- game/src/utilities/game_config.rs | 3 ++ wrapper/src/main.rs | 4 +-- 9 files changed, 80 insertions(+), 38 deletions(-) diff --git a/game/assets/default-texture.png b/game/assets/default-texture.png index 28ddf0b282864880caa748416d918dafe3844aa0..8fc5cff748145d10ab11fe1235d45e91b45fbec6 100644 GIT binary patch literal 47431 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 literal 73763 zcmeHQ30PBS+NHK?sTJCxN|kNej-rC#f*=BkrNyZzM8UEM7?q)j3n<8*#ht1kRaulR zAOcbq3WyW}q!xvdRD&dhQ!k2w6g4n}fsVR~FR)AL zSNG}tea>C@|4pZ_YF;?^-!nQV{Wa+uF}gB0=WTd5bN$r!g?^HiuYED?(Gl&B;0{a} z(AGr{J>`0!Cw%H{ir!{0Pv2Yoa0!LN8joZViM&>I*@Kdjf6g~A@LrJkq4kCz*?6@J zQ|}+iPX>R|zBpt+G-$X&u!%Rd4n9{>@7C=l2%vhlcy2AeHb*Zcr)tn}7W`6GeTI?0 zd`)3{U0t0>WMX^uCOBBB4PS|}7ITR3eBf^9>3XFS&2u$w`lV(&cN={;qEk}UO{`NT$^`o+qjw&vzkQU%Qzi>2k~t11Kmmwl03`2Zfna$3DI7*`+u#Jx9og2Zhrjjg%9<2TCA-)K7#4q8Ig$&0-p z*uO&|U9+d5`{3Hveqn$Z(m(XCeDQ21{57w> z!cabN|4?c(ujd0+VM$zhPYrA4UbZu5BG!+dLhSN6Ne2YvMZLBQTXvpy?PlJr!e>+u zAiq7%cD{Mlp7ry;pM3tM2e4TJ-VeEm&?`@h3qD*FWOu-nKL%8f1P*PeRX(W?#j6#m6;^3c#w zrbm2H-B0Xxtp_3zF=FF%F!Ppn*mjZoxf18xC7b76EBhp|*`eCXS>Vo<^FCU-(B&8rInOA7}N#ca?tgY#Dj_>!FMNt)Wko3O}!nD{GJH zf9e|@!^|;=nsq5|XAJlwF50-{clZ^>p)>cXtCiOcYqBZ%l&5dQ!?tgAD>XmuzKn!H zFMP~@43AP*VBy{J_o;tD;LpS-_HB?Xi!rBS$af}uvC(68>k1uPD?ehdvY@1-TQ(Ua z8&aDG<%?%sAN`GqFLIi?%{(?16c(y01T|+3COPKk=L6(y?-v5jmXeaAr#)ggnQ#__$D5^Vn4PcAB zNVR2QHn?sO5l!xVSll@Atc-raFQ51fcw}q#e8Ixp`Si2t6jp@i8@dgXG}hw)OkXic z7#bWjRu4^iz-VmYmENR-DkWKG9&_HDahq5Bvl&{&N#!eW~0+7M8 z0emPK=;;54KL&c}3FM1{p75zvw(A>wo7J${?WEPbeqmAF7B>tAlevX^lm4m8rBzlU zG53dwOT_4zf!2yaS~GR2azoaPc~QF$8>{1@Da|=Jkh7u|vnw0YPf6=(W{m z$i_`>r2>1k1%*02++6L^e~Bgb#o=(hS>gshpWo2XaByvYK>+~Mh_lVzywV3AwmPLN zT&}LNTi~%U+w$S)rI`5QxsSa;-$?{DlU?VP>eM#p=?;5%;zXepan9a;u{JR^c97`~ z&nR+TC})X_y-$6s+o;)N?Q7fCx}$fu_&sOw%rA`g-42Q ze4j~QSaN%^&K9A%(a2Yt#1Z*!fPyiHv{Gs1cC$ADNu;7v2FFo(ov+_$wl`mvy!}l;3qnu*}N`lp4R0&Udgt>Ex@!Le`8C^|3&#|_; z$?7>64=~fI`_nqQ?f}G(B+H`Si@`bY{D?w+#@YSk)Ifxrz?kT5N?ZBhnFR;8Lf=je z0f@{fx&fQGy}i8$*KVdX=r%kDn91k+)7V&0#h93cpB2~-c|PVkB}Z4#AdGSONq08< zp*1jHQg5gTe;xe>6JBuIJ94*m37^P7P1o9pg&e)?SXmNnD)zX0^#YrMOO!GkaYt@e z;N!D=rC`1?!dV>pnUUmUU$aIx=!ue`E0^7_81$7%GzAFWc2BN>>$V;!&w3%g`uYf{ zB%gP?h4!=lPRX9!|xOaK`Po z4MOyAXwzQ|S+Ff~mrx`kZGER-6lGs|$=Yy1KeSMRhzLueUebaWe%h_av(4)>BKr2)|S6$Gqn4IeG0FzAKe- z=y@5s!Bg*1=qF+Y$|jyC{+GVeb>p7san&3UaUuPDfd%gc#Rs1JF_r@XdUfjR8v!e^ z36wmlr)xh@Yk|;>*ycS%IqRNs6%!p<)FMyh8>=b^MTKz>fPU(AV;>7Nq~k%^6jf}b z5)J>M2flVvd5(P?R~EVjw4hH+TamEM{k->t*v~lPY~KlSTU(k*0{aH&YN~<$_ts*q zuj2ImeUNTXpqV>(I_?cHDwvVoo{^$QH1IxJ+5Z#~3hAb9(PI2YQF!q>JAj;rTl#FZ z4M@mu&kRSKlT+?rv?n{2fCFejThTD5<iU%Sh-1e_skX2vWt4*j@8d~#AbuoS7E?as;8!4k4;`aS)xVpwnaOFst|SO?d+5H7 zd@SP*7e<4Dimv4X!XpQ(^z?L~UkbFzOO*j;0^}5m#GRd;z$4_yVhAFy+qAE$xg|~l z7_;m+(GcO#kb$Y@sd6!Vxk3(NBwb+BWT9sFZPwb9RGut}c9Uqq;rbCrQ1`SPLD_U} zn!jOwTv;ST;ymL5Y%#@_BqDlY$#+{%i>E6YoJQH28ucvs0kHyXF*K}aZH>WKu?(x?Jm$J zWI982l@g;d*ETXcyh=oYPfEwFyleuoHBp0`AZ zlZBg+Kw0buxY;&6-2AP|WO4RT4U=gtxp(KYzGqujbG#1oGz& z1Zc{}*j+%Fl^3yU!i}i51(&dQE+N{ZLWPcpjTZGj%U9ijYoc@N4nA$~@7+&Ymq2lL zg6vgtplmAFt9|wq{zDgOaw|U?N(FlS2_UY1F>OVHRyr?Lv!|p!!||48kFT#Uz}@dG za4Wb_|9jPr1zor9XU##lJ%MIkd7<8lS=Bsj38JRX0ft(nZZc^*@Q3ycnRC`jJHoi{ifq?%VAXbv)ffNR%_H#5r4gA%I9UQB`2N@;BxB`TGOptZnZHMGWu=HCzEBDUR6z zkHUweZg>Wp5*TLS4Yx?Ik;<1&c6ImtF zyi!P`mpS%GoMjW;EYNfaw238#wFgqeS|3nqJ#u8BCMfD0_Y2&Y0UJ=DIY3XD60IVb zDUDK}1L~?ve)`zCTgdmi_J0Ep$aUQp(FxNjPr+L}`iDHLgH98}JVJkRgE)^yV~f74 zZ0`>$N+>4~2>(i8IYh36#4>^CF`}CRtPgxLu>I(ix;%J~kyiM=M81*(Eq{ zJ=2f+fZ{y0jD&u|xH$k#HVD<#)oa;oFSAPMVEeHi@%H_p9$ni)4%B)n19aUzf zLai)iws+s%utqzo1TCeiqD-`mce0WAfIzPb*geI=Gbb&O_$Cu8S=nlZu2C3YeC+S7 z^FAEW0;YqTuC;9|Q$_7@adBK%5xu*+n@*?K9rOzf3?velD>FG&;nD0gN2wcVRjuCM z*cgO9;9Xv(d+VHf7+EJs5wgizQLB}ID#%12PC&$k<`p+s8}UdJhcOAlsv=IajKdrZR@dPZWcSNVN1<89&(y%vHEo9zWrKoA!-K0#-c~ z8bF~@srztE2Kzu)b2gY#3hONWA;luj3E@_SH1i16$f#P&bg3nXZQ%qAwLUPv-L69CWG6okfAPslKS64<+W@HzYzc^UdbwYhFRz)x!9%3mW#q7J~a==N`9=V&J5 zUfSHw<;)&`0rv#SIVvmqA!XCxX?|(o%Qu5{8a1y$3K8ASa1N1{F;} zz%pfMB<07))XfGr$x8t>FWre(KrpQmfPqQ&_{od@bXlkg<`o~h?KP4m(OQvb)%-l{ z2omH^#}TxNmzlRunswkMah|oY%1|g_VD9n{ zwN(Dt$R~Q}2^R)!o5IxBZ}P0A3?Y6R&0;Y6(PqFT(Xgrt;f?k6U(89W%?pNXnvdJl z6%gGFb`kf7q6?!vw_>y)VYZ~c^A_KbSm2cFox8-DH8ZNX>VOzIoClh0VE1=)bcn@q zTIDw2U@q4OPfy$6ae8)H@BTufQ30S35-E06nSCk|YGo<2srWCF^-3xwXem_{WuoPK zyiAD?h?lNssoB##Jagg%iElEoG6|@OCd{5(;qZZD{DErp77Ilx7b)nd`u0Qev>}DdPiOt;e7W>Ahy&!VxWC z!hnv113{Yk?H50@dVB(;mLL$~0U2tMlzd7Au*HgK7X(@%-ai54Y_8y?+qn-)4+Z!3 zDOzX-(A0Ywb#RXuB(2{l(Ebc&O(*sr_`^CNG zF2RsdrB;S}$Q^V-13W;Y5Z_AL3FYayr#@=4P>a{uvfzefJ(B^q&>A+dZ^U-%^dH!6 zMH1U>Kd{}lNo}{Hla+Ejz)b_E#Z4`s5I#ta%;rXlUt+uECRG+41?#78jq?dzkB&85 zU6xMG&>0sMPttMtZX`!j5-3D=**h92)HK~dp+0-DRpF#Sp{^upBQ)IS(X;}Eb{QZI ztIVZrT0|owx*$-ff&=_RHlkG^P>6;UuT(??;eXt; zzzMEff|0~NBsM(&#qg!Rbi@-2Mm)ildZiK1yx6ixUD5avPhDFbr^24;QBz*+ws-Q3Gqg4u424R}w)-CIioiJkZxiaHF?j>T*?p_~ zSX}`uhEKr^zrn!5Ugf=!!;_t};7JMt*Ov=gq2h-us1+({e?F3J8&t9^>a?Chh!LW_EJld@3Nb=7(EfCQ#PIFCbg2D_bS@P8bDMn3xmm+tDG7Q6 ziNn(dODQ>hWw0D2r+6^K3o>iPAhWg-kW+AvOmDFB$AZ`$5J+0@?FT7BL&zyYpl~Ge zhQdKY1FW!*5?-`th<;fPU?XlYLN9((8M* zQL>4W&5>$>kCIKv#I2+cijvK7JOFAKqGWS&O9V>9K{@tBG^{Iv`lxTLw1ARLlx#|y zbQF|q0{IL|-Ulf{DA}BX4It9yWsM$`X-&e8*Q>3!@N#p`h%aEIgoY+1&?`UgY>Y_k zkUJdhY@(gbQ6C~oHlej*xd0`blRFnE*@Rg?CGo2$*_>1`pk#BLNFzNr-DqbMWY!{e z^U%)bNI@3FKs%cgNL#KMO&*J=8rsTIr6xK&1slX#wqQqMc2&vpL2H z(az=!1RFNm--200CH<|ply$wOU;9rZn<&8?DRTdk1XJLsy=z1ZKn~$UXEsM$!B8U< zo!JB@0riu@A?us$Cw)sNbWyU2l1-FsqGS_91OD;6l(&?ApkI5E?EQMVhsRYq({T)= zWD}j!9Jyss>+EY|o#mdZNEp!qMnsEoepfUgXsiYrJ1uBKcM`Hm9(=T+JJ!b?JwMZF z=%Qp3C7USO99wArr=3l{MxgKEYW?*0c5d^Td9M1X(Br<^r9(^Z#gyKKkG}Gc|*_QWyY`U-!k7^M%Jgk?5t0fu#@F7vOed^&ib4s zdj#}2n23`>;?S=>c|Q|SA)r@#tV|lKC;#l5oJb(VkY`vh4;!m%J*cmDj@Ve>y&w@} zk^jg*4u}`u(hl2B)K6iiI)0M;!L~hTwg#RF+D^wDE)vqSp73n1qZ#ZzI zZ&rOZv4m9HU@~j8$e8e=`Yhuy=Hm9>g>y9^wa+tN z99|sMw&vGJ#ew;~277bbB#E{BBM6DLVC&Axo1c;BED{4`@U?IDI>c;H306bey0Z<$ zkQZw9_VwvoSPPdAS?TP+<3U9Hxsv)E4>pL4r<;jx4tX-UPL&odH0eHMy0hT}+%+&? z2Hj8z+zEH5f!(sej@Mdz;XcX@gz!LiUDkeF$fl^uJLF1)oizJfy>8-k_N&+*e4fHI!Oy&w_pDz{WI(*Two`qov#BiBy8u)$WS)Rfa!FUZEIz zAM5Asf%@~V4V^Pd>hlh8iWeIp?m!mga{0Ht=`#f*iM3$!fZd4Em73s}Wdy$pGB z|I3vTE#U5CGq`kld(%$=`nAV%SmsNpFQT>>VQ`?7av| zuMO01xH4!HZ)zQEnZoq%_Ywq9JzG4t7GImgDmH2rs~;bKtg&^f?VjtixP`R#=H_OR z$i(()I>6~t8~!{B(iX-Ow)jls$0#Yrg8Jf*;A|CIi<1Kc(fxAD|6WZ_w+EV-g zYn>qi%$zp*SIyIRkvH$$9#pOP6H(UYoxJ;pzO*(H;;0B!K^!ry?=ou`H`U#zgPV_e zF)Y{qLw+U+x-_PqT4+gtKHIV>(k|y3ZL3N=xcGbPoq`d7nsCK^ZYPBcZFx;TKK(7P zyAvJH2bhxA#g>|pO@}%<$|z;+Hi5^t&fep(0@{AE70I!KJhko)sPmT;+&O%w&)N_e)Y`EJI zC7WZYF?N1XvWb#Slx&9hqGS^|R#CD!6-*ES*WxyR_X2{{xoAm3m83D z_Wx~l1tpuZgj$qrPAvC0DA}C2xT9oqxQWa_JDU^l49SDziZ*mdp=|8M>n$yyolUf} zIU@El(9UK@9opF(Gg6I}OK*8+6K(5_Z?(O}O z*&HpqP_l`V%@KTkqd7K8Hc_%Uy6T~16D6A?tKLMjC`vX*9+L6r=PhPkZ?b7xhO~f^ z&HsRGq6G6VO)x*YcF1r<3ur`bv~UYO0iD@|J1yv_>iBA4SemDx6S@;?M~RJB(!NK@ zCQ3F())BO`37!kIvx#;#N2eT6jyIzXy6nT<*!<6n4bVd%G619?F~K{+`&j_2*9@p}ds-oUMT<~f|vOJ1lv;Dq_f zIWZdRtC~Ach(D=y#vbsr)bP-oyTato)06#AeWQ($QiL2jb6M?BiVzQ^2)QoNux)GI z(fc{(j@`ql*`d;6c_AixU`ypQe@O(|_@)z6^xJ^A9UIq-pi6mm7^O4ZWT&<;;1MTinqw2Q`mlErU6 zK|1Xn@;oH@ozfL9SKacnGT_f;5bpZEuLe_|%ZuK>r}^m@cT?0TK7`6nx008En1AytQ%(zI8n-&gk8M^gt2_9# zy+6EBEXL5U*5(C6NpFwak&|l+9p;ans#tTzAZiv=5+rv%EQUXz1|}qp*TFuc+4IFGl%2sJO%FN=l_8B@ z=GY@~mQ8ds}FH*AP%K6R}V^x-j~KPuR{l zw*aF8oh^h=goZN*g?uzBT{R;TC~bgzHy2w4Lx(0Y8$c<9#3~{cw8vVIVKIYsn@>O@>n&=!!b=JF| zv<{@bJ0(Je4oG`> zMFlJ@dC1m^oRpyu;ir$SStmZzP|QF|#hp+54yA3AR~D43PF=E4f<9#p`riBNvw*H_U?WUT9^hhflLd;+JBwj^6E;h zul@W^uvLof-FkVEPJT&Y)r%NR?Vg1@1CAZ~pgn`4?|<$NJhbFI_sR&p8ex|rLC%_& zBWDB<8JDavQN2bh_fuB?f*_cQ2kU)vMW?NH%4d=I6;rOQWJwsLW0a}-cOy45In7y0 zf)KZd?s))S?r_JixMQD?v0OkX-)9A4-hqxO&?YZcW-u5y98M?_KS{>}JZ-o_s-QV$ z2Shd}_v%9Id_gPoD3Y?7=u{Cx+y%ePcdsVsgb#|dZ7bmaHpg{9yUMCQCi!+ZV&HoO zQK#3pEW~ISJwvC3o-Cc~)M2d_e5-?NS+AniChjvD%=r(r+L&_1ctC0)r5209Nb0*R zzGO>+k10D@oj%dV$YQGf?WE#+$?eHA?)5*lj;ggxp96R&JV)2Su(bh$?6Cv&l`{}( z_125#(X&2-Kf^%`-_kdGQxUXzHoh!C3FG*)F}x~KUhAE6S^$3b2f5MM8VW(?-C}Xv zNh=ShVn{RN_S*&_s!ZDS7ef|oi`*rYdDqH5Nv!Yms~n6etWB%Va|~O_oncYW(1qRaRoel?J{cIU|I*m=}cc_mDmZxWz_3p?sKK!hTq^ZrYPl+&UFYgzo(V2jV;rq z{l4!L551Z^KqsF4K-awlb3XtS6}wP2IaSr|OK$e+ee; zZ>R`=ML3S@faBgs;f&id5R*_Iq3WuaeGzeUv7A<@>Uj7QXlb4xaob8`Ye1iqvQrz8 zdY2G&@?tLt-q#I!q9o|@msDyd(G+NplqX9-p#$xa5>;%Z5)FSY2X5u*-z6`LD+}F1 zI0p7enMPw1`W=HPM!TmOS6&3wc%TQ~)}|9z=1~EdrUK}JF9F-%;bb8u|LSr>oizoq zJ0O<16x``f@dN5c@C8x_-yL)en}@<#!@H#5a?a6q=XT2Io!X-<#>x6M+F_f*ai-H@ qLz~GHmJO7kPg$e>7(s6lYGD0)msp+`naF{EHkw&}oo2f8*#80NFhWQG diff --git a/game/src/character/collisions.rs b/game/src/character/collisions.rs index 0a52deb..1c571c7 100644 --- a/game/src/character/collisions.rs +++ b/game/src/character/collisions.rs @@ -1,12 +1,20 @@ +use std::ops::Mul; + use raylib::math::{Rectangle, Vector2}; use super::{CharacterState, MainCharacter}; -const GRAVITY_PPS: f32 = 2.0; +pub const GRAVITY_PPS: f32 = 2.0; pub fn modify_player_based_on_forces(player: &mut MainCharacter) -> Result<(), ()> { - // Convert the player to a rectangle + // Modify the player's velocity by the forces + player.movement_force += player.base_velocity; + player.velocity = player.movement_force; + + // Predict the player's position next frame let predicted_player_position = player.position + player.velocity; + + // Calculate a bounding rect around the player let player_rect = Rectangle::new( predicted_player_position.x - (player.size.x / 2.0), predicted_player_position.y - (player.size.x / 2.0), @@ -18,23 +26,23 @@ pub fn modify_player_based_on_forces(player: &mut MainCharacter) -> Result<(), ( let floor_rect = Rectangle::new(f32::MIN, 0.0, f32::MAX, 1.0); // If the player is colliding, only apply the x force - if (floor_rect.check_collision_recs(&player_rect) || player_rect.y + player_rect.height > floor_rect.y) + if (floor_rect.check_collision_recs(&player_rect) + || player_rect.y + player_rect.height > floor_rect.y) && player.velocity.y > 0.0 { player.velocity.y = 0.0; // Handle ending a jump - if player.current_state == CharacterState::Jumping { - player.set_state(CharacterState::Running); + if player.current_state == CharacterState::Jumping + || player.current_state == CharacterState::Dashing + { + player.update_player(Some(CharacterState::Running)); + return Ok(()); } } - // TODO: Error out if colliding in the X direction - - // Apply the force + // Finally apply the velocity to the player player.position += player.velocity; - // Apply gravity - player.velocity.y += GRAVITY_PPS; Ok(()) } diff --git a/game/src/character/mod.rs b/game/src/character/mod.rs index d79b4eb..f35e5ab 100644 --- a/game/src/character/mod.rs +++ b/game/src/character/mod.rs @@ -6,9 +6,9 @@ use raylib::{math::Vector2, texture::Texture2D}; use crate::utilities::anim_render::AnimatedSpriteSheet; -use self::collisions::modify_player_based_on_forces; +use self::collisions::{modify_player_based_on_forces, GRAVITY_PPS}; -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Debug, Default, PartialEq, Eq, Clone)] pub enum CharacterState { #[default] Running, @@ -19,6 +19,8 @@ pub enum CharacterState { #[derive(Debug)] pub struct MainCharacter { pub position: Vector2, + pub movement_force: Vector2, + pub base_velocity: Vector2, pub velocity: Vector2, pub size: Vector2, pub sprite_sheet: AnimatedSpriteSheet, @@ -30,7 +32,9 @@ impl MainCharacter { pub fn new(position: Vector2, sprite_sheet: Texture2D) -> Self { Self { position, - velocity: Vector2::new(20.0, 0.0), + movement_force: Vector2::zero(), + velocity: Vector2::zero(), + base_velocity: Vector2::new(0.0, GRAVITY_PPS), size: Vector2::new(100.0, 130.0), sprite_sheet: AnimatedSpriteSheet::new( sprite_sheet, @@ -44,20 +48,23 @@ impl MainCharacter { } } - pub fn apply_force(&mut self, force: Vector2) -> Option<()> { - self.velocity = force; - modify_player_based_on_forces(self).unwrap(); - Some(()) - } + pub fn update_player(&mut self, state: Option) { + if let Some(state) = state { + // Update the internal state + if state != self.current_state { + self.current_state = state.clone(); + self.state_set_timestamp = Utc::now(); + } - pub fn update_gravity(&mut self) { - modify_player_based_on_forces(self).unwrap(); - } - - pub fn set_state(&mut self, state: CharacterState) { - if state != self.current_state { - self.current_state = state; - self.state_set_timestamp = Utc::now(); + // Handle extra external forces based on the character state + self.movement_force = match state { + CharacterState::Running => Vector2::new(12.0, 0.0), + CharacterState::Jumping => Vector2::new(12.0, -30.0), + CharacterState::Dashing => Vector2::new(30.0, -20.0), + }; } + + // Update the player based on the new velocity + modify_player_based_on_forces(self).unwrap(); } } diff --git a/game/src/character/render.rs b/game/src/character/render.rs index 6844f11..d98e509 100644 --- a/game/src/character/render.rs +++ b/game/src/character/render.rs @@ -1,4 +1,4 @@ -use std::ops::{Div, Sub}; +use std::ops::{Add, Div, Mul, Sub}; use chrono::Utc; use raylib::prelude::*; @@ -37,4 +37,16 @@ pub fn render_character_in_camera_space( Some(Vector2::new(player.size.y, player.size.y)), Some(frame_id), ); + + // Possibly render a debug vector + if config.debug_view { + raylib.draw_line_v( + player.position.sub(player.size.div(2.0)), + player + .position + .sub(player.size.div(2.0)) + .add(player.velocity.mul(10.0).add(Vector2::new(0.0, 100.0))), + Color::RED, + ); + } } diff --git a/game/src/lib.rs b/game/src/lib.rs index 96fc5a2..ca21477 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -106,7 +106,7 @@ pub use utilities::{datastore::StaticGameData, game_config::GameConfig}; mod character; /// The game entrypoint -pub async fn game_begin(game_config: &GameConfig) -> Result<(), Box> { +pub async fn game_begin(game_config: &mut GameConfig) -> Result<(), Box> { // Set up profiling #[cfg(debug_assertions)] let _puffin_server = @@ -209,6 +209,19 @@ pub async fn game_begin(game_config: &GameConfig) -> Result<(), Box for InGameScreen { debug!("Running InGameScreen for the first time"); // Set the player to running - self.player.set_state(CharacterState::Running); + self.player.update_player(Some(CharacterState::Running)); Ok(()) } diff --git a/game/src/scenes/ingame_scene/update.rs b/game/src/scenes/ingame_scene/update.rs index 268bd7a..0969a68 100644 --- a/game/src/scenes/ingame_scene/update.rs +++ b/game/src/scenes/ingame_scene/update.rs @@ -27,16 +27,15 @@ impl FrameUpdate for InGameScreen { let is_pause = raylib.is_key_pressed(KeyboardKey::KEY_ESCAPE); if is_jump { - self.player.apply_force(Vector2::new(0.0, -30.0)); - self.player.set_state(CharacterState::Jumping); + self.player.update_player(Some(CharacterState::Jumping)); } else if is_dash { - self.player.apply_force(Vector2::new(40.0, -10.0)); - self.player.set_state(CharacterState::Dashing); + self.player.update_player(Some(CharacterState::Dashing)); } else { - if self.player.current_state != CharacterState::Jumping { - self.player.set_state(CharacterState::Running); + if self.player.current_state != CharacterState::Jumping && self.player.current_state != CharacterState::Dashing { + self.player.update_player(Some(CharacterState::Running)); + } else { + self.player.update_player(None); } } - self.player.update_gravity(); } } diff --git a/game/src/utilities/game_config.rs b/game/src/utilities/game_config.rs index d91e544..d8647a9 100644 --- a/game/src/utilities/game_config.rs +++ b/game/src/utilities/game_config.rs @@ -30,6 +30,9 @@ pub struct GameConfig { pub sentry_dsn: String, pub colors: ColorTheme, pub animation_fps: usize, + + #[serde(skip)] + pub debug_view: bool } impl GameConfig { diff --git a/wrapper/src/main.rs b/wrapper/src/main.rs index e8336c3..76e2bbd 100644 --- a/wrapper/src/main.rs +++ b/wrapper/src/main.rs @@ -7,7 +7,7 @@ async fn main() { // Load the general config for the game // This happens here so we can properly track sentry events - let game_config = GameConfig::load( + let mut game_config = GameConfig::load( StaticGameData::get("configs/application.json").expect("Failed to load application.json"), ).unwrap(); @@ -22,5 +22,5 @@ async fn main() { )); // Start the game - game_begin(&game_config).await.unwrap(); + game_begin(&mut game_config).await.unwrap(); }