From 15c98361c0454117710783c665dce6d18e76cb7e Mon Sep 17 00:00:00 2001 From: Jakob Feldmann Date: Tue, 5 Sep 2023 18:09:58 +0200 Subject: [PATCH] fix: sticky wallslide, bounce consistency --- assets/sounds/grass swish 1.ogg | Bin 0 -> 29360 bytes assets/sounds/grass swish 1.ogg.import | 15 + assets/sounds/grass swish 2.ogg | Bin 0 -> 31141 bytes assets/sounds/grass swish 2.ogg.import | 15 + assets/sounds/grass swish 3.ogg | Bin 0 -> 32311 bytes assets/sounds/grass swish 3.ogg.import | 15 + assets/sounds/grass swish 4.ogg | Bin 0 -> 29375 bytes assets/sounds/grass swish 4.ogg.import | 15 + src/Actors/Actor.gd | 4 +- src/Actors/Blobby/Blobby.gd | 732 +++++++++++---------- src/Actors/Blobby/Blobby.tscn | 2 +- src/Actors/BlobbyCam.gd | 402 ++++++------ src/Actors/Enemies/Caterpillar.gd | 37 +- src/Actors/Enemies/Enemy.gd | 50 +- src/Actors/Friendlies/WhatAreFrog.gd | 832 +++++++++++++----------- src/Levels/1 Tutorial Level.tscn | 3 + src/Levels/2 Tutorial Level.tscn | 2 +- src/Levels/Actual Level 1.tscn | 9 +- src/Levels/Templates/LevelTemplate.gd | 10 +- src/Sounds/default_bus_layout.tres | 6 +- src/StateMachines/BlobbyStateMachine.gd | 6 +- 21 files changed, 1161 insertions(+), 994 deletions(-) create mode 100644 assets/sounds/grass swish 1.ogg create mode 100644 assets/sounds/grass swish 1.ogg.import create mode 100644 assets/sounds/grass swish 2.ogg create mode 100644 assets/sounds/grass swish 2.ogg.import create mode 100644 assets/sounds/grass swish 3.ogg create mode 100644 assets/sounds/grass swish 3.ogg.import create mode 100644 assets/sounds/grass swish 4.ogg create mode 100644 assets/sounds/grass swish 4.ogg.import diff --git a/assets/sounds/grass swish 1.ogg b/assets/sounds/grass swish 1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..456a6ca7caa07c9ea3f6e7dc9e56fa491111b59c GIT binary patch literal 29360 zcmb@tbyQtF^DlmY7HKI~ifeHzE(a;@?!}9{9^6~pT@O+miWPS+?(R?uh2q5>ejEBc z?|s+zch|lD+`TqgNoF#W%*-dr&I$6Srph2#&_7R$`riz~MJ+1~5sb5~gMm5Zu?hy{ z0`o+A0G`K8J&gQg%l|x&Egv}!ehI>%Pd;+}*E0?GR}ve*@WI^9?47)WDT$T2f!dRN z5=jykCKe_pP9`=IY9(VMCqr`^QxZ`dXLAQz8*5`5M;dsb9U1T^EH5i7DyO2%C*t5n zVxVtrU~5ZaWvuUP45251xR^uCj3KW9Hf38AM;CnuV?JeDCmSPca~op^B%oSEP(_pv z(8P=f6yzPuP0eletwU>L^5gH1_R~pYjfWrhNNCPmH9utFL(m)&_2_kUlBP~dCctKnEgq9}mkiYtQZmfbYKCPk@H(E55%5;pKMB&)I7ooL2*KkTp$Q>AiVvpA zPj&!A{T&tw$QKwUNIV8pvI29kf?#-@T>h9|@iqH6tEjSytSaz0>8Lv!&pJEJI(um( z2WZuMY19X3%?0RO1nA=g{_|dXtzJC7PeUhx0ev9@C$7_Ezs1Y`3C@P|4=jNN89kbW z1S$3{O>B;2zKKPdIkeWSxYl~Gl76rf`H2Mxwr7vM0evw~&Hw+sCK`#x|MyqGtdABX z0NAqEo}kyBTvUm?*MT14$-;dgz^4LA^xY0@;t;l82rux8JBswj%M72&p#JNGN4JAO z0?Y*6_5}TaHIx`89oW?&e6tYQS-=#J7WqFvpPu3c7zk;)Nuq@>B5Sn%lUaNLu{c?X z!pMI$0Sv)e8ziY?sVBo=l+<5eiZG#*9U&@Es)nLu=#vMnMsU{wU(yVubbm=1ONER` zBB$p4&ADMf5lV|DfI8f*G?X4(eSpt=A{C)%{sYifV=Q&EumKaug~UUtY8q7j%KIlQ zigeRPI>2i{i;xAVWdo89kh?NUI~YcKtoxtgBLMhKe-5W7{WFPIB)kD8X+CKjkz*7} z+!y9Pnp~oYNHM7*KLsURsyxTfPa`J*f&9^)qWItBDU|<4ac*oV?ErPv5X&I_V^Y#J z!oB;g3r!fA8Hi$fb|8u)YBn<cfXa5r5Y=j@j;|2>N5lr7Ov0C+LTd+2l{y#$Ssn zvdJpH(HVc^G>K)b%%L;MZak@KJnd{eUu&#Y=cQ5m4`BYnW_8x-zmW3?k+Ni+{h{o0Ui zHBh$O_gB)=Oa^MA!BkDl@U&v`^CJ+YDR7o#;@^_4UWTNfRI>f~oR= z76@7Ku}YSCxibL4aZGZXBwk6$yeNK3lbWIiAW$UCXj(Go&ln&-i7L&VGO(bjozX0L zQl9&${E;BZ0FjeIAWaw%qybt0eK8(+6g448otHbIDVbNJASF$aHzPz-S~FuHQ&fW| zB?*Yqlq{;5(kv~l!Qnxq33%*Pb)se{a~_r5TmJV1F(?W6K)6(#e>78a#Ffbt?> zfR@a)GZqodJp_is;5ct^m#2|q0llgL2n;=dNuGMe0JM-P?Z%UO z5(Oxq(Tpgq!Bdt3252Eu1T3XPH8nU8pv9w(8XQ1WFODSxu>7{efJoZ?Srp9rq(CGu zfW;Y}v?q-fk)|8RzlS6b#}AFBI~juZHV+4aBGd!qr1~FoG=%;bkA6XuqM-qnWrZKW zTK>^5|NBo+Kw!x;kPs{g$3Na+2)soC_`p9}DIB~-;IE_D zqp2+QXfB{m(-PR1ApkoV7_l))u>{dMv(5m7FHa$h30Ml*0GT;34T8pk7z05TLLhYj z0wLE(NywZuPew|DA{Pq`#F-KcO;(aNjR34(xtPGF zCNLf_Ll1$l6kuh;a3H3Ex~+I6V93c3ARz$O3t-;^SdYMP2rw5U60ikO*ZWA=N;CYs zngAO$T03Cz{ibLH`5f~FfF~@d2v{YUrJn4H7k~qBBj&M5FmD2#mMZ#Nj92V4=z28zqc{HDXENviC-=YV zo^qT25QZL|6As=acx;;nkpsg26C6muH{vbyb@;P4k7GmxTph0e6#mgtIq^>hPEfSS|9$A2aY6Hyx!f?&jqd|aNX+y!Ilo@TvA>X5vn$0v1zzoT}Tp$68 zIj%0L35_)~yC*v=fk0w3zz9(O@l?WJnErJfEr9r^ka#Q_J>u8#FF~m9zX<+gkHCH+ zC-TWl(_$f$=^N6Ur|pHrzC~+m+xt_ z5|8oN$-gat0DR=j`b$ufdWzdeQIGO~;3fT+04RD={zOm`LZtW)ArBA$^y)7GQ1ox^ zQ3?n&_T*3W1T2FBTy>&PWG`?j|Ke*6SpNRywIKhuJsB|1{3Ge#Ui`l={%=))3I~x9 z+J7VAn|_ewrXzUu?g@if0OGom4I>4q02pgpCVy5C`kk9QA!Sv;E+zPAEF}OYGc3Og z<71_yO1rTP!&Cf}lxTq&6qpZZP=uryYOu7zDmFDO5wdcD8T2v0%3A!Qr7TN-;TV1c zZ!HK?)6~ovgtO0TdY}|l0|IK!wJnFi!N3g9Jc9=rX1`dH1|+9ima!vbLeTQ_<}4!E zx6(Y&xG$$PBN{e|9LEH=h#aL#fmLvX4}sM4PeaWI%VGAd6+cvN#8r!8Ah0bD`7Sd2 zY?y&a9_x5y5v<3t90gwx_@i)N5+Q^7BJ4l{+Dx(0+=JgHg7M|s(LMq5%L`C2u%Lwl z6OjL3pBRMxh5CPi8Td$`E0oF9B1ydFMdj)_p2 zHrxb>#eR@Xuf4`clGkM^Z}F+CaGXzgSfl~IQFS~Dr7pFohNBGXYDoCo%~i&DVdhjB zsf|pu8Z2h|lXi{_?8t4M`09*eBEF9wIKY4e^i-xg%O<3Bu&CyrjqGN!SQx@;k9}3t z^!h`>Vl;M7?UORJUjO=we4-5XEEfhTcYeLAiFu*dJ02 zml=+h*Ua4@|FKYQ zUZ{8wBO5DA>+Q>p{fOWw(v?OZma!>P(DyOkWOJb^`O81OQp1@w7Yp|;BZJsM%|wg` z`UMe^9{6Zo}5K&JH06#IY8}rgc1Td=4r_li7nr{o04rC8{!YjAA1I`aMB7 zeS{pR#>`6C=RZ!9W37$j+8Xont|*9f^5FzP=9!77L&fR=Z2^VbzO!?O2p5eyonC4~ zsKEjPXz-xwu@|rGX!zljlG{?-yd|UF46d{;)1x?N)F+H5*%rOar~- zy1g`-i|~pA4^;}i{tU4S1qL2NxC-X^9>~GXccQMUT%3z;zADUcr%^YR_-xhfwk?nN z>w%7QUUwJ7+mq$t;x239xFOR8Iz2U&-+;@HlNY=D3ywc|%akZ=d1LsDDu(!j*Wr@E zU4t(10Bana9yY?%*4YokrbT=9#M!1@aAq%rr%iGj$pa#pfmPnmUbyVGoU+yZp?BHw zZolbjRd>DDny4l*(S5tXI!ujZh0k%{DZxrY3>1WaZjXIZmtX=sHoZ=?169 zA&L1~k|aw75!G4O#TSuGoS36V$&=>(t=cWvTa8N`_us;6&5j8oj{{J*S~~p)BlxT| zw2w1;9e=bl-UN%xo{NfFV#zG|v2XhxW0T!~NH}Yt>N!pPg2EToz8}iFn932ATOaws z!UYmY>8(}&N@UG-u-U_0`01TuOc&bn_574tWpl8!kpOj!hm!p$T+&we#;W;C*=?(7KB)vrMc3mp zLD3T#aaYjeRjT&oU{%pn={4nv_qFyb@AcDm^zUlO!61V1Q0k9P&%WJ{Zo0dS3v z6qh9i$zt!-4n+veT?>Ysou>}gPjeuE>W}O?VjF6L_Mee|q^*G68yfhAZtMxl@V@mr z>YugI-(I|vXWYGEys_!Gbf5c);9UYoDkiLpQcu`8x}o9jxq;r59j?p}(c>Yl)?`_z znR@+VZz$BPOAV6|He)N$P;ArSXr+aA#1w+kg+-AR)I8j{xuOU|l6)6r-Mr-;Djjxf zF_i2uA^1L;rhP@Dt>^;7n7k_g`RUMrxfon9lF^T?PsN;Za_0_vE5GSSEY$c@ z&`KITibTvTEw}YtJ;@eU^KK(#yr?%WEb#=|&o0Q;T)uz^`d_fafk3N?vy&+!?k!e6 zcO&_DE_E+p5iH<7K)dt#YdsR&Yn%AIZG1e*D0yjE#CdA-MT!#Yl@<i}mbNg>FqZ}4kToV{Eo$^tz-1nVcdD+pPAcNiZyYsC=Q zx|`p7(1TvTXIx%Q7&vjmoN&|dGR)*;(y;nEM#5uwM*=^9AHlibaMdzvqg!EJ;G*N2 z8gM2@+X4UOxG4>hemFEZkkqJ42;PhRPRYlsrt+%5{32_TU?dCqQ1UZ5D5UZDHjZBLzFbJK!+DL5UFGR?&mM4@AR}Otz+;=N~ zDqd6goPIcwPJxcvHfwvt!INlaHlpM1%PhYRpH(Mx2t4_j?KUVKC%;icKyoDAQnQo+ zejvm^1Zj`+;@RnkvB`J07~hN(3-8=VEkcP7lywUpL|sO8U=h_8SvT1#@%LsvM&t^z z*98W_%rs4iY@+r}%aXtNVEAV6!H(P;V>#U7q#Fd)sj}qkp1+)lHjd zmx_LRWZ0chdVk*)xBFPSd{BjhL3I7zt40PP=&a`FkLtXD!wUMw;csWv=ru`@?>=h7 zncpn+QVVi)_>;6Fw8x_Y-9 zKJZ<%-x%=g1ZrfKlBx{s@|2@>wWpNn!BRsPw7 zoU*g9KlBVS+>1i@XD9dxcsdPqS`*avN*TP|el7KO9!7AVP+L_LKoby7^4QcHih3YR z5~#oLzkLqcL}5rulULS$cYY788M@H8x51c=j$gZY6W4;0NF%w#*65{EE7RRjUDzs{ zMa!}%`h837w5zHTzK=GuVs+i+lBHsn0&C!unmH)&kg#HXeRIQYilN|pm*|{0^Y9OJ zIk7qJXng66H}F4CDVyM;Z#5Bc4;-{S;xfe&-1x)cmn@J}-YDq9nutki4z5s@b;D+e z4muz*p?qGM>+|i6EFqB3KuMtt(M3_NR*SrB9lrLPZcHYc*U2SHA76hB+5J9Owbz9= zyOcTZ28}DE(s9PelS*=fx8y8hXh^x9+3~YAJ>75iaNC}1tS0Kb`E`GJ2q_HxTV*}7fUHEd)$)}g>)i2z3~!*ElPXZr+ahR7-p{h?VNf-oyK(`- z`L>4|5zV083p#HxTanFf=S6fu^+IW6+EC%f#_>Jvh|CY;#)oPKFlU_|pTMdo`-3SHd3= zok(mD?b%1TZ=a91kALjHOWJKEvkaO)O>|+_X7IeR_GZY$gLfL5Zj8&$fB4BpJQ`Bk zeI8e;8g`QU(#j=WHvqfH^o)cm&#O*n+1nYXFkN-|)z$90cPphDF#-ROX}u?B&FObA zdtKCIV*k>#bL3>2Y!xar#5z;%0Ad{*?q>eARP)7G>nzsc_CM{=*3vc}u&#Gil*z9; z#VNkGLgCD?1V|-kKFZewJb5T5WPzGVQ@r|owO~cYd1%|2s=gDyD(Cxp!H-@GpXk2+ z(R%ZGlB9q}w8Ylya!uVst!E)}ps@`T?

y*~*Tn^TfB*sv!Mg>O+&0fenR6CkvC% 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 C@+b!Y literal 0 HcmV?d00001 diff --git a/assets/sounds/grass swish 1.ogg.import b/assets/sounds/grass swish 1.ogg.import new file mode 100644 index 0000000..ecb2456 --- /dev/null +++ b/assets/sounds/grass swish 1.ogg.import @@ -0,0 +1,15 @@ +[remap] + +importer="ogg_vorbis" +type="AudioStreamOGGVorbis" +path="res://.import/grass swish 1.ogg-bdbb4d7db9f101b427a7017365253335.oggstr" + +[deps] + +source_file="res://assets/sounds/grass swish 1.ogg" +dest_files=[ "res://.import/grass swish 1.ogg-bdbb4d7db9f101b427a7017365253335.oggstr" ] + +[params] + +loop=false +loop_offset=0 diff --git a/assets/sounds/grass swish 2.ogg b/assets/sounds/grass swish 2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7a16fbc6e54190e9239c6e4e6482d7698bf24588 GIT binary patch literal 31141 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 z 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 literal 0 HcmV?d00001 diff --git a/assets/sounds/grass swish 2.ogg.import b/assets/sounds/grass swish 2.ogg.import new file mode 100644 index 0000000..c5925e8 --- /dev/null +++ b/assets/sounds/grass swish 2.ogg.import @@ -0,0 +1,15 @@ +[remap] + +importer="ogg_vorbis" +type="AudioStreamOGGVorbis" +path="res://.import/grass swish 2.ogg-beebb4d61ae20e7e1fa9a915a809817d.oggstr" + +[deps] + +source_file="res://assets/sounds/grass swish 2.ogg" +dest_files=[ "res://.import/grass swish 2.ogg-beebb4d61ae20e7e1fa9a915a809817d.oggstr" ] + +[params] + +loop=false +loop_offset=0 diff --git a/assets/sounds/grass swish 3.ogg b/assets/sounds/grass swish 3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..17d41e368208de88dfde3deda470f26ff95cd956 GIT binary patch literal 32311 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 L!xI1i00000{aX;h literal 0 HcmV?d00001 diff --git a/assets/sounds/grass swish 3.ogg.import b/assets/sounds/grass swish 3.ogg.import new file mode 100644 index 0000000..43a7865 --- /dev/null +++ b/assets/sounds/grass swish 3.ogg.import @@ -0,0 +1,15 @@ +[remap] + +importer="ogg_vorbis" +type="AudioStreamOGGVorbis" +path="res://.import/grass swish 3.ogg-8d9986e80092be5e026c4d30b38c8a68.oggstr" + +[deps] + +source_file="res://assets/sounds/grass swish 3.ogg" +dest_files=[ "res://.import/grass swish 3.ogg-8d9986e80092be5e026c4d30b38c8a68.oggstr" ] + +[params] + +loop=false +loop_offset=0 diff --git a/assets/sounds/grass swish 4.ogg b/assets/sounds/grass swish 4.ogg new file mode 100644 index 0000000000000000000000000000000000000000..48752faedfe4af0f377dbb22d84717819226df75 GIT binary patch literal 29375 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

    *jce7$` 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 Rq+f^HfzR*+00000008_ void: - if level_state.is_dead: - return - var snap = Vector2.DOWN * 128 - var center_floor_rot = 0 - var floor_rot = 0 - var onfloor = is_on_floor() + if level_state.is_dead: + return + var snap = Vector2.DOWN * 128 + var center_floor_rot = 0 + var floor_rot = 0 + var onfloor = is_on_floor() - # get rotation of floor, compare collided floor with floor under center - if onfloor: - # TODO: Problem when correctly rotating? - center_floor_rot = $SlopeRaycast.get_collision_normal().rotated(PI / 2).angle() - floor_rot = get_floor_normal().rotated(PI / 2).angle() - if abs(center_floor_rot) > PI / 4 + 0.1: - center_floor_rot = floor_rot - # snap when on slopes - if (abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1) && snap_possible: - velocity = move_and_slide_with_snap(velocity.rotated(floor_rot), snap, FLOOR_NORMAL, true) - # normal slide on flat floor - else: - velocity = move_and_slide(velocity.rotated(floor_rot), FLOOR_NORMAL) - rotation = 0 - if ( - $SlopeRaycastLeft.is_colliding() - && $SlopeRaycastRight.is_colliding() - && $SlopeRaycast.is_colliding() - ): - rotation = calculate_slope_rotation(onfloor) - # rotate related to floor slope - # Convert velocity back to local space. - # TODO: Downward velocity should be increased by gravity - velocity = velocity.rotated(-floor_rot) if snap_possible else velocity + # get rotation of floor, compare collided floor with floor under center + if onfloor: + # TODO: Problem when correctly rotating? + center_floor_rot = $SlopeRaycast.get_collision_normal().rotated(PI / 2).angle() + floor_rot = get_floor_normal().rotated(PI / 2).angle() + if abs(center_floor_rot) > PI / 4 + 0.1: + center_floor_rot = floor_rot + # snap when on slopes + if (abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1) && snap_possible: + velocity = move_and_slide_with_snap(velocity.rotated(floor_rot), snap, FLOOR_NORMAL, true) + # normal slide on flat floor + else: + velocity = move_and_slide(velocity.rotated(floor_rot), FLOOR_NORMAL) + rotation = 0 + if ( + $SlopeRaycastLeft.is_colliding() + && $SlopeRaycastRight.is_colliding() + && $SlopeRaycast.is_colliding() + ): + rotation = calculate_slope_rotation(onfloor) + # rotate related to floor slope + # Convert velocity back to local space. + # TODO: Downward velocity should be increased by gravity + velocity = velocity.rotated(-floor_rot) if snap_possible else velocity func calculate_duck_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2: - var state = player_state_machine.state - var out_vel := linear_velocity - var velocity_direction = 1.0 - if velocity.x < 0: - velocity_direction = -1.0 + var state = player_state_machine.state + var out_vel := linear_velocity + var velocity_direction = 1.0 + if velocity.x < 0: + velocity_direction = -1.0 - # TODO Improve this to separate crawling(slow) and sliding - var deceleration_force = calculate_deceleration_force(_gravity, mass) * 0.333 + # TODO Improve this to separate crawling(slow) and sliding + var deceleration_force = calculate_deceleration_force(_gravity, mass) * 0.333 - # Slowing down movement when not controlling direction - if is_equal_approx(direction.x, 0): - # TODO Handle Deadzones - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta - ) - if abs(out_vel.x) > abs(velocity.x): - out_vel.x = 0 - else: - # Reversing movement - # When turning the opposite direction, friction is added to the opposite acceleration movement - var reverse_move = is_reversing_horizontal_movement(direction) - if reverse_move: - # TODO dont put constants in here - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta - ) - # Normal movement - if abs(velocity.x) < max_velocity[state]: - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, (acceleration_force[state].x) * direction.x, mass, delta - ) - elif !reverse_move: - out_vel.x = max_velocity[state] * direction.x - # TODO is_on_dropThrough does the action, is that ok? yEs, MaAsTeR-ChAn - # TODO Drop Through coyote time? - if Input.is_action_just_pressed("jump") && is_on_dropThrough(): - return Vector2(out_vel.x, _gravity * delta) - # Jumping when grounded or jump is buffered - if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()): - snap_possible = false - return calculate_jump_velocity(velocity, delta, direction) + # Slowing down movement when not controlling direction + if is_equal_approx(direction.x, 0): + # TODO Handle Deadzones + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta + ) + if abs(out_vel.x) > abs(velocity.x): + out_vel.x = 0 + else: + # Reversing movement + # When turning the opposite direction, friction is added to the opposite acceleration movement + var reverse_move = is_reversing_horizontal_movement(direction) + if reverse_move: + # TODO dont put constants in here + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta + ) + # Normal movement + if abs(velocity.x) < max_velocity[state]: + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, (acceleration_force[state].x) * direction.x, mass, delta + ) + elif !reverse_move: + out_vel.x = max_velocity[state] * direction.x + # TODO is_on_dropThrough does the action, is that ok? yEs, MaAsTeR-ChAn + # TODO Drop Through coyote time? + if Input.is_action_just_pressed("jump") && is_on_dropThrough(): + return Vector2(out_vel.x, _gravity * delta) + # Jumping when grounded or jump is buffered + if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping: + snap_possible = false + return calculate_jump_velocity(velocity, delta, direction) - elif player_state_machine.coyote_hanging: - out_vel.y = 0 + elif player_state_machine.coyote_hanging: + out_vel.y = 0 - else: - out_vel.y = _gravity * delta + else: + out_vel.y = _gravity * delta - return out_vel + return out_vel func is_on_dropThrough(): - var bodies: Array = $BlobbySkin.get_overlapping_bodies() - for i in range(0, bodies.size()): - if bodies[i].get_collision_mask_bit(7): - set_collision_mask_bit(7, false) - return true - return false + var bodies: Array = $BlobbySkin.get_overlapping_bodies() + for i in range(0, bodies.size()): + if bodies[i].get_collision_mask_bit(7): + set_collision_mask_bit(7, false) + return true + return false func calculate_grounded_velocity( - linear_velocity: Vector2, delta: float, direction: Vector2 + linear_velocity: Vector2, delta: float, direction: Vector2 ) -> Vector2: - var state = player_state_machine.state - var out_vel := linear_velocity - var velocity_direction = 1.0 - if velocity.x < 0: - velocity_direction = -1.0 + var state = player_state_machine.state + var out_vel := linear_velocity + var velocity_direction = 1.0 + if velocity.x < 0: + velocity_direction = -1.0 - var deceleration_force = calculate_deceleration_force(_gravity, mass) + var deceleration_force = calculate_deceleration_force(_gravity, mass) - # Slowing down movement when not controlling direction - if is_equal_approx(direction.x, 0): - # TODO Handle Deadzones - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta - ) - if abs(out_vel.x) > abs(velocity.x): - out_vel.x = 0 - else: - # Reversing movement - # When turning the opposite direction, friction is added to the opposite acceleration movement - var reverse_move = is_reversing_horizontal_movement(direction) - if reverse_move: - # TODO dont put constants in here - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta - ) - # Normal movement - if abs(velocity.x) < max_velocity[state]: - out_vel.x = PhysicsFunc.two_step_euler( - out_vel.x, - ( - ( - acceleration_force[state].x - + (init_acceleration_force[init_boost_type] * int(init_boost)) - ) - * direction.x - ), - mass, - delta - ) - elif !reverse_move: - out_vel.x = max_velocity[state] * direction.x - # Jumping when grounded or jump is buffered - if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()): - snap_possible = false - return calculate_jump_velocity(velocity, delta, direction) + # Slowing down movement when not controlling direction + if is_equal_approx(direction.x, 0): + # TODO Handle Deadzones + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta + ) + if abs(out_vel.x) > abs(velocity.x): + out_vel.x = 0 + else: + # Reversing movement + # When turning the opposite direction, friction is added to the opposite acceleration movement + var reverse_move = is_reversing_horizontal_movement(direction) + if reverse_move: + # TODO dont put constants in here + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta + ) + # Normal movement + if abs(velocity.x) < max_velocity[state]: + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, + ( + ( + acceleration_force[state].x + + (init_acceleration_force[init_boost_type] * int(init_boost)) + ) + * direction.x + ), + mass, + delta + ) + elif !reverse_move: + out_vel.x = max_velocity[state] * direction.x + # Jumping when grounded or jump is buffered + if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping: + snap_possible = false + return calculate_jump_velocity(velocity, delta, direction) - elif player_state_machine.coyote_hanging: - out_vel.y = 0 + elif player_state_machine.coyote_hanging: + out_vel.y = 0 - else: - out_vel.y = _gravity * delta + else: + out_vel.y = _gravity * delta - return out_vel + return out_vel # Determines if the player has reversed the steering direction # in reference to the current movement direction func is_reversing_horizontal_movement(direction: Vector2) -> bool: - return (direction.x > 0 && velocity.x < 0) || (direction.x < 0 && velocity.x > 0) + return (direction.x > 0 && velocity.x < 0) || (direction.x < 0 && velocity.x > 0) # Returns if the character is touching a wall with its whole body # Being able to touch a vertical surface over this length also makes it a qualified "wall" # Also sets wall_touch_direction func is_touching_wall_completely() -> bool: - var value = true - for left_raycast in left_wall_raycasts.get_children(): - wall_touch_direction = -1 - if !left_raycast.is_colliding(): - value = false - continue - if value == true: - return value + var value = true + for left_raycast in left_wall_raycasts.get_children(): + wall_touch_direction = -1 + if !left_raycast.is_colliding(): + value = false + continue + if value == true: + return value - value = true - for right_raycast in right_wall_raycasts.get_children(): - wall_touch_direction = 1 - if !right_raycast.is_colliding(): - value = false - continue - return value + value = true + for right_raycast in right_wall_raycasts.get_children(): + wall_touch_direction = 1 + if !right_raycast.is_colliding(): + value = false + continue + return value # Attached to wall state is in the PlayerStateMachine func is_correct_walljump_input(direction: Vector2) -> bool: - return ( - Input.is_action_just_pressed("jump") - && abs(direction.x + wall_touch_direction) < 1 - && abs(direction.x + wall_touch_direction) >= 0 - ) + return ( + Input.is_action_just_pressed("jump") + && abs(direction.x + wall_touch_direction) < 1 + && abs(direction.x + wall_touch_direction) >= 0 + ) func is_correct_airstrafe_input() -> bool: - return ( - air_strafe_charges > 0 - && (Input.is_action_just_pressed("move_right") || Input.is_action_just_pressed("move_left")) - ) + return ( + air_strafe_charges > 0 + && (Input.is_action_just_pressed("move_right") || Input.is_action_just_pressed("move_left")) + ) # Calculates the force of the ground friction func calculate_deceleration_force(_gravity: float, mass: float) -> float: - return floor_friction * _gravity * mass + return floor_friction * _gravity * mass + + +func calculate_stomp_velocity(delta: float) -> float: + var v = 0 + if Input.is_action_pressed("jump"): + v += stomp_feedback + # print(stomp_time) + stomp_time -= delta + # print(stomp_time) + if stomp_time <= 0: +# print("stomping over") + stomping = false + stomp_time = init_stomp_time + return v func calculate_jump_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2: - var state = player_state_machine.state - var additive_jump_force = velocity_jump_boost_ratio * abs(velocity.x) * mass - #TODO Single out stomping and make betta - #TODO too much force intially and too high with frog jump - if stomping: - if Input.is_action_pressed("jump"): - additive_jump_force += stomp_feedback - stomp_time -= delta - # print(stomp_time) - if stomp_time <= 0: -# print("stomping over") - stomping = false - stomp_time = init_stomp_time + var state = player_state_machine.state + var additive_jump_force = velocity_jump_boost_ratio * abs(velocity.x) * mass + #TODO Single out stomping and make betta + #TODO too much force intially and too high with frog jump + if stomping: + additive_jump_force += calculate_stomp_velocity(delta) - if state != "jump": - linear_velocity.y = PhysicsFunc.two_step_euler( - linear_velocity.y, - (acceleration_force[state].y / delta + additive_jump_force) * -1, - mass, - delta - ) + if state != "jump": + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y, + (acceleration_force[state].y / delta + additive_jump_force) * -1, + mass, + delta + ) # print(acceleration_force[state].y) # print(linear_velocity.y) - if !Input.is_action_pressed("jump") && !stomping: - # Smooth transition from jumping to falling - if velocity.y > _gravity * delta * 10: - linear_velocity.y += _gravity * delta * 10 - else: - linear_velocity.y += (max(abs(linear_velocity.y), _gravity * delta) / 2) + if !Input.is_action_pressed("jump") && !stomping: + # Smooth transition from jumping to falling + if velocity.y > _gravity * delta * 10: + linear_velocity.y += _gravity * delta * 10 + else: + linear_velocity.y += (max(abs(linear_velocity.y), _gravity * delta) / 2) - else: - linear_velocity.y += _gravity * delta + else: + linear_velocity.y += _gravity * delta - # TODO This is poop too - if ( - -max_velocity["jump"].x < velocity.x and direction.x < 0 - || max_velocity["jump"].x > velocity.x and direction.x > 0 - ): - var absolut = 1 - initial_velocity_dependence - var divisor = 1 / max(0.1, initial_velocity_dependence) - var movement_factor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor) - linear_velocity.x = PhysicsFunc.two_step_euler( - linear_velocity.x, - acceleration_force[state].x * movement_factor * direction.x, - mass, - delta - ) + # TODO This is poop too + if ( + -max_velocity["jump"].x < velocity.x and direction.x < 0 + || max_velocity["jump"].x > velocity.x and direction.x > 0 + ): + var absolut = 1 - initial_velocity_dependence + var divisor = 1 / max(0.1, initial_velocity_dependence) + var movement_factor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor) + linear_velocity.x = PhysicsFunc.two_step_euler( + linear_velocity.x, + acceleration_force[state].x * movement_factor * direction.x, + mass, + delta + ) - if is_correct_airstrafe_input(): - linear_velocity = execute_airstrafe(linear_velocity, delta, direction) + if is_correct_airstrafe_input(): + linear_velocity = execute_airstrafe(linear_velocity, delta, direction) # print(linear_velocity.y) - return linear_velocity + return linear_velocity # Only applicable to downwards gravity # Can set the jump buffer func calculate_fall_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2: - var state = player_state_machine.state - if velocity.y < max_velocity["fall"].y: - linear_velocity.y = PhysicsFunc.two_step_euler( - linear_velocity.y, _gravity * mass, mass, delta - ) - else: - linear_velocity.y = max_velocity["fall"].y - if ( - -max_velocity["fall"].x < velocity.x and direction.x < 0 - || max_velocity["fall"].x > velocity.x and direction.x > 0 - ): - # TODO This is poop - var absolut = 1 - initial_velocity_dependence - var divisor = 1 / max(0.1, initial_velocity_dependence) - var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor) - linear_velocity.x = PhysicsFunc.two_step_euler( - linear_velocity.x, - acceleration_force[state].x * movementFactor * direction.x, - mass, - delta - ) - if Input.is_action_just_pressed("jump"): - jump_buffer_filled = true - if is_correct_airstrafe_input(): - linear_velocity = execute_airstrafe(linear_velocity, delta, direction) - if stomping: - linear_velocity = calculate_jump_velocity(Vector2(linear_velocity.x, 0), delta, direction) - return linear_velocity + var state = player_state_machine.state + if velocity.y < max_velocity["fall"].y: + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y, _gravity * mass, mass, delta + ) + else: + linear_velocity.y = max_velocity["fall"].y + if ( + -max_velocity["fall"].x < velocity.x and direction.x < 0 + || max_velocity["fall"].x > velocity.x and direction.x > 0 + ): + # TODO This is poop + var absolut = 1 - initial_velocity_dependence + var divisor = 1 / max(0.1, initial_velocity_dependence) + var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor) + linear_velocity.x = PhysicsFunc.two_step_euler( + linear_velocity.x, + acceleration_force[state].x * movementFactor * direction.x, + mass, + delta + ) + if Input.is_action_just_pressed("jump"): + jump_buffer_filled = true + if is_correct_airstrafe_input(): + linear_velocity = execute_airstrafe(linear_velocity, delta, direction) + if stomping: + linear_velocity = calculate_jump_velocity(Vector2(linear_velocity.x, 0), delta, direction) + return linear_velocity func calculate_wallslide_velocity( - linear_velocity: Vector2, delta: float, direction: Vector2 + linear_velocity: Vector2, delta: float, direction: Vector2 ) -> Vector2: - # Walljump mechanics - if is_correct_walljump_input(direction): - linear_velocity.x = PhysicsFunc.two_step_euler( - 0, acceleration_force["walljump"].x / delta * direction.x, mass, delta - ) - linear_velocity.y = PhysicsFunc.two_step_euler( - 0, acceleration_force["walljump"].y / delta * -1, mass, delta - ) - elif is_correct_airstrafe_input(): - # var rev = 1 if !is_reversing_horizontal_movement(direction) else -1 - linear_velocity = execute_airstrafe(linear_velocity, delta, direction) - else: - # TODO dont put constants in here - linear_velocity.y = PhysicsFunc.two_step_euler( - linear_velocity.y * 0.94, _gravity * mass, mass, delta - ) - air_strafe_charges = ( - air_strafe_charges + 1 - if max_air_strafe_charges > air_strafe_charges - else 0 - ) - return linear_velocity.rotated(rotation) + # Walljump mechanics + if is_correct_walljump_input(direction): + linear_velocity.x = PhysicsFunc.two_step_euler( + 0, acceleration_force["walljump"].x / delta * direction.x, mass, delta + ) + linear_velocity.y = PhysicsFunc.two_step_euler( + 0, acceleration_force["walljump"].y / delta * -1, mass, delta + ) + elif is_correct_airstrafe_input(): + # var rev = 1 if !is_reversing_horizontal_movement(direction) else -1 + linear_velocity = execute_airstrafe(linear_velocity, delta, direction) + else: + # TODO dont put constants in here + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y * 0.94, _gravity * mass, mass, delta + ) + air_strafe_charges = ( + air_strafe_charges + 1 + if max_air_strafe_charges > air_strafe_charges + else 0 + ) + return linear_velocity.rotated(rotation) func execute_airstrafe(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2: - # var rev = 1 if !is_reversing_horizontal_movement(direction) else -1 - # TODO Consider adding a extra state for airstrafing - # TODO Make airstrafing less instantaneous and moderate the impulse - if direction.x > 0: - effect_player.play("airstrafing") - else: - effect_player.play("airstrafingLeft") - if is_reversing_horizontal_movement(direction): - linear_velocity.x = 0 - linear_velocity.x = PhysicsFunc.two_step_euler( - linear_velocity.x, acceleration_force["air_strafe"].x / delta * direction.x, mass, delta - ) - if linear_velocity.y > 0: - # TODO Put constant elsewhere - linear_velocity.y = linear_velocity.y * 0.33 - air_strafe_charges -= 1 - return linear_velocity + # var rev = 1 if !is_reversing_horizontal_movement(direction) else -1 + # TODO Consider adding a extra state for airstrafing + # TODO Make airstrafing less instantaneous and moderate the impulse + if direction.x > 0: + effect_player.play("airstrafing") + else: + effect_player.play("airstrafingLeft") + if is_reversing_horizontal_movement(direction): + linear_velocity.x = 0 + linear_velocity.x = PhysicsFunc.two_step_euler( + linear_velocity.x, acceleration_force["air_strafe"].x / delta * direction.x, mass, delta + ) + if linear_velocity.y > 0: + # TODO Put constant elsewhere + linear_velocity.y = linear_velocity.y * 0.33 + air_strafe_charges -= 1 + return linear_velocity func calculate_slope_rotation(_onfloor: bool) -> float: - var angle = 0 - var slope_angle_left = $SlopeRaycastLeft.get_collision_normal().rotated(PI / 2).angle() - var slope_angle_right = $SlopeRaycastRight.get_collision_normal().rotated(PI / 2).angle() - # avoid invalid angles and stay in rotation when touching ground completely - if ( - !(-PI / 2 <= slope_angle_left && slope_angle_left <= PI / 2) - || !(-PI / 2 <= slope_angle_right && slope_angle_right <= PI / 2) - || (is_equal_approx(abs(slope_angle_left), abs(slope_angle_right))) - ): - return ( - previous_rotation - if abs(rad2deg(previous_rotation)) > 1 && !is_equal_approx(slope_angle_left, 0) - else 0.0 - ) - # downturn - if ( - abs(slope_angle_left) > abs(slope_angle_right) && velocity.x < -10 - || abs(slope_angle_right) > abs(slope_angle_left) && velocity.x > 10 - ): - var length_vector: Vector2 = ( - $SlopeRaycastRight.get_collision_point() - - $SlopeRaycastLeft.get_collision_point() - ) - angle = length_vector.angle() - # upturn - else: - var length_vector: Vector2 = ( - $SlopeRaycastLeft.get_collision_point() - - $SlopeRaycastRight.get_collision_point() - ) - angle = length_vector.angle() - PI - previous_rotation = angle - if is_equal_approx(deg2rad(angle), 0): - pass - return angle + var angle = 0 + var slope_angle_left = $SlopeRaycastLeft.get_collision_normal().rotated(PI / 2).angle() + var slope_angle_right = $SlopeRaycastRight.get_collision_normal().rotated(PI / 2).angle() + # avoid invalid angles and stay in rotation when touching ground completely + if ( + !(-PI / 2 <= slope_angle_left && slope_angle_left <= PI / 2) + || !(-PI / 2 <= slope_angle_right && slope_angle_right <= PI / 2) + || (is_equal_approx(abs(slope_angle_left), abs(slope_angle_right))) + ): + return ( + previous_rotation + if abs(rad2deg(previous_rotation)) > 1 && !is_equal_approx(slope_angle_left, 0) + else 0.0 + ) + # downturn + if ( + abs(slope_angle_left) > abs(slope_angle_right) && velocity.x < -10 + || abs(slope_angle_right) > abs(slope_angle_left) && velocity.x > 10 + ): + var length_vector: Vector2 = ( + $SlopeRaycastRight.get_collision_point() + - $SlopeRaycastLeft.get_collision_point() + ) + angle = length_vector.angle() + # upturn + else: + var length_vector: Vector2 = ( + $SlopeRaycastLeft.get_collision_point() + - $SlopeRaycastRight.get_collision_point() + ) + angle = length_vector.angle() - PI + previous_rotation = angle + if is_equal_approx(deg2rad(angle), 0): + pass + return angle # TODO could be expanded with a parameter about what got stomped func stomp() -> void: # print("stomping") - stomping = true + print(player_state_machine.state) + scene_audio.play_parallel_sound( + "res://assets/sounds/FABRIC_Flap_03_mono.wav", -15, false, 1.5, 0.2 + ) + scene_audio.play_parallel_sound("res://assets/sounds/CLASP_Plastic_Open_stereo.wav", -12) + stomping = true # TOD lose_power_up function func receive_power_up(kind: String) -> void: - if kind == "shield": - $BubbleShieldViewport/IridescenceBall.visible = true - shielded = true + if kind == "shield": + $BubbleShieldViewport/IridescenceBall.visible = true + shielded = true # TODO Maybe this should be a state in itself? func die(animation_number: int = 0) -> void: - if level_state.is_dead: - return - if shielded: - shielded = false - $BubbleShieldViewport/IridescenceBall.visible = false - $InvincibilityTimer.start() - $BlobbySprite.material = invincible_shader - return - elif !$InvincibilityTimer.is_stopped(): - return - z_index = 1 - $BlobbySprite.material = death_shader - signal_manager.emit_signal("player_died", animation_number) - $"%BlobbymationTree".active = false - $"%BlobbymationPlayer".play("dying3") - if animation_number < 1: - $"%BlobbymationPlayer".play("expandingDisolve") - scene_audio.play_parallel_sound(death_sound_1, -15) - scene_audio.play_parallel_sound(death_sound_2, -16) + if level_state.is_dead: + return + if shielded: + shielded = false + $BubbleShieldViewport/IridescenceBall.visible = false + $InvincibilityTimer.start() + $BlobbySprite.material = invincible_shader + return + elif !$InvincibilityTimer.is_stopped(): + return + z_index = 1 + $BlobbySprite.material = death_shader + signal_manager.emit_signal("player_died", animation_number) + $"%BlobbymationTree".active = false + $"%BlobbymationPlayer".play("dying3") + if animation_number < 1: + $"%BlobbymationPlayer".play("expandingDisolve") + scene_audio.play_parallel_sound(death_sound_1, -15) + scene_audio.play_parallel_sound(death_sound_2, -16) func die_for_real(animation_number: int = 0) -> void: - shielded = false - $BubbleShieldViewport/IridescenceBall.visible = false - die(animation_number) + shielded = false + $BubbleShieldViewport/IridescenceBall.visible = false + die(animation_number) # TODO Checkpoint system func respawn() -> void: - # Is tied to the death animation - get_tree().reload_current_scene() + # Is tied to the death animation + get_tree().reload_current_scene() # When the Enemy stomp AREA enters the enemy collision area -> stomp func _on_BlobbySkin_area_entered(area: Area2D) -> void: - if area.is_in_group("harmful"): - die() - if area.is_in_group("pit"): - $PitfallTimer.start() + if area.is_in_group("harmful"): + die() + if area.is_in_group("pit"): + $PitfallTimer.start() # This problem stems from trying to decelerate a walk @@ -464,49 +476,49 @@ func _on_BlobbySkin_area_entered(area: Area2D) -> void: # It is particularly usefull for moving floor physics # TODO Setting y velocity this way stopped is_on_floor() from working correctly func _on_Blobby_got_grounded() -> void: - velocity.x -= get_floor_velocity().x - snap_possible = true - var floor_object = get_last_slide_collision().collider.get_parent() - #TODO There is already a friction property in engine - if "slide_friction" in floor_object: - floor_friction = floor_object.slide_friction - else: - floor_friction = base_floor_friction - air_strafe_charges = ( - air_strafe_charges + 1 - if max_air_strafe_charges > air_strafe_charges - else 0 - ) + velocity.x -= get_floor_velocity().x + snap_possible = true + var floor_object = get_last_slide_collision().collider.get_parent() + #TODO There is already a friction property in engine + if "slide_friction" in floor_object: + floor_friction = floor_object.slide_friction + else: + floor_friction = base_floor_friction + air_strafe_charges = ( + air_strafe_charges + 1 + if max_air_strafe_charges > air_strafe_charges + else 0 + ) func _on_BlobbySkin_body_exited(body: Node) -> void: - # This is for drop through platforms - if body.get_collision_mask_bit(7): - set_collision_mask_bit(7, true) + # This is for drop through platforms + if body.get_collision_mask_bit(7): + set_collision_mask_bit(7, true) func _on_InvincibilityTimer_timeout() -> void: - $BlobbySprite.material = null - for area in $BlobbySkin.get_overlapping_areas(): - if area.is_in_group("harmful"): - die() + $BlobbySprite.material = null + for area in $BlobbySkin.get_overlapping_areas(): + if area.is_in_group("harmful"): + die() func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2: - return calculate_grounded_velocity(velocity, delta, direction) + return calculate_grounded_velocity(velocity, delta, direction) func handle_jump_movement(delta: float, direction: Vector2) -> Vector2: - return calculate_jump_velocity(velocity, delta, direction) + return calculate_jump_velocity(velocity, delta, direction) func handle_duck_movement(delta: float, direction: Vector2) -> Vector2: - return calculate_duck_velocity(velocity, delta, direction) + return calculate_duck_velocity(velocity, delta, direction) func handle_fall_movement(delta: float, direction: Vector2) -> Vector2: - return calculate_fall_velocity(velocity, delta, direction) + return calculate_fall_velocity(velocity, delta, direction) func handle_wallslide_movement(delta: float, direction: Vector2) -> Vector2: - return calculate_wallslide_velocity(velocity, delta, direction) + return calculate_wallslide_velocity(velocity, delta, direction) diff --git a/src/Actors/Blobby/Blobby.tscn b/src/Actors/Blobby/Blobby.tscn index a250edf..a6007b8 100644 --- a/src/Actors/Blobby/Blobby.tscn +++ b/src/Actors/Blobby/Blobby.tscn @@ -4385,7 +4385,7 @@ texture = SubResource( 62 ) offset = Vector2( 1, 0 ) hframes = 6 vframes = 6 -frame = 10 +frame = 7 __meta__ = { "_editor_description_": "YXNlcHJpdGVfd2l6YXJkX2NvbmZpZwpwbGF5ZXJ8PUJsb2JieVNwcml0ZS9CbG9iYnltYXRpb25QbGF5ZXIKc291cmNlfD1yZXM6Ly9hc3NldHMvYmxvYmJ5L2Jsb2JieS1zcHJpdGVzaGVldHQuYXNlcHJpdGUKbGF5ZXJ8PUJsb2JieQpvcF9leHB8PUZhbHNlCm9fZm9sZGVyfD0Kb19uYW1lfD0Kb25seV92aXNpYmxlfD1GYWxzZQpvX2V4X3B8PQo=" } diff --git a/src/Actors/BlobbyCam.gd b/src/Actors/BlobbyCam.gd index e3a2061..3ceaee1 100644 --- a/src/Actors/BlobbyCam.gd +++ b/src/Actors/BlobbyCam.gd @@ -5,7 +5,7 @@ export var offset_reset_seconds := 1 export var offset_adapt_seconds := 1 export var offset_input_seconds := 0.618 * 2 export var alarm_light_shader: Material -export var fixed_position : bool = false +export var fixed_position: bool = false onready var level_state := $"%LevelState" onready var signal_manager := $"%SignalManager" @@ -29,7 +29,7 @@ var original_limit_right: int var original_limit_bottom: int var original_limit_top: int var camera_is_panning: bool = false -var target_offset: Vector2 = Vector2(0,0) +var target_offset: Vector2 = Vector2(0, 0) var terminal_activated: bool = false var image = Image.new() @@ -38,232 +38,252 @@ var prev_pos: Vector2 var camera_state := "centered" var screen_rect = Vector2() -var old_screen_rect = Vector2(ProjectSettings.get_setting("display/window/size/width") * zoom.x, ProjectSettings.get_setting("display/window/size/height") * zoom.y ) +var old_screen_rect = Vector2( + ProjectSettings.get_setting("display/window/size/width") * zoom.x, + ProjectSettings.get_setting("display/window/size/height") * zoom.y +) var screen_center = Vector2() var screen_bottom = Vector2() var screen_top = Vector2() var screen_left = Vector2() var screen_right = Vector2() + # Gets the camera limits from the tilemap of the level # Requires "TileMap" to be a sibling of blobby func _ready(): - _set_boundaries() - get_tree().get_root().connect("size_changed", self, "_set_boundaries") - if !fixed_position: - self.position = blobby.global_position - image.create(128, 2, false, Image.FORMAT_RGBAH) - # TODO Test Performance - material.set_shader_param("light_data", null) - _update_lighting_shader() - # TODO Trigger when needed - signal_manager.connect("terminal_activated", self, "_on_SignalManager_terminal_activated") - signal_manager.connect("player_died", self, "_death_cam") + _set_boundaries() + get_tree().get_root().connect("size_changed", self, "_set_boundaries") + if !fixed_position: + self.position = blobby.global_position + image.create(128, 2, false, Image.FORMAT_RGBAH) + # TODO Test Performance + material.set_shader_param("light_data", null) + _update_lighting_shader() + # TODO Trigger when needed + signal_manager.connect("terminal_activated", self, "_on_SignalManager_terminal_activated") + signal_manager.connect("player_died", self, "_death_cam") + func _on_SignalManager_terminal_activated(animation_number: int = 0): - terminal_activated = true - get_node("LightAnimationPlayer").play("Pulsing") + terminal_activated = true + get_node("LightAnimationPlayer").play("Pulsing") + #func _draw(): # draw_line(Vector2((limit_left - position.x), screen_center.y), screen_left, Color(255, 0, 0), 1) + func _physics_process(delta: float) -> void: - if fixed_position: - return + if fixed_position: + return # update() - screen_center = (get_camera_screen_center() - position) - screen_bottom = screen_center + Vector2(0, screen_rect.y/2) - screen_top = screen_center - Vector2(0, screen_rect.y/2) - screen_left = screen_center - Vector2(screen_rect.x/2, 0) - screen_right = screen_center + Vector2(screen_rect.x/2, 0) - var was_adjusted := false - if(!level_state.is_dead): - was_adjusted = _adjust_offset(delta) + screen_center = (get_camera_screen_center() - position) + screen_bottom = screen_center + Vector2(0, screen_rect.y / 2) + screen_top = screen_center - Vector2(0, screen_rect.y / 2) + screen_left = screen_center - Vector2(screen_rect.x / 2, 0) + screen_right = screen_center + Vector2(screen_rect.x / 2, 0) + var was_adjusted := false + if !level_state.is_dead: + was_adjusted = _adjust_offset(delta) - if(anim_player.is_playing() || was_adjusted): - position = blobby.position - prev_pos = position - _update_lighting_shader() - return - var player_vel = (blobby.position - prev_pos)/delta - # TODO Take average of velocity here - if(abs(player_vel.x) >= blobby.max_velocity["walk"] * 0.97 - && (sign(player_vel.x) == sign(target_offset.x) || target_offset.x == 0)): - if(player_vel.x > 0): - right_move_time += delta - left_move_time = max(0, left_move_time - delta) - slow_time = max(0, slow_time - delta) - else: - left_move_time += delta - right_move_time = max(0, right_move_time - delta) - slow_time = max(0, slow_time - delta) - elif(abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.9 - || sign(player_vel.x) != sign(target_offset.x) || target_offset.x == 0): - slow_time += delta - left_move_time = max(0, left_move_time - delta) - right_move_time = max(0, right_move_time - delta) + if anim_player.is_playing() || was_adjusted: + position = blobby.position + prev_pos = position + _update_lighting_shader() + return + var player_vel = (blobby.position - prev_pos) / delta + # TODO Take average of velocity here + if ( + abs(player_vel.x) >= blobby.max_velocity["walk"] * 0.97 + && (sign(player_vel.x) == sign(target_offset.x) || target_offset.x == 0) + ): + if player_vel.x > 0: + right_move_time += delta + left_move_time = max(0, left_move_time - delta) + slow_time = max(0, slow_time - delta) + else: + left_move_time += delta + right_move_time = max(0, right_move_time - delta) + slow_time = max(0, slow_time - delta) + elif ( + abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.9 + || sign(player_vel.x) != sign(target_offset.x) + || target_offset.x == 0 + ): + slow_time += delta + left_move_time = max(0, left_move_time - delta) + right_move_time = max(0, right_move_time - delta) + + _adapt_to_movement(player_vel) + if abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.9: + _adapt_to_input(player_vel, delta) + position = blobby.position + prev_pos = position + _update_lighting_shader() - _adapt_to_movement(player_vel) - if abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.9: - _adapt_to_input(player_vel, delta) - position = blobby.position - prev_pos = position - _update_lighting_shader() # TODO This has to be redone when the screen is resized in any way # Otherwise the boundaries will not be correct anymore func _set_boundaries(): - screen_rect = get_viewport_rect().size - screen_rect.x *= zoom.x - screen_rect.y *= zoom.y - original_x_zoom = zoom.x - original_y_zoom = zoom.y - # This is ok, because it only happens on initialization - # But it is also quite fickle - var tilemap = get_node("./%TileMap") - # TODO: This goes wrong when overwriting old tiles with new sprites - # New pngs -> completely new tiles and rebuild map - var rect = tilemap.get_used_rect() - var cell_size = tilemap.cell_size - # TODO is fixed for camera issue in adjust horizontal - limit_right = rect.end.x * cell_size.x - 6 - limit_left = rect.position.x * cell_size.x + 6 - limit_top = rect.position.y * cell_size.y + 6 - limit_bottom = rect.end.y * cell_size.y - 6 - original_limit_left = limit_left - original_limit_right = limit_right - original_limit_top = limit_top - original_limit_bottom = limit_bottom - var screen_size = get_viewport_rect() - var h_pixels = limit_right - limit_left - var v_pixels = limit_bottom - limit_top - # TODO: Fix that it can zoom both? - if screen_size.end.x * original_x_zoom - h_pixels > 0: - zoom.x = h_pixels / screen_size.end.x - zoom.y = zoom.x - if screen_size.end.y * original_y_zoom - v_pixels > 0: - zoom.y = v_pixels / screen_size.end.y - zoom.x = zoom.y + screen_rect = get_viewport_rect().size + screen_rect.x *= zoom.x + screen_rect.y *= zoom.y + original_x_zoom = zoom.x + original_y_zoom = zoom.y + # This is ok, because it only happens on initialization + # But it is also quite fickle + var tilemap = get_node("./%TileMap") + # TODO: This goes wrong when overwriting old tiles with new sprites + # New pngs -> completely new tiles and rebuild map + var rect = tilemap.get_used_rect() + var cell_size = tilemap.cell_size + # TODO is fixed for camera issue in adjust horizontal + limit_right = rect.end.x * cell_size.x - 6 + limit_left = rect.position.x * cell_size.x + 6 + limit_top = rect.position.y * cell_size.y + 6 + limit_bottom = rect.end.y * cell_size.y - 6 + original_limit_left = limit_left + original_limit_right = limit_right + original_limit_top = limit_top + original_limit_bottom = limit_bottom + var screen_size = get_viewport_rect() + var h_pixels = limit_right - limit_left + var v_pixels = limit_bottom - limit_top + # TODO: Fix that it can zoom both? + if screen_size.end.x * original_x_zoom - h_pixels > 0: + zoom.x = h_pixels / screen_size.end.x + zoom.y = zoom.x + if screen_size.end.y * original_y_zoom - v_pixels > 0: + zoom.y = v_pixels / screen_size.end.y + zoom.x = zoom.y + # Smoothing the camera limits in godot ruins something func _adapt_to_movement(velocity: Vector2) -> void: - var offset_track - var center = get_camera_screen_center() - var left_edge_pos = center.x - screen_rect.x/2 + camera_horizontal_shift - var right_edge_pos = center.x + screen_rect.x/2 - camera_horizontal_shift - if(left_move_time >= offset_adapt_seconds && !anim_player.is_playing()): - left_move_time = 0 - target_offset.x = -camera_horizontal_shift - if(offset == target_offset): - return - offset_track = shiftLeft.find_track(".:offset") - shiftLeft.track_set_key_value(offset_track, 0, offset) - shiftLeft.track_set_key_value(offset_track, 1, target_offset) - camera_state = "shiftedLeft" - anim_player.play("shiftingLeft") - elif(right_move_time >= offset_adapt_seconds && !anim_player.is_playing()): - right_move_time = 0 - target_offset.x = camera_horizontal_shift - if(offset == target_offset): - return - offset_track = shiftRight.find_track(".:offset") - shiftRight.track_set_key_value(offset_track, 0, offset) - shiftRight.track_set_key_value(offset_track, 1, target_offset) - camera_state = "shiftedRight" - anim_player.play("shiftingRight") - elif(slow_time >= offset_reset_seconds && - !(Input.is_action_pressed("up") || Input.is_action_pressed("duck"))): - slow_time = 0 - target_offset.x = 0 - if(offset == target_offset): - return - if(left_edge_pos > limit_left && limit_right > right_edge_pos): - offset_track = shiftCenter.find_track(".:offset") - shiftCenter.track_set_key_value(offset_track, 0, offset) - shiftCenter.track_set_key_value(offset_track, 1, target_offset) - camera_state = "centered" - anim_player.play("shiftingCenter") - return + var offset_track + var center = get_camera_screen_center() + var left_edge_pos = center.x - screen_rect.x / 2 + camera_horizontal_shift + var right_edge_pos = center.x + screen_rect.x / 2 - camera_horizontal_shift + if left_move_time >= offset_adapt_seconds && !anim_player.is_playing(): + left_move_time = 0 + target_offset.x = -camera_horizontal_shift + if offset == target_offset: + return + offset_track = shiftLeft.find_track(".:offset") + shiftLeft.track_set_key_value(offset_track, 0, offset) + shiftLeft.track_set_key_value(offset_track, 1, target_offset) + camera_state = "shiftedLeft" + anim_player.play("shiftingLeft") + elif right_move_time >= offset_adapt_seconds && !anim_player.is_playing(): + right_move_time = 0 + target_offset.x = camera_horizontal_shift + if offset == target_offset: + return + offset_track = shiftRight.find_track(".:offset") + shiftRight.track_set_key_value(offset_track, 0, offset) + shiftRight.track_set_key_value(offset_track, 1, target_offset) + camera_state = "shiftedRight" + anim_player.play("shiftingRight") + elif ( + slow_time >= offset_reset_seconds + && !(Input.is_action_pressed("up") || Input.is_action_pressed("duck")) + ): + slow_time = 0 + target_offset.x = 0 + if offset == target_offset: + return + if left_edge_pos > limit_left && limit_right > right_edge_pos: + offset_track = shiftCenter.find_track(".:offset") + shiftCenter.track_set_key_value(offset_track, 0, offset) + shiftCenter.track_set_key_value(offset_track, 1, target_offset) + camera_state = "centered" + anim_player.play("shiftingCenter") + return + func _adapt_to_input(velocity: Vector2, delta: float) -> void: - # TODO Den bug dass man damit durch die map gucken kann wenn man sich weiter bewegt - # lasse ich erstmal drin - if(velocity.length() > 20.0): - input_time = 0 - return - if(input_time < offset_input_seconds): - input_time += delta - return - if Input.is_action_pressed("duck"): - if(original_limit_bottom - position.y - 2 > screen_bottom.y && offset.y < 48): - offset.y += 0.5 - elif Input.is_action_pressed("up"): - if(original_limit_top - position.y + 2 < screen_top.y && offset.y > -48): - offset.y -= 0.5 + # TODO Den bug dass man damit durch die map gucken kann wenn man sich weiter bewegt + # lasse ich erstmal drin + if velocity.length() > 20.0: + input_time = 0 + return + if input_time < offset_input_seconds: + input_time += delta + return + if Input.is_action_pressed("duck"): + if original_limit_bottom - position.y - 2 > screen_bottom.y && offset.y < 48: + offset.y += 0.5 + elif Input.is_action_pressed("up"): + if original_limit_top - position.y + 2 < screen_top.y && offset.y > -48: + offset.y -= 0.5 + # TODO This is a regulatory problem, it doesn't adapt fast enough # TODO Maybe just make background black and dont bother -func _adjust_offset(delta: float) -> bool: - var new_offset = offset - if (limit_left - position.x - screen_left.x > 0.1): - if (anim_player.is_playing()): - anim_player.stop(true) - new_offset.x += (limit_left - position.x - screen_left.x)/1.5 - if (limit_right - position.x - screen_right.x < 0.1): - if (anim_player.is_playing()): - anim_player.stop(true) - new_offset.x += (limit_right - position.x - screen_right.x)/1.5 - if (limit_top - position.y - screen_top.y > 0.001): - new_offset.y += (limit_top - position.y - screen_top.y)/1.5 - if (limit_bottom - position.y - screen_bottom.y < 0.001): - new_offset.y += (limit_bottom - position.y - screen_bottom.y)/1.5 - #print(abs(offset.x) - abs(new_offset.x)) - if(abs(offset.x) > abs(new_offset.x) || abs(offset.y) > abs(new_offset.y)): - offset = new_offset - return true - else: - return false - - +func _adjust_offset(delta: float) -> bool: + var new_offset = offset + if limit_left - position.x - screen_left.x > 0.1: + if anim_player.is_playing(): + anim_player.stop(true) + new_offset.x += (limit_left - position.x - screen_left.x) / 1.5 + if limit_right - position.x - screen_right.x < 0.1: + if anim_player.is_playing(): + anim_player.stop(true) + new_offset.x += (limit_right - position.x - screen_right.x) / 1.5 + if limit_top - position.y - screen_top.y > 0.001: + new_offset.y += (limit_top - position.y - screen_top.y) / 1.5 + if limit_bottom - position.y - screen_bottom.y < 0.001: + new_offset.y += (limit_bottom - position.y - screen_bottom.y) / 1.5 + #print(abs(offset.x) - abs(new_offset.x)) + if abs(offset.x) > abs(new_offset.x) || abs(offset.y) > abs(new_offset.y): + offset = new_offset + return true + else: + return false + + func reset_limits() -> void: - limit_left = original_limit_left - limit_right = original_limit_right - limit_bottom = original_limit_bottom - limit_top = original_limit_top + limit_left = original_limit_left + limit_right = original_limit_right + limit_bottom = original_limit_bottom + limit_top = original_limit_top + func _death_cam(animation_number: int = 0) -> void: - if(animation_number < 1): - $CameraAnimationPlayer.play("deathCamJustZoom") - if(animation_number == 1): - $CameraAnimationPlayer.play("deathCamLateRotation") + if animation_number < 1: + $CameraAnimationPlayer.play("deathCamJustZoom") + if animation_number == 1: + $CameraAnimationPlayer.play("deathCamLateRotation") + # TODO Rename to alarm lights specially func _update_lighting_shader() -> void: - if !terminal_activated: return - # Props to gameendaevour - # TODO get this into a central world update management system - var lights = get_tree().get_nodes_in_group("light") - image.lock() - for i in lights.size(): - var light = lights[i] - # TODO To make the lighting affect all layers properly - # I would have the access the global positions of nodes in different Z layers - # without the projection to the global center layer. + if !terminal_activated: + return + # Props to gameendaevour + # TODO get this into a central world update management system + var lights = get_tree().get_nodes_in_group("light") + image.lock() + for i in lights.size(): + var light = lights[i] + # TODO To make the lighting affect all layers properly + # I would have the access the global positions of nodes in different Z layers + # without the projection to the global center layer. - # var vtrans = get_canvas_transform() - # var top_left = -vtrans.origin / vtrans.get_scale() - # var vsize = get_viewport_rect().size - # var t = Transform2D(0, (top_left + 0.5*vsize/vtrans.get_scale()).rotated(rotation)) - image.set_pixel(i, 0, Color( - light.position.x, light.position.y, - light.strength, light.radius - )) - image.set_pixel(i, 1, light.color) - image.unlock() + # var vtrans = get_canvas_transform() + # var top_left = -vtrans.origin / vtrans.get_scale() + # var vsize = get_viewport_rect().size + # var t = Transform2D(0, (top_left + 0.5*vsize/vtrans.get_scale()).rotated(rotation)) + image.set_pixel( + i, 0, Color(light.position.x, light.position.y, light.strength, light.radius) + ) + image.set_pixel(i, 1, light.color) + image.unlock() - texture.create_from_image(image) + texture.create_from_image(image) - material.set_shader_param("n_lights", lights.size()) - material.set_shader_param("light_data", texture) - material.set_shader_param("global_transform", get_global_transform()) - material.set_shader_param("viewport_transform", get_viewport_transform()) + material.set_shader_param("n_lights", lights.size()) + material.set_shader_param("light_data", texture) + material.set_shader_param("global_transform", get_global_transform()) + material.set_shader_param("viewport_transform", get_viewport_transform()) diff --git a/src/Actors/Enemies/Caterpillar.gd b/src/Actors/Enemies/Caterpillar.gd index 9526d24..1252839 100644 --- a/src/Actors/Enemies/Caterpillar.gd +++ b/src/Actors/Enemies/Caterpillar.gd @@ -9,20 +9,29 @@ export var block_size := 16 var time = 0 var snap = Vector2.DOWN * block_size + func _ready() -> void: - velocity.x = -120 + velocity.x = -120 + func execute_movement(delta: float) -> void: - # rotation - var movement = max(0,sign(sin(time*15))) - if(left_src.is_colliding() && right_src.is_colliding() && !left_wrc.is_colliding() && !right_wrc.is_colliding()): - pass - elif(left_wrc.is_colliding() || (!right_src.is_colliding() && left_src.is_colliding())): - rotation += delta * 7 * movement - else: - rotation += sign(velocity.x) * delta * 7 * movement - - # velocity - var v = Vector2(velocity.x * movement, 0) - time += delta - move_and_slide_with_snap(v.rotated(rotation), snap.rotated(rotation), FLOOR_NORMAL, false, 4, PI, false) + # rotation + var movement = max(0, sign(sin(time * 15))) + if ( + left_src.is_colliding() + && right_src.is_colliding() + && !left_wrc.is_colliding() + && !right_wrc.is_colliding() + ): + pass + elif left_wrc.is_colliding() || (!right_src.is_colliding() && left_src.is_colliding()): + rotation += delta * 7 * movement + else: + rotation += sign(velocity.x) * delta * 7 * movement + + # velocity + var v = Vector2(velocity.x * movement, 0) + time += delta + move_and_slide_with_snap( + v.rotated(rotation), snap.rotated(rotation), FLOOR_NORMAL, false, 4, PI, false + ) diff --git a/src/Actors/Enemies/Enemy.gd b/src/Actors/Enemies/Enemy.gd index 88d7188..4b72eba 100644 --- a/src/Actors/Enemies/Enemy.gd +++ b/src/Actors/Enemies/Enemy.gd @@ -3,31 +3,35 @@ class_name Enemy var player_entered_stomp = false + func _on_StompDetector_body_entered(body: Node) -> void: - if !body.is_in_group("player"): - return - player_entered_stomp = true - var incoming_vel_vector: Vector2 = body.velocity.normalized() - print(rad2deg(abs(incoming_vel_vector.angle_to(Vector2.DOWN.rotated(rotation))))) - if abs(incoming_vel_vector.angle_to(Vector2.DOWN.rotated(rotation))) > deg2rad(95): - print("too shallow entry") - body.die() - player_entered_stomp = false - return - signal_manager.emit_signal("got_stomped") - remove_from_group("harmful") - $StompDetector.remove_from_group("weakpoint") - get_node("EnemyBody").disabled = true - die() + if !body.is_in_group("player"): + return + player_entered_stomp = true + var incoming_vel_vector: Vector2 = body.velocity.normalized() + print(rad2deg(abs(incoming_vel_vector.angle_to(Vector2.DOWN.rotated(rotation))))) + if abs(incoming_vel_vector.angle_to(Vector2.DOWN.rotated(rotation))) > deg2rad(95): + print("too shallow entry") + body.die() + player_entered_stomp = false + return + signal_manager.emit_signal("got_stomped") + remove_from_group("harmful") + $StompDetector.remove_from_group("weakpoint") + get_node("EnemyBody").disabled = true + die() + func die() -> void: - queue_free() + queue_free() + + +func _on_EnemySkin_area_entered(area: Area2D) -> void: + if area.is_in_group("harmful"): + get_node("EnemyBody").disabled = true + die() + -func _on_EnemySkin_area_entered(area:Area2D) -> void: - if area.is_in_group("harmful"): - get_node("EnemyBody").disabled = true - die() - func _on_EnemySkin_body_entered(body: Node) -> void: - if body.is_in_group("player") && !player_entered_stomp: - body.die() + if body.is_in_group("player") && !player_entered_stomp: + body.die() diff --git a/src/Actors/Friendlies/WhatAreFrog.gd b/src/Actors/Friendlies/WhatAreFrog.gd index ecc2b76..0a7614d 100644 --- a/src/Actors/Friendlies/WhatAreFrog.gd +++ b/src/Actors/Friendlies/WhatAreFrog.gd @@ -3,9 +3,8 @@ const PhysicsFunc = preload("res://src/Utilities/Physic/PhysicsFunc.gd") onready var players = get_tree().get_nodes_in_group("player") - onready var vision_raycast: RayCast2D = $VisionRayCast -onready var orientation: RayCast2D = $Orientation +onready var orientation: RayCast2D = $Orientation onready var feeler_raycast: RayCast2D = $FeelerRayCast onready var tilemap: TileMap = $"../%TileMap" onready var state_machine = $Statemachine @@ -28,8 +27,6 @@ export var jump_time_standard_deviation := 0.1 # TODO Make constant for project export var block_size := 16 - - # Also in blocks var movement_radius: float var anchor: Node2D @@ -56,288 +53,319 @@ var attached_player = null func _ready(): - default_jump_distance = default_jump_distance * tilemap.cell_size.x - jump_timer = Timer.new() - jump_timer.set_one_shot(true) - jump_timer.connect("timeout", self, "jump") - target_lost_timer = Timer.new() - target_lost_timer.set_one_shot(true) - target_lost_timer.connect("timeout", self, "loose_target") - add_child(jump_timer) - add_child(target_lost_timer) - # TODO this is so bad ;_; - if(get_parent().name.begins_with("Bound")): - is_bound = true - else: - level_state.free_a_frog(frog_number) - level_state.register_frog(frog_number, !is_bound) - # TODO Stays harmless for now - #if(is_bound): add_to_group("harmful") + default_jump_distance = default_jump_distance * tilemap.cell_size.x + jump_timer = Timer.new() + jump_timer.set_one_shot(true) + jump_timer.connect("timeout", self, "jump") + target_lost_timer = Timer.new() + target_lost_timer.set_one_shot(true) + target_lost_timer.connect("timeout", self, "loose_target") + add_child(jump_timer) + add_child(target_lost_timer) + # TODO this is so bad ;_; + if get_parent().name.begins_with("Bound"): + is_bound = true + else: + level_state.free_a_frog(frog_number) + level_state.register_frog(frog_number, !is_bound) + # TODO Stays harmless for now + #if(is_bound): add_to_group("harmful") -func bind_to_anchor(anchor_node: Node2D, radius: float ) -> void: - anchor = anchor_node - movement_radius = radius * block_size - is_bound = true - # TODO multiple free frogs - $Digit.visible = true - $Digit.frame = frog_number - $LeashAnchor.visible = is_bound +func bind_to_anchor(anchor_node: Node2D, radius: float) -> void: + anchor = anchor_node + movement_radius = radius * block_size + is_bound = true + # TODO multiple free frogs + $Digit.visible = true + $Digit.frame = frog_number + $LeashAnchor.visible = is_bound func execute_movement(delta: float) -> void: - # Navigation2DServer.map_get_path() - current_delta = delta - # TODO what when the game runs really long and the float runs out of space? - # Achievment maybe lul - detect_timer += delta - velocity.y += _gravity * delta - if(is_bound): - var next_position = global_position + velocity * current_delta - var current_distance = global_position.distance_to(anchor.global_position) - var new_distance = next_position.distance_to(anchor.global_position) - # TODO Fix this in respects to x and y distances and movement dampening - # Maybe use mathemathematics or something idfc - if(current_distance >= movement_radius && new_distance > current_distance): - velocity.x = velocity.x * 0.8 - velocity.y = velocity.y * 0.8 - was_restricted = true - velocity = move_and_slide(velocity, FLOOR_NORMAL, false, 4, 0.785398, false) + # Navigation2DServer.map_get_path() + current_delta = delta + # TODO what when the game runs really long and the float runs out of space? + # Achievment maybe lul + detect_timer += delta + velocity.y += _gravity * delta + if is_bound: + var next_position = global_position + velocity * current_delta + var current_distance = global_position.distance_to(anchor.global_position) + var new_distance = next_position.distance_to(anchor.global_position) + # TODO Fix this in respects to x and y distances and movement dampening + # Maybe use mathemathematics or something idfc + if current_distance >= movement_radius && new_distance > current_distance: + velocity.x = velocity.x * 0.8 + velocity.y = velocity.y * 0.8 + was_restricted = true + velocity = move_and_slide(velocity, FLOOR_NORMAL, false, 4, 0.785398, false) - if($"%GroundDetector".get_overlapping_bodies().size() > 0): - velocity.y -= 10 * (delta/0.0083) - var min_x_slide_velocity = 50 * (delta/0.0083) - velocity.x = sign(velocity.x) * max(min_x_slide_velocity, velocity.x * 0.99) - return - elif(is_on_floor()): - velocity = Vector2(0,0) - - # Reverse direction when hitting limit + if $"%GroundDetector".get_overlapping_bodies().size() > 0: + velocity.y -= 10 * (delta / 0.0083) + var min_x_slide_velocity = 50 * (delta / 0.0083) + velocity.x = sign(velocity.x) * max(min_x_slide_velocity, velocity.x * 0.99) + return + elif is_on_floor(): + velocity = Vector2(0, 0) + + # Reverse direction when hitting limit func die() -> void: - queue_free() + queue_free() -func _on_EnemySkin_area_entered(area:Area2D) -> void: - if area.is_in_group("harmful") && !area.is_in_group("frogfood"): - get_node("EnemyBody").disabled = true - die() +func _on_EnemySkin_area_entered(area: Area2D) -> void: + if area.is_in_group("harmful") && !area.is_in_group("frogfood"): + get_node("EnemyBody").disabled = true + die() func _on_EnemySkin_body_entered(body: Node) -> void: - if body.is_in_group("frogfood"): - loose_target() - body.die() - + if body.is_in_group("frogfood"): + loose_target() + body.die() + func _on_StompDetector_body_entered(body: Node) -> void: - if body.is_in_group("player"): - attached_player = body - $FeelerRayCast.collision_mask -= 1 - if !body.is_in_group("player") || is_hurt: - return - var incoming_vel_vector: Vector2 = body.velocity.normalized() - # TODO This is not the right angle somehow + if body.is_in_group("player"): + attached_player = body + $FeelerRayCast.collision_mask -= 1 + if !body.is_in_group("player") || is_hurt: + return + var incoming_vel_vector: Vector2 = body.velocity.normalized() + # TODO This is not the right angle somehow # print(rad2deg(abs(incoming_vel_vector.angle_to(Vector2.DOWN.rotated(rotation))))) # if abs(incoming_vel_vector.angle_to(\Vector2.DOWN.rotated(rotation))) > deg2rad(60): # print("too shallow entry") # return - signal_manager.emit_signal("got_stomped") - remove_from_group("harmful") - # TODO Weakpoint group is not needed per se - $StompDetector.remove_from_group("weakpoint") - get_node("EnemyBody").disabled = true - is_hurt = true - $FrogSprite.material = invincible_shader - $HurtTimer.start() + signal_manager.emit_signal("got_stomped") + remove_from_group("harmful") + # TODO Weakpoint group is not needed per se + $StompDetector.remove_from_group("weakpoint") + get_node("EnemyBody").disabled = true + is_hurt = true + $FrogSprite.material = invincible_shader + $HurtTimer.start() + func _on_StompDetector_body_exited(body: Node) -> void: - if attached_player == body: - $FeelerRayCast.collision_mask += 1 - attached_player = null + if attached_player == body: + $FeelerRayCast.collision_mask += 1 + attached_player = null func searching() -> Vector2: - if(detect_timer > 0.333): - search_next_target() - detect_timer = 0.0 - if(is_on_floor()): - if(jump_timer.is_stopped()): - jump_timer.start(rng.randfn(jump_time_search, jump_time_standard_deviation)) - if(in_air): - in_air = false - else: - if(!in_air): - start_x = global_position.x - reversing_possible_searching = true - jump_timer.stop() - in_air = true - return velocity + if detect_timer > 0.333: + search_next_target() + detect_timer = 0.0 + if is_on_floor(): + if jump_timer.is_stopped(): + jump_timer.start(rng.randfn(jump_time_search, jump_time_standard_deviation)) + if in_air: + in_air = false + else: + if !in_air: + start_x = global_position.x + reversing_possible_searching = true + jump_timer.stop() + in_air = true + return velocity func search_next_target(): - if(target != null && !weakref(target).get_ref()): - return - detect_food() - if(food_target == null && is_bound): - detect_player() + if target != null && !weakref(target).get_ref(): + return + detect_food() + if food_target == null && is_bound: + detect_player() func hunting() -> Vector2: - var was_target_freed = !weakref(target).get_ref() - if(detect_timer > 0.333): - search_next_target() - detect_timer = 0.0 - #TODO Dependent on block size - elif(is_on_floor() && food_target != null && !was_target_freed && - global_position.distance_to(food_target.global_position) <= attack_jump_range * block_size): - - var collider = check_feeler(food_target.global_position - global_position) - if(!was_restricted && collider != null && collider.is_in_group("frogfood")): - jump_timer.stop() - return attack_jump(food_target.global_position) - - if(is_on_floor()): - if(jump_timer.is_stopped()): - jump_timer.start(rng.randfn(jump_time_hunt, jump_time_standard_deviation)) - if(in_air): - in_air = false - - else: - if(!in_air): - start_x = global_position.x - reversing_possible_searching = true - jump_timer.stop() - in_air = true + var was_target_freed = !weakref(target).get_ref() + if detect_timer > 0.333: + search_next_target() + detect_timer = 0.0 + #TODO Dependent on block size + elif ( + is_on_floor() + && food_target != null + && !was_target_freed + && ( + global_position.distance_to(food_target.global_position) + <= attack_jump_range * block_size + ) + ): + var collider = check_feeler(food_target.global_position - global_position) + if !was_restricted && collider != null && collider.is_in_group("frogfood"): + jump_timer.stop() + return attack_jump(food_target.global_position) - if(barely_held_back_counter > 1): - barely_held_back_counter = 0 - loose_target() + if is_on_floor(): + if jump_timer.is_stopped(): + jump_timer.start(rng.randfn(jump_time_hunt, jump_time_standard_deviation)) + if in_air: + in_air = false - if(target != null && !was_target_freed && - sign((target.global_position - global_position).x) != get_facing_direction()): - # TODO Waits in front of too small tunnels if it sees the target on the other side - # It's ok behavior for now - reverse_facing_direction() + else: + if !in_air: + start_x = global_position.x + reversing_possible_searching = true + jump_timer.stop() + in_air = true - return velocity + if barely_held_back_counter > 1: + barely_held_back_counter = 0 + loose_target() + + if ( + target != null + && !was_target_freed + && sign((target.global_position - global_position).x) != get_facing_direction() + ): + # TODO Waits in front of too small tunnels if it sees the target on the other side + # It's ok behavior for now + reverse_facing_direction() + + return velocity func detect_food() -> void: - # TODO What if food spawns in - food_sources = get_tree().get_nodes_in_group("frogfood") - if(food_sources.empty()): - return - var i = 0 - var min_dist_f_index = 0 - var min_dist = (food_sources[0].global_position - global_position).length() - var food_node = null - for f in food_sources: - var new_dist = (food_sources[i].global_position - global_position).length() - min_dist = new_dist if new_dist < min_dist else min_dist - min_dist_f_index = i if new_dist < min_dist else min_dist_f_index - i += 1 - food_node = food_sources[min_dist_f_index] - #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 - vision_raycast.cast_to = (food_node.global_position - global_position).normalized() * block_size * vision_distance - var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to) - vision_raycast.force_raycast_update() - var collider = vision_raycast.get_collider() - if(abs(ray_angle_to_facing) < PI/3 && collider != null && collider.is_in_group("frogfood")): - target_lost_timer.stop() - target = collider - food_target = collider - elif(target != null && target_lost_timer.is_stopped()): - target_lost_timer.start(loose_target_seconds) + # TODO What if food spawns in + food_sources = get_tree().get_nodes_in_group("frogfood") + if food_sources.empty(): + return + + #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 + var i = 0 + var min_dist_f_index = 0 + var min_dist = (food_sources[0].global_position - global_position).length() + var food_node = null + for f in food_sources: + var new_dist = (food_sources[i].global_position - global_position).length() + min_dist = new_dist if new_dist < min_dist else min_dist + min_dist_f_index = i if new_dist < min_dist else min_dist_f_index + i += 1 + + #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 + food_node = food_sources[min_dist_f_index] + #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 + vision_raycast.cast_to = ( + (food_node.global_position - global_position).normalized() + * block_size + * vision_distance + ) + var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to) + vision_raycast.force_raycast_update() + var collider = vision_raycast.get_collider() + if abs(ray_angle_to_facing) < PI / 3 && collider != null && collider.is_in_group("frogfood"): + target_lost_timer.stop() + target = collider + food_target = collider + elif target != null && target_lost_timer.is_stopped(): + target_lost_timer.start(loose_target_seconds) func detect_player() -> void: - var player - if(players.empty()): - # print("no player found") - return - player = players[0] - #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 - vision_raycast.cast_to = (player.global_position - global_position - Vector2(0, 9)).normalized() * block_size * vision_distance - var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to) - vision_raycast.force_raycast_update() - var collider = vision_raycast.get_collider() - if(abs(ray_angle_to_facing) < PI/4 && collider != null && collider.is_in_group("player")): - target_lost_timer.stop() - target = collider - elif(target != null && target_lost_timer.is_stopped()): - target_lost_timer.start(loose_target_seconds) + var player + if players.empty(): + # print("no player found") + return + + #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 + player = players[0] + #TODO Depends on height of blobby sprite since blobbys bottom and not his middle is on y=0 + vision_raycast.cast_to = ( + (player.global_position - global_position - Vector2(0, 9)).normalized() + * block_size + * vision_distance + ) + var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to) + vision_raycast.force_raycast_update() + var collider = vision_raycast.get_collider() + if abs(ray_angle_to_facing) < PI / 4 && collider != null && collider.is_in_group("player"): + target_lost_timer.stop() + target = collider + elif target != null && target_lost_timer.is_stopped(): + target_lost_timer.start(loose_target_seconds) func sleeping() -> Vector2: - jump_timer.stop() - # detect_player() - return velocity + jump_timer.stop() + # detect_player() + return velocity func loose_target() -> void: - # print("frog target lost") - target = null - food_target = null + # print("frog target lost") + target = null + food_target = null func jump(): - # print("jump calculation initiated") - # Can only reverse once per jump calculation - has_reversed = false - var zero_vector = Vector2(0,0) - var v: Vector2 = velocity_for_jump_distance(default_jump_distance, deg2rad(default_jump_angle)) - v = correct_jump_direction(v) + # print("jump calculation initiated") + # Can only reverse once per jump calculation + has_reversed = false + var zero_vector = Vector2(0, 0) + var v: Vector2 = velocity_for_jump_distance(default_jump_distance, deg2rad(default_jump_angle)) + v = correct_jump_direction(v) + + if is_bound: + var next_position = global_position + v * current_delta + var current_distance = global_position.distance_to(anchor.global_position) + var new_distance = next_position.distance_to(anchor.global_position) + # print(current_distance) + # print(new_distance) + # Would go out of distance + if ( + (new_distance >= movement_radius && new_distance > current_distance) + || (new_distance > current_distance && was_restricted) + ): + if state_machine.state == "hunting": + barely_held_back_counter += 1 + if ( + can_reverse_facing_direction() + && (barely_held_back_counter == 0 || barely_held_back_counter > 1) + ): + reverse_facing_direction() + was_restricted = false + + if $Right_Wallcast.is_colliding() && $Left_Wallcast.is_colliding(): + # TODO No idea what it might do in these situations + print("help this is a really tight space :(") + elif get_facing_direction() < 0 && $Left_Wallcast.is_colliding(): + v = zero_vector + elif get_facing_direction() > 0 && $Right_Wallcast.is_colliding(): + v = zero_vector + + v = correct_jump_direction(v) + if v != zero_vector: + v = consider_jump_headspace(v) + if v != zero_vector: + v = consider_jump_landing_space(v) + if v == zero_vector: + # TODO fix that you could call jump from jumping on top + # and let it fail if the top is dangerous for jump height or not safe + v = consider_jumping_on_top() + if v == zero_vector && can_reverse_facing_direction(): + reverse_facing_direction() - if(is_bound): - var next_position = global_position + v * current_delta - var current_distance = global_position.distance_to(anchor.global_position) - var new_distance = next_position.distance_to(anchor.global_position) - # print(current_distance) - # print(new_distance) - # Would go out of distance - if((new_distance >= movement_radius && new_distance > current_distance) || (new_distance > current_distance && was_restricted)): - if(state_machine.state == "hunting"): - barely_held_back_counter += 1 - if can_reverse_facing_direction() && (barely_held_back_counter == 0 || barely_held_back_counter > 1): - reverse_facing_direction() - was_restricted = false - - if ($Right_Wallcast.is_colliding() && $Left_Wallcast.is_colliding()): - # TODO No idea what it might do in these situations - print("help this is a really tight space :(") - elif (get_facing_direction() < 0 && $Left_Wallcast.is_colliding()): - v = zero_vector - elif (get_facing_direction() > 0 && $Right_Wallcast.is_colliding()): - v = zero_vector - - - v = correct_jump_direction(v) - if(v != zero_vector): - v = consider_jump_headspace(v) - if(v != zero_vector): - v = consider_jump_landing_space(v) - if(v == zero_vector): - # TODO fix that you could call jump from jumping on top - # and let it fail if the top is dangerous for jump height or not safe - v = consider_jumping_on_top() - if(v == zero_vector && can_reverse_facing_direction()): - reverse_facing_direction() - # if attached_player != null && v != zero_vector: # move_with_player(v) - - velocity = v + + velocity = v + #func move_with_player(v: Vector2): # print(v) # attached_player.move_and_slide(v * 10) + func correct_jump_direction(v: Vector2) -> Vector2: - if sign(v.x) != get_facing_direction(): - v.x *= -1 - return v + if sign(v.x) != get_facing_direction(): + v.x *= -1 + return v # Cast a ray to the highest point of the jump @@ -345,215 +373,245 @@ func correct_jump_direction(v: Vector2) -> Vector2: # Calculate safe jump height and then a safe jump velocity # Returns 0,0 if theres no headspace func consider_jump_headspace(v: Vector2, recursive_check_count = 0, max_checks = 2) -> Vector2: - if recursive_check_count >= max_checks: - print("Frog has no safe headspace") - return Vector2(0,0) - var height = calculate_jump_height(v) - var distance = calculate_jump_distance(v) - var angle = (v * get_facing_direction()).angle() - # Half distance is an estimate of the jumps apex() - #TODO Consider sprite size for height - var height_collider = check_feeler(Vector2(get_facing_direction()*(distance/2), -(height+23))) - if(height_collider != null): - var collision_point = feeler_raycast.get_collision_point() - var target_height = collision_point.y - (feeler_raycast.global_position.y - 23) - # print(feeler_raycast.global_position) - var new_angle = angle * (0.75 if target_height > -26 else 0.95) - var new_distance = abs(distance) * (0.66 if target_height < -26 else 0.75) - v = velocity_for_jump_distance(new_distance, abs(new_angle)) - v = correct_jump_direction(v) - height = calculate_jump_height(v) * -1 - distance = calculate_jump_distance(v) * get_facing_direction() - if(height < target_height && can_reverse_facing_direction()): - v = consider_jump_headspace(v, recursive_check_count + 1) - return v + if recursive_check_count >= max_checks: + print("Frog has no safe headspace") + return Vector2(0, 0) + var height = calculate_jump_height(v) + var distance = calculate_jump_distance(v) + var angle = (v * get_facing_direction()).angle() + # Half distance is an estimate of the jumps apex() + #TODO Consider sprite size for height + var height_collider = check_feeler( + Vector2(get_facing_direction() * (distance / 2), -(height + 23)) + ) + if height_collider != null: + var collision_point = feeler_raycast.get_collision_point() + var target_height = collision_point.y - (feeler_raycast.global_position.y - 23) + # print(feeler_raycast.global_position) + var new_angle = angle * (0.75 if target_height > -26 else 0.95) + var new_distance = abs(distance) * (0.66 if target_height < -26 else 0.75) + v = velocity_for_jump_distance(new_distance, abs(new_angle)) + v = correct_jump_direction(v) + height = calculate_jump_height(v) * -1 + distance = calculate_jump_distance(v) * get_facing_direction() + if height < target_height && can_reverse_facing_direction(): + v = consider_jump_headspace(v, recursive_check_count + 1) + return v # Check the block in jump distance for danger or height # If danger check neighboring blocks: if still danger, then jump closer (or jump over) # If height move to distance which allows 1 block high jump func consider_jump_landing_space(v: Vector2) -> Vector2: - var jump_distance = calculate_jump_distance(v) - var jump_height = calculate_jump_height(v) - var collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2)) - # TODO Unpacked loop, make function or something? - # Shortens the jump in steps to make it more safe - if(!is_jump_path_safe(v, global_position) || collider != null): - jump_distance = calculate_jump_distance(v) - block_size/1.5 - v = change_jump_distance(jump_distance, v) - jump_height = calculate_jump_height(v) - v = correct_jump_direction(v) - collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2)) - if(!is_jump_path_safe(v, global_position) || collider != null): - jump_distance = calculate_jump_distance(v) - block_size/2.0 - v = change_jump_distance(jump_distance, v) - jump_height = calculate_jump_height(v) - v = correct_jump_direction(v) - collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2)) - if((!is_jump_path_safe(v, global_position) || collider != null) && can_reverse_facing_direction()): - # Can be printed when frog would jump into a wall too - print("at wall or no safe landing spot") - return Vector2(0,0) - return v + var jump_distance = calculate_jump_distance(v) + var jump_height = calculate_jump_height(v) + var collider = check_feeler(Vector2(jump_distance * get_facing_direction(), -jump_height / 2)) + # TODO Unpacked loop, make function or something? + # Shortens the jump in steps to make it more safe + if !is_jump_path_safe(v, global_position) || collider != null: + jump_distance = calculate_jump_distance(v) - block_size / 1.5 + v = change_jump_distance(jump_distance, v) + jump_height = calculate_jump_height(v) + v = correct_jump_direction(v) + collider = check_feeler(Vector2(jump_distance * get_facing_direction(), -jump_height / 2)) + if !is_jump_path_safe(v, global_position) || collider != null: + jump_distance = calculate_jump_distance(v) - block_size / 2.0 + v = change_jump_distance(jump_distance, v) + jump_height = calculate_jump_height(v) + v = correct_jump_direction(v) + collider = check_feeler(Vector2(jump_distance * get_facing_direction(), -jump_height / 2)) + if ( + (!is_jump_path_safe(v, global_position) || collider != null) + && can_reverse_facing_direction() + ): + # Can be printed when frog would jump into a wall too + print("at wall or no safe landing spot") + return Vector2(0, 0) + return v func consider_jumping_on_top() -> Vector2: - var collider = check_feeler(Vector2(42 * get_facing_direction(),0)) - # 0 just for tile coordinate calculation - var facing = 0 if get_facing_direction() >= 0 else - 1 - if (collider == null): - return Vector2(0,0) - var local_position = tilemap.to_local(feeler_raycast.get_collision_point()) - var map_position = tilemap.world_to_map(local_position) - var tile_position = Vector2(map_position.x + facing, map_position.y - 1) - # TODO Here the climb height of frog is limited to one constantly - var cell_id = tilemap.get_cell(tile_position.x, tile_position.y - 1) - if (cell_id != -1 && - #TODO 0 is the navigation tile, but thats subject to change! - cell_id != 7): - return Vector2(0,0) - var tile_upper_left_corner = tilemap.to_global(tilemap.map_to_world(tile_position)) - var tile_upper_right_corner = Vector2(tile_upper_left_corner.x + tilemap.cell_size.x, tile_upper_left_corner.y) - - var jump_angle = 0 - if(facing < 0): - var frog_bottom_left_corner = Vector2($EnemyBody.global_position.x - $EnemyBody.shape.extents.x, - $EnemyBody.global_position.y + $EnemyBody.shape.extents.y) - jump_angle = frog_bottom_left_corner.angle_to_point(tile_upper_right_corner) - else: - var frog_bottom_right_corner = Vector2($EnemyBody.global_position.x + $EnemyBody.shape.extents.x, - $EnemyBody.global_position.y + $EnemyBody.shape.extents.y) - jump_angle = frog_bottom_right_corner.angle_to_point(tile_upper_left_corner) - PI - - if(abs(rad2deg(jump_angle)) < 78): - return correct_jump_direction(velocity_for_jump_distance(default_jump_distance/2, abs(deg2rad(80)))) - else: - var v = velocity_for_jump_distance(block_size/1.5, abs(deg2rad(45))) - return Vector2(v.x * -1 * get_facing_direction(), v.y) + var collider = check_feeler(Vector2(42 * get_facing_direction(), 0)) + # 0 just for tile coordinate calculation + var facing = 0 if get_facing_direction() >= 0 else -1 + if collider == null: + return Vector2(0, 0) + var local_position = tilemap.to_local(feeler_raycast.get_collision_point()) + var map_position = tilemap.world_to_map(local_position) + var tile_position = Vector2(map_position.x + facing, map_position.y - 1) + # TODO Here the climb height of frog is limited to one constantly + var cell_id = tilemap.get_cell(tile_position.x, tile_position.y - 1) + if ( + cell_id != -1 + #TODO 0 is the navigation tile, but thats subject to change! + && cell_id != 7 + ): + return Vector2(0, 0) + var tile_upper_left_corner = tilemap.to_global(tilemap.map_to_world(tile_position)) + var tile_upper_right_corner = Vector2( + tile_upper_left_corner.x + tilemap.cell_size.x, tile_upper_left_corner.y + ) + + var jump_angle = 0 + if facing < 0: + var frog_bottom_left_corner = Vector2( + $EnemyBody.global_position.x - $EnemyBody.shape.extents.x, + $EnemyBody.global_position.y + $EnemyBody.shape.extents.y + ) + jump_angle = frog_bottom_left_corner.angle_to_point(tile_upper_right_corner) + else: + var frog_bottom_right_corner = Vector2( + $EnemyBody.global_position.x + $EnemyBody.shape.extents.x, + $EnemyBody.global_position.y + $EnemyBody.shape.extents.y + ) + jump_angle = frog_bottom_right_corner.angle_to_point(tile_upper_left_corner) - PI + + if abs(rad2deg(jump_angle)) < 78: + return correct_jump_direction( + velocity_for_jump_distance(default_jump_distance / 2, abs(deg2rad(80))) + ) + else: + var v = velocity_for_jump_distance(block_size / 1.5, abs(deg2rad(45))) + return Vector2(v.x * -1 * get_facing_direction(), v.y) # Tries to shorten the jump, so that it lands in a tiles center func jump_to_tile_center(v: Vector2) -> Vector2: - var distance = stepify(calculate_jump_distance(v), 0.01) - if !is_equal_approx(fmod(abs(global_position.x + distance * get_facing_direction()), block_size), (block_size/2.0)): - # print(distance) - # print(global_position.x + distance) - # print(fmod((global_position.x + distance), block_size)) - var new_distance = distance - if(get_facing_direction() < 0): - new_distance = fmod((global_position.x + distance), block_size) - (block_size/2.0) + distance - else: - new_distance = distance + block_size/2.0 - fmod((global_position.x + distance), block_size) - # print("centering distance") - # print(new_distance) - v = change_jump_distance(abs(new_distance), v) - v = correct_jump_direction(v) - return v + var distance = stepify(calculate_jump_distance(v), 0.01) + if !is_equal_approx( + fmod(abs(global_position.x + distance * get_facing_direction()), block_size), + block_size / 2.0 + ): + # print(distance) + # print(global_position.x + distance) + # print(fmod((global_position.x + distance), block_size)) + var new_distance = distance + if get_facing_direction() < 0: + new_distance = ( + fmod(global_position.x + distance, block_size) + - (block_size / 2.0) + + distance + ) + else: + new_distance = ( + distance + + block_size / 2.0 + - fmod(global_position.x + distance, block_size) + ) + # print("centering distance") + # print(new_distance) + v = change_jump_distance(abs(new_distance), v) + v = correct_jump_direction(v) + return v # TODO Depends on Frog Shape and Tile Shape func is_jump_path_safe(v: Vector2, pos: Vector2) -> bool: - var v0 = v.length() - var angle = v.angle() - var jump_distance = calculate_jump_distance(v) - var harmful_nodes = get_tree().get_nodes_in_group("harmful") - harmful_nodes.append_array(get_tree().get_nodes_in_group("pit")) - for node in harmful_nodes: - var node_pos = node.global_position - # TODO Ignores spikes more than 4 blocks below and 3 jumps away - # Also when its too near to one - if (abs(node_pos.x - pos.x) > abs(jump_distance) * 3 - ||abs(node_pos.y - pos.y) > block_size * 4 - || abs(node_pos.x - pos.x) < 1): - continue - var node_y = node_pos.y - block_size/2.0 - var initial_throw_height = node_y - (global_position.y + 9) - var term1 = (pow(v0, 2) * sin(2 * angle)) / (2 * _gravity) - var term2 = ((v0 * cos(angle))/_gravity) * sqrt(pow(v0, 2) * pow(sin(angle), 2) + 2 * _gravity * initial_throw_height) - var distance = abs(term1) + abs(term2) - # print("distance to next spike") - # print(pos.x + sign(v.x) * distance - node_pos.x) - var safe_distance = block_size/2.0 - if (sign(initial_throw_height) < 0): - safe_distance = block_size - if(abs(pos.x + sign(v.x) * distance - node_pos.x) < safe_distance): - return false - return true + var v0 = v.length() + var angle = v.angle() + var jump_distance = calculate_jump_distance(v) + var harmful_nodes = get_tree().get_nodes_in_group("harmful") + harmful_nodes.append_array(get_tree().get_nodes_in_group("pit")) + for node in harmful_nodes: + var node_pos = node.global_position + # TODO Ignores spikes more than 4 blocks below and 3 jumps away + # Also when its too near to one + if ( + abs(node_pos.x - pos.x) > abs(jump_distance) * 3 + || abs(node_pos.y - pos.y) > block_size * 4 + || abs(node_pos.x - pos.x) < 1 + ): + continue + var node_y = node_pos.y - block_size / 2.0 + var initial_throw_height = node_y - (global_position.y + 9) + var term1 = (pow(v0, 2) * sin(2 * angle)) / (2 * _gravity) + var term2 = ( + ((v0 * cos(angle)) / _gravity) + * sqrt(pow(v0, 2) * pow(sin(angle), 2) + 2 * _gravity * initial_throw_height) + ) + var distance = abs(term1) + abs(term2) + # print("distance to next spike") + # print(pos.x + sign(v.x) * distance - node_pos.x) + var safe_distance = block_size / 2.0 + if sign(initial_throw_height) < 0: + safe_distance = block_size + if abs(pos.x + sign(v.x) * distance - node_pos.x) < safe_distance: + return false + return true func calculate_jump_height(v: Vector2) -> float: - return abs((pow(v.length(), 2) * pow(sin(v.angle()), 2))/(2*_gravity)) + return abs((pow(v.length(), 2) * pow(sin(v.angle()), 2)) / (2 * _gravity)) # Only works for jumps on straight ground func calculate_jump_distance(v: Vector2) -> float: - return abs((pow(v.length(), 2) * sin(-1 * 2 * v.angle()))/(_gravity)) + return abs((pow(v.length(), 2) * sin(-1 * 2 * v.angle())) / (_gravity)) func jump_height_to_velocity(target_height: float, v: Vector2) -> Vector2: - var initial_height = calculate_jump_height(v) - return v.normalized() * sqrt(pow(v.length(),2)/(initial_height/target_height)) + var initial_height = calculate_jump_height(v) + return v.normalized() * sqrt(pow(v.length(), 2) / (initial_height / target_height)) # Changes a Vector for a jump to the targeted distance, keeping the angle func change_jump_distance(target_distance: float, v: Vector2) -> Vector2: - var initial_distance = calculate_jump_distance(v) - return v.normalized() * sqrt(pow(v.length(),2)/(initial_distance/target_distance)) + var initial_distance = calculate_jump_distance(v) + return v.normalized() * sqrt(pow(v.length(), 2) / (initial_distance / target_distance)) # Takes an angle and a distance to calculate a jump launching at that angle and covering the distance -func velocity_for_jump_distance(distance: float = default_jump_distance*block_size, angle: float = deg2rad(default_jump_angle)) -> Vector2: - var abs_velocity = sqrt((distance * _gravity)/sin(2*angle)) - return Vector2(abs_velocity,0).rotated(-1*angle) +func velocity_for_jump_distance( + distance: float = default_jump_distance * block_size, angle: float = deg2rad(default_jump_angle) +) -> Vector2: + var abs_velocity = sqrt((distance * _gravity) / sin(2 * angle)) + return Vector2(abs_velocity, 0).rotated(-1 * angle) func can_reverse_facing_direction() -> bool: - if(is_on_floor() && !has_reversed): - return true - return false + if is_on_floor() && !has_reversed: + return true + return false # Returns a jump velocity that has the target_position in it's path func attack_jump(target_position: Vector2) -> Vector2: - var target_vector = target_position - global_position - target_vector = Vector2(abs(target_vector.x), target_vector.y) - var jump_angle = target_vector.angle() - var v = Vector2() - # TODO Tunable parameters - if jump_angle < deg2rad(-30): - v = velocity_for_jump_distance(target_vector.x, deg2rad(default_jump_angle)) - v = jump_height_to_velocity(abs(target_vector.y), v) - else: - v = velocity_for_jump_distance(target_vector.x * 1.5,deg2rad(45)) - v = correct_jump_direction(v) - return v + var target_vector = target_position - global_position + target_vector = Vector2(abs(target_vector.x), target_vector.y) + var jump_angle = target_vector.angle() + var v = Vector2() + # TODO Tunable parameters + if jump_angle < deg2rad(-30): + v = velocity_for_jump_distance(target_vector.x, deg2rad(default_jump_angle)) + v = jump_height_to_velocity(abs(target_vector.y), v) + else: + v = velocity_for_jump_distance(target_vector.x * 1.5, deg2rad(45)) + v = correct_jump_direction(v) + return v # Checks the feeler ray for collisions and returns collider or null -func check_feeler(v: Vector2, _offset = Vector2(0,0)) -> Object: - var prev_position = feeler_raycast.position - feeler_raycast.position += _offset - feeler_raycast.cast_to = v - feeler_raycast.force_raycast_update() - var collider = feeler_raycast.get_collider() - feeler_raycast.position = prev_position - return collider +func check_feeler(v: Vector2, _offset = Vector2(0, 0)) -> Object: + var prev_position = feeler_raycast.position + feeler_raycast.position += _offset + feeler_raycast.cast_to = v + feeler_raycast.force_raycast_update() + var collider = feeler_raycast.get_collider() + feeler_raycast.position = prev_position + return collider func reverse_facing_direction() -> void: - has_reversed = true - # print("reversing direction") - orientation.cast_to.x *= -1 + has_reversed = true + # print("reversing direction") + orientation.cast_to.x *= -1 func get_facing_direction() -> float: - return orientation.cast_to.x + return orientation.cast_to.x func _on_HurtTimer_timeout() -> void: - is_hurt = false - #if(is_bound): add_to_group("harmful") - $FrogSprite.material = null - - - + is_hurt = false + #if(is_bound): add_to_group("harmful") + $FrogSprite.material = null diff --git a/src/Levels/1 Tutorial Level.tscn b/src/Levels/1 Tutorial Level.tscn index e908194..8900dbc 100644 --- a/src/Levels/1 Tutorial Level.tscn +++ b/src/Levels/1 Tutorial Level.tscn @@ -212,6 +212,9 @@ unique_name_in_owner = true position = Vector2( -70, 1 ) scale = Vector2( 0.878906, 0.936025 ) +[node name="BlobbySprite" parent="Blobby" index="5"] +frame = 8 + [node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"] parameters/playback = SubResource( 14 ) parameters/jumpStretching/blend_position = 1 diff --git a/src/Levels/2 Tutorial Level.tscn b/src/Levels/2 Tutorial Level.tscn index e04cfe8..79f169e 100644 --- a/src/Levels/2 Tutorial Level.tscn +++ b/src/Levels/2 Tutorial Level.tscn @@ -1040,7 +1040,7 @@ position = Vector2( -156, -51 ) scale = Vector2( 0.878906, 0.936025 ) [node name="BlobbySprite" parent="Blobby" index="5"] -frame = 6 +frame = 5 [node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"] parameters/playback = SubResource( 6 ) diff --git a/src/Levels/Actual Level 1.tscn b/src/Levels/Actual Level 1.tscn index 5b6311a..ca68379 100644 --- a/src/Levels/Actual Level 1.tscn +++ b/src/Levels/Actual Level 1.tscn @@ -44,17 +44,14 @@ wait_time = 20.0 [node name="BlobbyCam" parent="." instance=ExtResource( 9 )] unique_name_in_owner = true -[node name="AnimatedSprite" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="4"] -frame = 13 - -[node name="AnimatedSprite2" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="5"] -frame = 3 - [node name="Blobby" parent="." instance=ExtResource( 15 )] unique_name_in_owner = true position = Vector2( 251, -24 ) scale = Vector2( 0.878906, 0.936025 ) +[node name="BlobbySprite" parent="Blobby" index="5"] +frame = 6 + [node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"] parameters/playback = SubResource( 1 ) diff --git a/src/Levels/Templates/LevelTemplate.gd b/src/Levels/Templates/LevelTemplate.gd index 31c7513..e88746f 100644 --- a/src/Levels/Templates/LevelTemplate.gd +++ b/src/Levels/Templates/LevelTemplate.gd @@ -5,8 +5,8 @@ onready var signal_manager := $"%SignalManager" onready var level_state := $"%LevelState" func _ready() -> void: - # should spawn the tutorial thingies which are still remembered in the progress dictionary - signal_manager.emit_signal("level_loaded") - get_tree().paused = false - - + # should spawn the tutorial thingies which are still remembered in the progress dictionary + signal_manager.emit_signal("level_loaded") + get_tree().paused = false + + diff --git a/src/Sounds/default_bus_layout.tres b/src/Sounds/default_bus_layout.tres index 647ba66..1028d26 100644 --- a/src/Sounds/default_bus_layout.tres +++ b/src/Sounds/default_bus_layout.tres @@ -41,12 +41,12 @@ resource_name = "LowPassFilter" cutoff_hz = 3000.0 [resource] -bus/0/volume_db = -6.0206 +bus/0/volume_db = -10.4576 bus/1/name = "Music" bus/1/solo = false bus/1/mute = false bus/1/bypass_fx = false -bus/1/volume_db = -20.0 +bus/1/volume_db = -6.0206 bus/1/send = "Master" bus/1/effect/0/effect = SubResource( 1 ) bus/1/effect/0/enabled = false @@ -68,7 +68,7 @@ bus/3/name = "UI" bus/3/solo = false bus/3/mute = false bus/3/bypass_fx = false -bus/3/volume_db = -4.43698 +bus/3/volume_db = -6.0206 bus/3/send = "Master" bus/3/effect/0/effect = SubResource( 6 ) bus/3/effect/0/enabled = true diff --git a/src/StateMachines/BlobbyStateMachine.gd b/src/StateMachines/BlobbyStateMachine.gd index b5c46b9..958979c 100644 --- a/src/StateMachines/BlobbyStateMachine.gd +++ b/src/StateMachines/BlobbyStateMachine.gd @@ -165,6 +165,9 @@ func _get_transition(_delta): ) anim_tree.set("parameters/wallsliding/blend_position", parent.wall_touch_direction) new_state = states.wallslide + # TODO Wallslide has to stick because the animation disconnects the wall raycasts + if self.state == states.wallslide && state_time < 0.2: + new_state = states.wallslide # Begins coyote time only if walking from ledge elif [states.walk, states.run].has(self.state) && !was_coyote_hanging: $CoyoteTimer.start() @@ -180,6 +183,7 @@ func _get_transition(_delta): if coyote_hanging: new_state = self.state + elif abs(parent.velocity.x) > 5: was_coyote_hanging = false if Input.is_action_pressed("boost_move"): @@ -263,7 +267,7 @@ func _exit_state(old_state, new_state): running_particles.emitting = false if old_state == "fall" && new_state != "wallslide": scene_audio.play_parallel_sound(landing_sound_1, 0.0, true, 1.0, 0.1) - elif old_state == "fall" && new_state == "wallslide": + elif new_state == "wallslide": scene_audio.play_parallel_sound(landing_sound_2, -15.0, true, 1.0, 0.1)