From 0c52a8d411a1d855e715dcfd615ce86c2c92066e Mon Sep 17 00:00:00 2001 From: catherinehoang44 Date: Mon, 27 Jul 2026 21:13:29 -0400 Subject: [PATCH] Add coins, enemy slime, and level reset. --- Assets/Enemy/Slime/slime_purple.png | Bin 0 -> 1030 bytes Assets/Enemy/Slime/slime_purple.png.import | 40 ++++++ Assets/Environment/BG/foreground.png | Bin 0 -> 2197 bytes Assets/Environment/BG/foreground.png.import | 40 ++++++ Assets/Environment/BG/midground.png | Bin 0 -> 1211 bytes Assets/Environment/BG/midground.png.import | 40 ++++++ Assets/Environment/BG/sky.png | Bin 0 -> 1062 bytes Assets/Environment/BG/sky.png.import | 40 ++++++ Assets/Environment/Veges/mushroom_32x64.png | Bin 0 -> 2049 bytes .../Veges/mushroom_32x64.png.import | 40 ++++++ Assets/Environment/Veges/veg_32x32.png | Bin 0 -> 675 bytes Assets/Environment/Veges/veg_32x32.png.import | 40 ++++++ Assets/Pickups/coin.png | Bin 0 -> 500 bytes Assets/Pickups/coin.png.import | 40 ++++++ Assets/Player/Dead/Player Death 64x64.png | Bin 0 -> 1584 bytes .../Player/Dead/Player Death 64x64.png.import | 40 ++++++ Assets/Player/Hurt/Player Hurt 48x48.png | Bin 0 -> 1448 bytes .../Player/Hurt/Player Hurt 48x48.png.import | 40 ++++++ Scenes/bullet.tscn | 2 + Scenes/coin.gd | 7 + Scenes/coin.gd.uid | 1 + Scenes/coin.tscn | 116 ++++++++++++++++ Scenes/game.tscn | 103 ++++++++++++-- Scenes/player.tscn | 130 ++++++++++++++++-- Scenes/slime.tscn | 74 ++++++++++ Scripts/bullet.gd | 2 +- Scripts/game.gd | 65 ++++++++- Scripts/player.gd | 25 +++- Scripts/rscs/characterstats.gd | 10 ++ Scripts/rscs/characterstats.gd.uid | 1 + Scripts/rscs/playerStats.tres | 10 ++ Scripts/rscs/slimeStats.tres | 11 ++ Scripts/scene_manager.gd | 49 ++++++- Scripts/slime.gd | 30 ++++ Scripts/slime.gd.uid | 1 + project.godot | 14 +- 36 files changed, 970 insertions(+), 41 deletions(-) create mode 100644 Assets/Enemy/Slime/slime_purple.png create mode 100644 Assets/Enemy/Slime/slime_purple.png.import create mode 100644 Assets/Environment/BG/foreground.png create mode 100644 Assets/Environment/BG/foreground.png.import create mode 100644 Assets/Environment/BG/midground.png create mode 100644 Assets/Environment/BG/midground.png.import create mode 100644 Assets/Environment/BG/sky.png create mode 100644 Assets/Environment/BG/sky.png.import create mode 100644 Assets/Environment/Veges/mushroom_32x64.png create mode 100644 Assets/Environment/Veges/mushroom_32x64.png.import create mode 100644 Assets/Environment/Veges/veg_32x32.png create mode 100644 Assets/Environment/Veges/veg_32x32.png.import create mode 100644 Assets/Pickups/coin.png create mode 100644 Assets/Pickups/coin.png.import create mode 100644 Assets/Player/Dead/Player Death 64x64.png create mode 100644 Assets/Player/Dead/Player Death 64x64.png.import create mode 100644 Assets/Player/Hurt/Player Hurt 48x48.png create mode 100644 Assets/Player/Hurt/Player Hurt 48x48.png.import create mode 100644 Scenes/coin.gd create mode 100644 Scenes/coin.gd.uid create mode 100644 Scenes/coin.tscn create mode 100644 Scenes/slime.tscn create mode 100644 Scripts/rscs/characterstats.gd create mode 100644 Scripts/rscs/characterstats.gd.uid create mode 100644 Scripts/rscs/playerStats.tres create mode 100644 Scripts/rscs/slimeStats.tres create mode 100644 Scripts/slime.gd create mode 100644 Scripts/slime.gd.uid diff --git a/Assets/Enemy/Slime/slime_purple.png b/Assets/Enemy/Slime/slime_purple.png new file mode 100644 index 0000000000000000000000000000000000000000..76f564e1d18d3f4b59c032ee8233ebf4665af431 GIT binary patch literal 1030 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@!3HEb(?2AGr~;43Vg?3oVGw3ym^DX&fq{94 zr;B4q#hkZu_UB)A5IH_yFgSBs)oT$}vmn=*zw9@ptqPdBe?d}nV{fk>$4CBvg?)Ed z_vO50>IiWPSm-r%m!<3^wh~P~_4RS~ zpI=Gub+-QhIeq%h`RaxX{5TJNc>dLzfkEQSwe9u4|AzdIT*^2{!A86~-QWe|7ymwB zC>Ti{|81}_`+UPPl@+TN=sEg&On58UrMgnvLQXF0_ys@bQ1@EdnLWo=s>t&5b6*sD zcFMcwU?tm(D_Xg)W-Wc$-E!h}Crjk()1K3gUwWA?xq;Wdw18cHo3k~Zx-$Fb`AU$*-@DD zmGPf?jG6V$dCTQj>{2>(Zt>F0fcfj}50vb4xa*Xko3|y%e%9UPUyOMTg5ncDvEEv- z-pIj{ckVgygWdnMA2Z(bzqjb#^{`seQ^pPQ$9_6a&90O2#S*<mC1;UMyZZkxfN& z@uKHWkGnrH91Z`H^EmwCk41a3FUGWg-!^5J_|wx1K5Uz!#D3x7Zw}ELVrNTt9P8IR z_1(WOXsY%rc>^6i*W&vj&+HC_UuW8s@vbNLPX_av( z9~A($9RP3!02&0rQvm!#24IE(fZJUFEaL7x-|LPnV2rW&-(yta8?m`j~D=YXNdt%Zc;PI!w^pKnWp9bO2yF%c3LA#=z=QKA9*LCW_ z(x5RTphpC#nj_8t%K!w?nHRto&UE++2_i)D7R)LC+d&2k<+WlD-Q1Dx`#7AlN5$tj zeb=?;&5bq2DDu~{^~VV!p5>4&@B;eyE?XGNaKJKr^#CMy3dke_y-=7dL__XnmvQp_am2EeUMBe?ChWnNd%eeE z#52xvIMaz??ln(}6I_h<$x@~A!~{``42EH$l#XS*U

6R%e`0H4BtYw&h7Gi-Sv) zO$LUvkE0lOURt5VRKzxd_{liKC}}gI99THRjA|iwb;-D2#Jw%xS0m5mL)69BqP#v9 zFE7_6@5(=o$E}9tTa6Xm81@4uQ5UkWEts|RZiij)C@LaflI`I-93n@}S{6)4xR^gO zW9wyH(6`&tsvEatM{gMv9XUGX;$c{MMif+CENhbdRqxcYQZiJD=UhevNd-CIU; zgDG3Vx|=NXgnD}Ff~y6XPA^tg?!~^Frd70G;y-(wGW*XcUn6V$^Q-!_oZO>>^~Gf? zGwJ)?3b~=6Z;USLY255%rV@=i|wtg2Z`PUabVJZgVh zsk5J*K1BxmQ@Z7}vNNJ|bH!zn$0MghbdH%?5-GY!Jb$Q8p$w*PfGH-}@c4}N%gKjN zc)FDDb?b{zy9sy8*Lv+qRcli1_;w1|%&a^x>aZ*;GyB$;U$yg^=cYv3yYesLg1oby zdq@*M5j!zfGT9%Raw>E>DwN)9@~@%xcN^GL@ZH0tYm*9Y zoSN;iCyn36V*cJFW3?+ge@nC=T~`Wr-tRFEva3kA(%4tDLGXr z@wVYKVZ>9;%2P*wABH>D33Jv8d$+DtT&xI>%w4vJ4My0w&`S-tkh`Y%5T;;>n^u!O zWP_UvE^%6{N}1GkhekBWy0%VWTpQ>b|7z8ISGP7#(1WU3U-N6I`?YVI?$oO{t0L8w zL(hU;Prf27eE-8IMvtaQQeYN+`T$^RRBaO$x;N>`N>1mEB75mTmB8(^-@G@Ww$CRN zD4QCYHgAfg(fpHunc$0k!7~__aUwav{JNvc__;yw`pnY^&MRk=Sq|Q!psUj^X^r{w z_hB6Eck{h+{-X|@Zd#=qux>~`x!yUNyt)zH##PZpF??lf*5)p93?q?0eL3f6RXb6yD1%a&Tb4TDJ!KfC zEo5e=j@gg6Z8O6e5py2;O-)uTE0~23Hosna3H^Cf66=Ak)ev4L_qji@@wonk1|o+g z(GRwKs7=Bu41L|%3J;UR;EuK1EuX*b8Z$ahS$}mx7x2Rg&)~|fNcx7%gtoyZ-P3KI zl+7?YuB*hNWd_!1S(UmCHcfdk+mi`dX;&=0Uc0L<(~6{{RU^s5k0S%A&IA$0NqryH zTBP)5%^wbC-Jt@K=)r6BtyW0+4;Wo-r%z$dqR8BkH9M;W^`27x@EQ@f3zUkiS&k`{ zoC%)xZMq&&KYM)n;{*=rCe0Vuy-2A{@&fVxgza10(T??!v| z8;bbL*A8QF9OB18Fi8@UINAJYpV|25#(3p!{GiGEhmc| literal 0 HcmV?d00001 diff --git a/Assets/Environment/BG/foreground.png.import b/Assets/Environment/BG/foreground.png.import new file mode 100644 index 0000000..9af6cf2 --- /dev/null +++ b/Assets/Environment/BG/foreground.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b73qg48wsqvai" +path="res://.godot/imported/foreground.png-d037a775d391d8a623162bf3c34b45fd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Environment/BG/foreground.png" +dest_files=["res://.godot/imported/foreground.png-d037a775d391d8a623162bf3c34b45fd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Assets/Environment/BG/midground.png b/Assets/Environment/BG/midground.png new file mode 100644 index 0000000000000000000000000000000000000000..6202d0195b3f9c705b46a2d01d1b2afa16b074e2 GIT binary patch literal 1211 zcmds%-Ahwp9LImpcJ|`g3!61}G%t<{-neul!f0CC+HxZmwIsbr&t_?)7c)&(nV#0H zMP^-&UPy#gh{`C6bm}}EgTTrNs!1=diweoGuvn$lvuWVp;Nkb2!}s(3exK*LI;TsD z3lwAu2>=R*-C72Krtwlr#h8>{;Op=QHI)@uQ23Fq9Sfq)Tx15gbxyY66k$!**vpCl zj${I`K7d~sv7Z1A=>cXKfXx8_t^3koX&yGjt{nwdI15i;)IBvN!z96NuWSOy&WJ7K zxw^FlLrJrv$R?SQtW)Now7Ww_0O4PU)x66yH5)EfaE!d;nYmVJuumr>tT~Z4U}9c( z{YXW5lfBh{8Y*#rH9!5$-?Z}w!(X1}w|#6J4l4j{ANG1i}? zLtT{eXYiQDNl+2Z-k}4vIFr)#dm>-sA}U%Nr)T>rkAtzH&=_sm=~pum8*pggilr0I zPE28S1lrhx24Q-lHUhO;vnMEW!gw j92@E8br1Hui2aSgVJo)YurS_#(D@q0 literal 0 HcmV?d00001 diff --git a/Assets/Environment/BG/midground.png.import b/Assets/Environment/BG/midground.png.import new file mode 100644 index 0000000..e7c057d --- /dev/null +++ b/Assets/Environment/BG/midground.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cg22tty2vuet8" +path="res://.godot/imported/midground.png-b73bfa7973b29ce70529610c0fcee36a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Environment/BG/midground.png" +dest_files=["res://.godot/imported/midground.png-b73bfa7973b29ce70529610c0fcee36a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Assets/Environment/BG/sky.png b/Assets/Environment/BG/sky.png new file mode 100644 index 0000000000000000000000000000000000000000..0be90ee5373af9a1b96d617ed82d64c4b1400a74 GIT binary patch literal 1062 zcmeAS@N?(olHy`uVBq!ia0y~yV0-|?d>m{*k-%9;(t#9Xage(cLqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zuqAoByDx`7I;J!Gcf2WgD_*oQu{KXAbW|YuPgg2c4~)y=utFV8C%;gW> z*myt)A~BNXAc2BCTtKa2rpL$npP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;#Hd&H%q~+S&^M000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2kHkK5El!;L|~)<00%`$L_t(&-tCvmZXCxIhQCu)Ju}@s_aTR*Oq-;wK!_wn zwvl&8gj|3;KsL!*fRR_oJ}{6M$UaLu@iv_N?$6CYIe%=|0`j3gFQ&34j09UIuV;ttX#7 zJe`n!nbV(N>dQaIlVj&UShK9RjV#4Ny<({vN1zo(34s;@C9)J)j4ehp9sPQ=wivbgj9Y!iOPeGs?^DE^AOY6wdl(OjYHq9bM=iecXI{>tvZWHf+ ziJl$eRR~_AoF%G4%PX4Wqcb}8Yjc0anUgRMgqjfot?=GMv5zW;cvGXlQ=2O=xR1_9 z4OOKg zfcMPPR}3HolUiFMO$G6eN0m@snEs!E7 z&kK^wagbQ{N0v$IF;)c&```D~hcVJz+6eX9MkI3L^m)E}DOCN{x;D#oMWd#Os)|-L ze=26N+|Om1R{~t6OBwdbydgc@XZUoNybUV$^kW-K3Bbu-tz-U_OYdBHgP1W<6sJVQ_sL@@<3y(W1bYp z@DI0B|2zS@u@DCiWel^%GSkiqWtrg*bE?zP3tET=?{LnOmqO_wwVu7wbD#odMqvue zl5_02d5L~{S`vyJJqsrycoA|ZOlFX$7SA(bI3^`O~e4%;}WQlVqNQ>HO0c-oKo{&;>l6 z*iu9pQ6-^!LM7cpj*@QfNa2GRTWih-irE;SCs^y47H~NA>`fd=?!kEiUqT5M&kS#$ zpFxgG@yE9x2*86kF>u@+TWs#dRQkUQ_EiBc#=By zW{#ws|4|g+@g!KrSp8B3KEC}xKDx5*AEj4+jQi)v&+DKckBqzVGD*D$jj zrUg%@iYGJAp!AeSatm_-GW>i%ky*I2on|kch!zzwl!AH{j9M&nAey4lCvEp};xU6K zxWNwNtYlCqhSoFj9_K*`ME+#I`$VQywzK?&1b%X7)<6q*oIsXuPu-ci;mx(4x;>iKfx7QyB+S8m*J(VgwBdLyRY zX%dC=j+jm}OgdxY3O3){;7@=1iy3}3wE*iIkpc#Q9BilV%=5r!5BD7~IsV~454m#V z##}ZfD5X$JA%GTz`ns*~`B$T3nID|u^p&ULZxkM-&?dkH0Vb%R1B24~S@q6*;W^jk zv|0;kv|2Rlbwof1RR)I%!_oAWZJmoirCO!lXwYmn5fQv-s$qDpEB(0$C{bu_FvcJv zXsuC7eR~Av&Ct*1#6>qgry0d-fj{@o*F=B|0v80HFXR4=67b&R7n$#m-n{?z>VU|6 z3YMb=B#UwSO@-j6?_ZW*{p^RwN37RlqI#V$t`pVk#PvFj=KT79@6I;Qu6Xm`7`I$he`F1@8LS3kV=W)!%*b=ls#vkgGE(`IAq-4nI1w3hXa4Z58+ fS3kV=N-F#p=bTrhzq@d%t literal 0 HcmV?d00001 diff --git a/Assets/Environment/Veges/mushroom_32x64.png.import b/Assets/Environment/Veges/mushroom_32x64.png.import new file mode 100644 index 0000000..99fea3b --- /dev/null +++ b/Assets/Environment/Veges/mushroom_32x64.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dl14otm4thnq2" +path="res://.godot/imported/mushroom_32x64.png-e8c947fe836480d74eafa4339d8b25e2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Environment/Veges/mushroom_32x64.png" +dest_files=["res://.godot/imported/mushroom_32x64.png-e8c947fe836480d74eafa4339d8b25e2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Assets/Environment/Veges/veg_32x32.png b/Assets/Environment/Veges/veg_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..4e09fa94c72733804bbf24e8b93c93c7daf096c0 GIT binary patch literal 675 zcmV;U0$lxxP)EX>4Tx04R}tkv&MmKpe$iTcsiu5i5!~WT;Lph>AFB6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jf7n~Gbq{ROvg%&X$9QWhhy~o`#<}3IpJ#@RbZVYBOe_@ISZ-rhG*sd#;)tSZl<&{D ztZ?4qtd^^+c~AbrP)=J}<~q$0B(R7jh!7y7iW17O5TjKi#YBqs;~xHD$1jpgCRYiJ z91EyGh2;3b|KNAGW`1(QO$x<<&KKMM7zKj6K%-{c-^aGyH~|9Bz?IhWSL(pbC+W48 z7C8cXw}Ff6mL~53mpj1FlP(#OBL!&s^LgO?jJ_!g^xp#AYi@7NeVjf3Y3eF@0~{Oz zV+G1y_jq?#dvE`qY4-O6go1LeRQ&;x00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=>riLDmieSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{004VQL_t(o!|ju?4Zt7_1PueQT$ad4EWvVFfK*5>Yzf;q zY5pn-!u{hw1ONa4006+xlv4-w(dJs;*Hb5K$3aK5xV}Y5s6Pw5~a#BWiLE#M?t^`K{fyY002ov JPDHLkV1hjJ7cT$+ literal 0 HcmV?d00001 diff --git a/Assets/Environment/Veges/veg_32x32.png.import b/Assets/Environment/Veges/veg_32x32.png.import new file mode 100644 index 0000000..ead4b98 --- /dev/null +++ b/Assets/Environment/Veges/veg_32x32.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c7bikbpg5swtd" +path="res://.godot/imported/veg_32x32.png-33598d1a116938a361ee88ef51853556.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Environment/Veges/veg_32x32.png" +dest_files=["res://.godot/imported/veg_32x32.png-33598d1a116938a361ee88ef51853556.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Assets/Pickups/coin.png b/Assets/Pickups/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..01ae33d70b398db7f1f7bcafe883a0a469805201 GIT binary patch literal 500 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 void: position += transform.x * speed * delta func _on_body_entered(body: Node2D) -> void: - if body is Crate: + if body.is_in_group("shootable"): bulletHitSignal.emit(body,self) diff --git a/Scripts/game.gd b/Scripts/game.gd index 7dbb33c..d8c8b95 100644 --- a/Scripts/game.gd +++ b/Scripts/game.gd @@ -1,13 +1,27 @@ class_name GameController extends Node2D signal destroySignal(body) +signal playerHurtSignal(playerHealth,maxHealth) +signal playerDeadSignal var numberOfCrates = 2 +var totalCoinsCollected = 0 + var timer = Timer.new() var timeAvailable = 50 +var currentPlayerHealth = 100 +var startingHealth = 100 +var enemiesDict = {} + +var enemy:CharacterStats +var player:CharacterStats + # Called when the node enters the scene tree for the first time. func _ready() -> void: get_window().grab_focus() + player = load("res://Scripts/rscs/playerStats.tres") + enemy = load("res://Scripts/rscs/slimeStats.tres") + add_child(timer) # time based on seconds timer.wait_time = 1 @@ -16,12 +30,15 @@ func _ready() -> void: timer.connect("timeout", countdown) timer.start() +func reset()->void: + currentPlayerHealth = player.startingHealth + func countdown() -> void: # Reduce time left timeAvailable -= 1 if timeAvailable <= 0 and numberOfCrates > 0: print("LOSER") - get_tree().reload_current_scene() + playerDeadSignal.emit() # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: @@ -32,7 +49,8 @@ func _on_trigger(body: Variant, trigger: Variant, intent:String) -> void: print("Game controller knows trigger fired") match intent: "destroy": - destroySignal.emit(body) + if body is RigidBody2D: + destroySignal.emit(body) func crateTotal(howMany): numberOfCrates = howMany @@ -41,8 +59,45 @@ func crateTotal(howMany): print("YOU WON!!!") get_tree().reload_current_scene() +func coinCollected(body,coin)->void: + print("GC knows coin collected") + totalCoinsCollected +=1 + destroySignal.emit(coin) + +func coinTotal(totalAmount)->void: + print("GC knows total coins "+str(totalAmount)) + +func totalEnemies(numberOfEnemies)->void: + print("GC knows total bad guys "+str(numberOfEnemies)) + +func slimeAttack(body,slime)->void: + print("GC knows slime attack "+str(enemiesDict[slime]["damage"])) + currentPlayerHealth -= enemiesDict[slime]["damage"] + if currentPlayerHealth > 0: + print("ouch") + playerHurtSignal.emit(currentPlayerHealth,startingHealth) + else: + print("ded") + playerDeadSignal.emit() + func bulletDamage(body, _bullet)->void: if body.is_in_group("shootable"): - destroySignal.emit(body) - destroySignal.emit(_bullet) - + if body is Crate: + destroySignal.emit(body) + destroySignal.emit(_bullet) + if body is Slime: + enemiesDict[body]["health"]-=player.rangeDamage + if enemiesDict[body]["health"] <=0: + enemiesDict.erase(body) + destroySignal.emit(body) + destroySignal.emit(_bullet) + +func levelChange()->void: + get_tree().reload_current_scene() + +func addEnemyToLevel(slime)->void: + var stats = { + "health": enemy.startingHealth+randi_range(0,20), + "damage": enemy.meleeDamage+randi_range(0,10) + } + enemiesDict[slime]=stats diff --git a/Scripts/player.gd b/Scripts/player.gd index 25c4815..e67c660 100644 --- a/Scripts/player.gd +++ b/Scripts/player.gd @@ -1,6 +1,7 @@ class_name Player extends CharacterBody2D signal pushSignal(body, direction) signal shootSignal(markerPosition, speed) +signal deathAnimationCompleteSignal const SPEED = 300.0 const JUMP_VELOCITY = -400.0 @@ -18,18 +19,25 @@ var pushTimer = 0 enum FaceDirection {RIGHT,LEFT} var facing:FaceDirection = FaceDirection.RIGHT -enum playerStates {IDLE, RUNNING, JUMPING, FALLING, CHARGING, SHOVING} +enum playerStates {IDLE, RUNNING, JUMPING, FALLING, CHARGING, SHOVING, HURT, DEAD} var current_player_state:playerStates = playerStates.IDLE var upJump = false func _physics_process(delta: float) -> void: + if current_player_state != playerStates.DEAD: + handle_input() handle_movement(delta) - handle_input() handle_states() handle_animation() move_and_slide() handle_collisions() +func hurt(playerHealth, maxHealth)->void: + current_player_state = playerStates.HURT + +func kill()->void: + current_player_state = playerStates.DEAD + func handle_input()->void: # Handle jump. if Input.is_action_just_pressed("ui_accept") and is_on_floor(): @@ -38,7 +46,6 @@ func handle_input()->void: upJump = true #Handle shove target if Input.is_action_just_pressed("shove"): - print("I want to shove") if pushRightEnabled && facing==FaceDirection.RIGHT: current_player_state = playerStates.CHARGING pushTimer = Time.get_ticks_msec() @@ -59,7 +66,6 @@ func handle_input()->void: #Handle Shoot Bullet if Input.is_action_just_pressed("shoot"): - print("Ima shoot a bullet") #marker postion, speed match facing: FaceDirection.RIGHT: @@ -88,7 +94,6 @@ func handle_movement(delta)->void: func handle_collisions()->void: if right_cast.is_colliding(): - print("Right raycast collision") var collider = right_cast.get_collider() if collider is Node: pushRightEnabled = true @@ -97,7 +102,6 @@ func handle_collisions()->void: pushRightEnabled = false if left_cast.is_colliding(): - print("Left raycast collision") var collider = left_cast.get_collider() if collider is Node: pushLeftEnabled = true @@ -115,7 +119,6 @@ func handle_collisions()->void: func handle_states()->void: match current_player_state: playerStates.IDLE when velocity.x != 0: - print("I run") current_player_state = playerStates.RUNNING playerStates.RUNNING when velocity.x == 0: current_player_state = playerStates.IDLE @@ -142,6 +145,10 @@ func handle_animation()->void: player_graphic.play("charging") playerStates.SHOVING: player_graphic.play("shoving") + playerStates.HURT: + player_graphic.play("hurt") + playerStates.DEAD: + player_graphic.play("dead") func _on_animation_finished() -> void: @@ -150,3 +157,7 @@ func _on_animation_finished() -> void: upJump = false playerStates.SHOVING: current_player_state = playerStates.IDLE + playerStates.HURT: + current_player_state = playerStates.IDLE + playerStates.DEAD: + deathAnimationCompleteSignal.emit() diff --git a/Scripts/rscs/characterstats.gd b/Scripts/rscs/characterstats.gd new file mode 100644 index 0000000..ce376de --- /dev/null +++ b/Scripts/rscs/characterstats.gd @@ -0,0 +1,10 @@ +class_name CharacterStats extends Resource + +#health +@export var currentHealth:int = 100 +@export var maxHealth := 150 +@export var startingHealth := 100 + +#damage +@export var meleeDamage := 20 +@export var rangeDamage := 15 diff --git a/Scripts/rscs/characterstats.gd.uid b/Scripts/rscs/characterstats.gd.uid new file mode 100644 index 0000000..45505b5 --- /dev/null +++ b/Scripts/rscs/characterstats.gd.uid @@ -0,0 +1 @@ +uid://b184uwt12pcwt diff --git a/Scripts/rscs/playerStats.tres b/Scripts/rscs/playerStats.tres new file mode 100644 index 0000000..9ae14f0 --- /dev/null +++ b/Scripts/rscs/playerStats.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="CharacterStats" format=3 uid="uid://be2pt870o5sfl"] + +[ext_resource type="Script" uid="uid://b184uwt12pcwt" path="res://Scripts/rscs/characterstats.gd" id="1_eiyfu"] + +[resource] +script = ExtResource("1_eiyfu") +maxHealth = 200 +meleeDamage = 30 +rangeDamage = 20 +metadata/_custom_type_script = "uid://b184uwt12pcwt" diff --git a/Scripts/rscs/slimeStats.tres b/Scripts/rscs/slimeStats.tres new file mode 100644 index 0000000..9c70ef5 --- /dev/null +++ b/Scripts/rscs/slimeStats.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="CharacterStats" format=3 uid="uid://bv3403ln5bjch"] + +[ext_resource type="Script" uid="uid://b184uwt12pcwt" path="res://Scripts/rscs/characterstats.gd" id="1_g41dv"] + +[resource] +script = ExtResource("1_g41dv") +currentHealth = 60 +maxHealth = 80 +startingHealth = 60 +rangeDamage = 0 +metadata/_custom_type_script = "uid://b184uwt12pcwt" diff --git a/Scripts/scene_manager.gd b/Scripts/scene_manager.gd index 8dc10c1..3641583 100644 --- a/Scripts/scene_manager.gd +++ b/Scripts/scene_manager.gd @@ -1,29 +1,42 @@ extends Node2D # hold control and drag + drop -@onready var game:GameController = $".." + @onready var crates: Node2D = $"../Crates" @onready var player: Player = $"../Player" +@onready var coins: Node2D = $"../Coins" +@onready var enemies: Node2D = $"../Enemies" var bullet = preload("res://Scenes/bullet.tscn") var bulletArray:Array[Bullet] = [] var totalAllowedBullets:int = 7 +var coin # Called when the node enters the scene tree for the first time. func _ready() -> void: + Gamecontroller.reset() player.pushSignal.connect(pushTarget) player.shootSignal.connect(makeBullet) + player.deathAnimationCompleteSignal.connect(Gamecontroller.levelChange) #signals from the GameController - game.destroySignal.connect(destroy) + Gamecontroller.destroySignal.connect(destroy) + Gamecontroller.playerHurtSignal.connect(player.hurt) + Gamecontroller.playerDeadSignal.connect(player.kill) + + #signals from pickups + #coin.coinCollectedSignal.connect(Gamecontroller.coinCollected) buildLevel() # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass - + func buildLevel() -> void: #tell GC how many crates... updateCrates() + updateCoins() + updateEnemies() + func updateCrates()->void: var totalCrates = 0 if crates: @@ -33,7 +46,31 @@ func updateCrates()->void: obj.tree_exited.connect(updateCrates) totalCrates +=1 - game.crateTotal(totalCrates) + Gamecontroller.crateTotal(totalCrates) + +func updateCoins()->void: + var totalCoins = 0 + if coins: + print("updateCoins called") + for obj in coins.get_children(): + if obj is Coin: + if not obj.tree_exited.is_connected(updateCoins): + obj.tree_exited.connect(updateCoins) + if not obj.coinCollectedSignal.is_connected(Gamecontroller.coinCollected): + obj.coinCollectedSignal.connect(Gamecontroller.coinCollected) + totalCoins +=1 + Gamecontroller.coinTotal(totalCoins) + +func updateEnemies()->void: + var totalEnemies = 0 + if enemies: + for obj in enemies.get_children(): + if obj is Slime: + Gamecontroller.addEnemyToLevel(obj) + obj.slimeDamageSignal.connect(Gamecontroller.slimeAttack) + totalEnemies += 1 + Gamecontroller.totalEnemies(totalEnemies) + func pushTarget(body,pushDirection)->void: if body is RigidBody2D: body.apply_central_impulse(pushDirection) @@ -61,8 +98,8 @@ func bulletFactory()->Bullet: #make a new bullet myBullet = bullet.instantiate() add_sibling(myBullet) - if not myBullet.bulletHitSignal.is_connected(game.bulletDamage): - myBullet.bulletHitSignal.connect(game.bulletDamage) + if not myBullet.bulletHitSignal.is_connected(Gamecontroller.bulletDamage): + myBullet.bulletHitSignal.connect(Gamecontroller.bulletDamage) else: # gets oldest one - pop_back myBullet = bulletArray.pop_back() diff --git a/Scripts/slime.gd b/Scripts/slime.gd new file mode 100644 index 0000000..c1133d1 --- /dev/null +++ b/Scripts/slime.gd @@ -0,0 +1,30 @@ +class_name Slime extends Area2D +@onready var right_cast: RayCast2D = $rightCast +@onready var right_down_cast: RayCast2D = $rightDownCast +@onready var left_down_cast: RayCast2D = $leftDownCast +@onready var left_cast: RayCast2D = $leftCast +@onready var slime_graphic: AnimatedSprite2D = $slimeGraphic + +signal slimeDamageSignal(body,slime) +@export var speed:int = 100 +var direction = 1 + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + if not right_down_cast.is_colliding(): + direction = -1 + slime_graphic.flip_h = true + if not left_down_cast.is_colliding(): + direction = 1 + slime_graphic.flip_h = false + if right_cast.is_colliding() && not right_cast.get_collider() is Player: + direction = -1 + slime_graphic.flip_h = true + if left_cast.is_colliding() && not left_cast.get_collider() is Player: + direction = 1 + slime_graphic.flip_h = false + position.x += direction*speed*delta + + +func _on_body_entered(body: Node2D) -> void: + slimeDamageSignal.emit(body,self) diff --git a/Scripts/slime.gd.uid b/Scripts/slime.gd.uid new file mode 100644 index 0000000..2c271f5 --- /dev/null +++ b/Scripts/slime.gd.uid @@ -0,0 +1 @@ +uid://0upi64wxvgdi diff --git a/project.godot b/project.godot index 0263f05..7a2a88d 100644 --- a/project.godot +++ b/project.godot @@ -12,9 +12,21 @@ config_version=5 config/name="CatGame" run/main_scene="uid://bportqr2j3d7s" -config/features=PackedStringArray("4.6", "Forward Plus") +config/features=PackedStringArray("4.7", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +Gamecontroller="*uid://cvrssvw6p8myl" + +[display] + +window/size/viewport_width=480 +window/size/viewport_height=270 +window/size/window_width_override=960 +window/size/window_height_override=540 +window/stretch/mode="viewport" + [input] shove={