From 8e211dd1f643a0e7b1731ca8b167e14c40bdb89a Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:59:14 +1000 Subject: [PATCH 01/29] Added atlas and png files and created an animation controller for new mob boss Patrick --- .../core/assets/images/mobboss/patrick.atlas | 198 ++++++++++++++++++ source/core/assets/images/mobboss/patrick.png | Bin 0 -> 97275 bytes .../csse3200/game/areas/ForestGameArea.java | 6 +- .../bosses/DemonAnimationController.java | 4 +- .../bosses/PatrickAnimationController.java | 39 ++++ 5 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 source/core/assets/images/mobboss/patrick.atlas create mode 100644 source/core/assets/images/mobboss/patrick.png create mode 100644 source/core/src/main/com/csse3200/game/components/bosses/PatrickAnimationController.java diff --git a/source/core/assets/images/mobboss/patrick.atlas b/source/core/assets/images/mobboss/patrick.atlas new file mode 100644 index 000000000..c86c282e1 --- /dev/null +++ b/source/core/assets/images/mobboss/patrick.atlas @@ -0,0 +1,198 @@ +Patrick.png +size:2048,512 +repeat:none +Bringer-of-Death_Attack +index:3 +bounds:2,97,140,93 +Bringer-of-Death_Attack +index:8 +bounds:428,382,140,93 +Bringer-of-Death_Attack +index:10 +bounds:286,97,140,93 +Bringer-of-Death_Attack +index:5 +bounds:854,382,140,93 +Bringer-of-Death_Attack +index:2 +bounds:712,97,140,93 +Bringer-of-Death_Attack +index:7 +bounds:1138,287,140,93 +Bringer-of-Death_Attack +index:4 +bounds:996,2,140,93 +Bringer-of-Death_Attack +index:9 +bounds:1280,192,140,93 +Bringer-of-Death_Attack +index:1 +bounds:1706,382,140,93 +Bringer-of-Death_Attack +index:6 +bounds:1422,2,140,93 +Bringer-of-Death_Cast +index:3 +bounds:144,287,140,93 +Bringer-of-Death_Cast +index:8 +bounds:286,287,140,93 +Bringer-of-Death_Cast +index:5 +bounds:286,2,140,93 +Bringer-of-Death_Cast +index:2 +bounds:996,382,140,93 +Bringer-of-Death_Cast +index:7 +bounds:1138,382,140,93 +Bringer-of-Death_Cast +index:4 +bounds:1280,287,140,93 +Bringer-of-Death_Cast +index:9 +bounds:1138,97,140,93 +Bringer-of-Death_Cast +index:1 +bounds:1138,2,140,93 +Bringer-of-Death_Cast +index:6 +bounds:1422,97,140,93 +Bringer-of-Death_Death +index:4 +bounds:2,192,140,93 +Bringer-of-Death_Death +index:9 +bounds:144,192,140,93 +Bringer-of-Death_Death +index:1 +bounds:286,192,140,93 +Bringer-of-Death_Death +index:6 +bounds:712,382,140,93 +Bringer-of-Death_Death +index:3 +bounds:854,287,140,93 +Bringer-of-Death_Death +index:8 +bounds:996,287,140,93 +Bringer-of-Death_Death +index:10 +bounds:996,192,140,93 +Bringer-of-Death_Death +index:5 +bounds:1138,192,140,93 +Bringer-of-Death_Death +index:2 +bounds:1422,192,140,93 +Bringer-of-Death_Death +index:7 +bounds:1564,192,140,93 +Bringer-of-Death_Hurt +index:1 +bounds:144,2,140,93 +Bringer-of-Death_Hurt +index:3 +bounds:854,192,140,93 +Bringer-of-Death_Hurt +index:2 +bounds:1280,2,140,93 +Bringer-of-Death_Idle +index:7 +bounds:2,287,140,93 +Bringer-of-Death_Idle +index:4 +bounds:144,97,140,93 +Bringer-of-Death_Idle +index:1 +bounds:712,287,140,93 +Bringer-of-Death_Idle +index:6 +bounds:570,97,140,93 +Bringer-of-Death_Idle +index:3 +bounds:854,97,140,93 +Bringer-of-Death_Idle +index:8 +bounds:854,2,140,93 +Bringer-of-Death_Idle +index:5 +bounds:1564,382,140,93 +Bringer-of-Death_Idle +index:2 +bounds:1848,382,140,93 +Bringer-of-Death_Spell +index:7 +bounds:2,382,140,93 +Bringer-of-Death_Spell +index:13 +bounds:144,382,140,93 +Bringer-of-Death_Spell +index:4 +bounds:2,2,140,93 +Bringer-of-Death_Spell +index:3 +bounds:2,2,140,93 +Bringer-of-Death_Spell +index:10 +bounds:428,287,140,93 +Bringer-of-Death_Spell +index:9 +bounds:428,192,140,93 +Bringer-of-Death_Spell +index:15 +bounds:570,287,140,93 +Bringer-of-Death_Spell +index:16 +bounds:570,287,140,93 +Bringer-of-Death_Spell +index:1 +bounds:570,192,140,93 +Bringer-of-Death_Spell +index:2 +bounds:570,192,140,93 +Bringer-of-Death_Spell +index:6 +bounds:428,2,140,93 +Bringer-of-Death_Spell +index:12 +bounds:712,192,140,93 +Bringer-of-Death_Spell +index:8 +bounds:1280,382,140,93 +Bringer-of-Death_Spell +index:14 +bounds:996,97,140,93 +Bringer-of-Death_Spell +index:5 +bounds:1422,287,140,93 +Bringer-of-Death_Spell +index:11 +bounds:1280,97,140,93 +Bringer-of-Death_Walk +index:4 +bounds:286,382,140,93 +Bringer-of-Death_Walk +index:1 +bounds:570,382,140,93 +Bringer-of-Death_Walk +index:6 +bounds:428,97,140,93 +Bringer-of-Death_Walk +index:3 +bounds:570,2,140,93 +Bringer-of-Death_Walk +index:8 +bounds:712,2,140,93 +Bringer-of-Death_Walk +index:5 +bounds:1422,382,140,93 +Bringer-of-Death_Walk +index:2 +bounds:1564,287,140,93 +Bringer-of-Death_Walk +index:7 +bounds:1706,287,140,93 +Default +index:7 +bounds:2,287,140,93 diff --git a/source/core/assets/images/mobboss/patrick.png b/source/core/assets/images/mobboss/patrick.png new file mode 100644 index 0000000000000000000000000000000000000000..6699d771e4549abc50027c746df29b3592b1b0d4 GIT binary patch literal 97275 zcmce-i93|h-#>oSilnj?G1-%?B0`p|+1rqakWiMgW|+?L%U+|mja?P0gKKGpS-p}j(I86sH zn55*1C8{)meW+&EVxVE6F%(F1I`zaF}N=O(pD2IXDFsFBqg!RC~#c8LDtwQv22|9%I)7aBU;niAa1 zO~~Mr)eL`zEZew-$Z7TWWG~QPgHNyVCw-hdWOydoT&Wp-s@JQ2_+s4U# z?JbqcqeoZ&&rSV-HH+TjHhknHZZ`^fq=Jm7C2-bhLH_qKKuw;UC9RlpGX}0xwXu9G z2+C?=@fuPCh5lzf5txAKmS{ZyINUB+dL%A-v*<&Cw42_koL^ zn9=oF2y53C*N&ujR~`mF{t!gUaSp9=vT}B#d`ljOU4mr`7!A=j*XzF?`|mJatL;N@ zUP0zuJxeGKR9D0k%-^#dPK7?kl#z0oaN#TXrv|uXzVU!*LJSW!d`M$DO{<0cuQUn-Wa%-K9xSUa z0Cb2QWv9EAt%7CC90a4Ho2#PaWn=u}T_$vx(rgOX`JYih+6FHm9?bUe6cB-#=j!*Q zyb5fd#^d;F8MB^u>jt>#VLqz=of!~1T&3wqRmsps<~7j*{Cv9fan)g><`@)hn)uIK zM(-MyH9(w`AxT#jgrAFYi)XHdNdv%Q7zW6Ht<*8Xi{WP7j$Zh^u}U0YGD;y-sr=8A z_w*_#$X}atG6;YB@u$?LTgR{8@gNwWD^0l)1OeNPiz496Xe@Y-J^ zuWd3ZniASte`i;y)=_T!f1RTtS!wUX^Xs!aqGt@}U2Zd+5x2w){2Ack>3VXJ8mF#T!a8>{P=*Z^IpszbY|mWGgC z!P(^mk48PDS!<0pTy^o_URWJP6ChGR zE9zf$*ld2l3oLooPm#><|Iej9<|=KC2!lgCn&UWtG5_{Vq`Bo(wUT;s&=-S$2P3W= zu&-{p4PFBFUdc5*-PF485Zt9AG*H|Oy~d4olrQ!M<5OWIwZ+5^050;;nKGvY%_$3` z!EB2mu)n0er_z!o6=!pgVP_hMIRxQ?{b?~S02j~KbvW73b?SDgX1svS>M>qm&FPzp zK|U{F5WpVs*A)~oJN(!J*NP(!wQE%5;R^wmd`Dn_4BC3c@tJsuFJLCQ-?r}R*egi? z+)~*N;}q%RX}Q&5sG#kxVsu>ihEcdrK*t&G?_27#2fl{GG2pTw0^h|qR#qj_@&Kz0x zpZ3SG4eu(XUi&AoHgh{w~`-NPNo)Jx_XdcPK8eresQqs_oo z*}f|;yFt?gm{O(K!FKNy>@mmzU`Lfepe*uNVJ;=KtUH{7HG_@{xvL5O=%Oy>=qcF@ zl~WBEUj#cBQ0NTPx&2hfwV;w8mVZK5=Hh{8(bunXqTi%Apr_;24E=u*xzUlY%9xLL ztY@e$ zO-_{mZB9|m^;War527MJ1+~QwrGl9O3;Ni`1g7{2c8098``R}KdP-65%(ar_cq5Y{ z8$W4A&YX#)Z->aEmBQxrrw(h$${(|p>L@HCsyZ6a%BCQ;oZ8;25ah?S~HJ6@_&p`#Q#9T9q5=G$W&(Zqu-yfE6nYLEi$riw9?X%~T=$WkxU7Ajdl@eJ%{|^^+VkGRajlBEd z*-iD|ydkqN0_r@S5O5>vKVHz)EvP2mmLxxX%&VtGkk-{wF^e~A#VSS%)FdeFIKAc4 zUdzLP;`eQImPPV5*J~e$JpnJy`1Lo%0Dn1 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 lSl;wdrafH%p#5Z27uq-pns<;kB}E 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 + animator.startAnimation(animationName)); + } +} \ No newline at end of file From fba5dca5083a7f70eced412d88a4c89a82be52a9 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Fri, 22 Sep 2023 21:08:48 +1000 Subject: [PATCH 02/29] Created event listeners for patrick boss --- .../core/assets/images/mobboss/patrick.atlas | 128 +++++++++--------- .../bosses/PatrickAnimationController.java | 25 ++-- ...DeathBringerTask.java => PatrickTask.java} | 4 +- .../entities/factories/MobBossFactory.java | 41 +++++- 4 files changed, 111 insertions(+), 87 deletions(-) rename source/core/src/main/com/csse3200/game/components/tasks/bosstask/{DeathBringerTask.java => PatrickTask.java} (88%) diff --git a/source/core/assets/images/mobboss/patrick.atlas b/source/core/assets/images/mobboss/patrick.atlas index c86c282e1..e4388a59c 100644 --- a/source/core/assets/images/mobboss/patrick.atlas +++ b/source/core/assets/images/mobboss/patrick.atlas @@ -1,196 +1,196 @@ Patrick.png size:2048,512 repeat:none -Bringer-of-Death_Attack +Patrick_Attack index:3 bounds:2,97,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:8 bounds:428,382,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:10 bounds:286,97,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:5 bounds:854,382,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:2 bounds:712,97,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:7 bounds:1138,287,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:4 bounds:996,2,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:9 bounds:1280,192,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:1 bounds:1706,382,140,93 -Bringer-of-Death_Attack +Patrick_Attack index:6 bounds:1422,2,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:3 bounds:144,287,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:8 bounds:286,287,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:5 bounds:286,2,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:2 bounds:996,382,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:7 bounds:1138,382,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:4 bounds:1280,287,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:9 bounds:1138,97,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:1 bounds:1138,2,140,93 -Bringer-of-Death_Cast +Patrick_Cast index:6 bounds:1422,97,140,93 -Bringer-of-Death_Death +Patrick_Death index:4 bounds:2,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:9 bounds:144,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:1 bounds:286,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:6 bounds:712,382,140,93 -Bringer-of-Death_Death +Patrick_Death index:3 bounds:854,287,140,93 -Bringer-of-Death_Death +Patrick_Death index:8 bounds:996,287,140,93 -Bringer-of-Death_Death +Patrick_Death index:10 bounds:996,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:5 bounds:1138,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:2 bounds:1422,192,140,93 -Bringer-of-Death_Death +Patrick_Death index:7 bounds:1564,192,140,93 -Bringer-of-Death_Hurt +Patrick_Hurt index:1 bounds:144,2,140,93 -Bringer-of-Death_Hurt +Patrick_Hurt index:3 bounds:854,192,140,93 -Bringer-of-Death_Hurt +Patrick_Hurt index:2 bounds:1280,2,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:7 bounds:2,287,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:4 bounds:144,97,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:1 bounds:712,287,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:6 bounds:570,97,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:3 bounds:854,97,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:8 bounds:854,2,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:5 bounds:1564,382,140,93 -Bringer-of-Death_Idle +Patrick_Idle index:2 bounds:1848,382,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:7 bounds:2,382,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:13 bounds:144,382,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:4 bounds:2,2,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:3 bounds:2,2,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:10 bounds:428,287,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:9 bounds:428,192,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:15 bounds:570,287,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:16 bounds:570,287,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:1 bounds:570,192,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:2 bounds:570,192,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:6 bounds:428,2,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:12 bounds:712,192,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:8 bounds:1280,382,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:14 bounds:996,97,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:5 bounds:1422,287,140,93 -Bringer-of-Death_Spell +Patrick_Spell index:11 bounds:1280,97,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:4 bounds:286,382,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:1 bounds:570,382,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:6 bounds:428,97,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:3 bounds:570,2,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:8 bounds:712,2,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:5 bounds:1422,382,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:2 bounds:1564,287,140,93 -Bringer-of-Death_Walk +Patrick_Walk index:7 bounds:1706,287,140,93 Default diff --git a/source/core/src/main/com/csse3200/game/components/bosses/PatrickAnimationController.java b/source/core/src/main/com/csse3200/game/components/bosses/PatrickAnimationController.java index a9e64a357..4a5d4351e 100644 --- a/source/core/src/main/com/csse3200/game/components/bosses/PatrickAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/bosses/PatrickAnimationController.java @@ -3,7 +3,7 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -public class DemonAnimationController extends Component { +public class PatrickAnimationController extends Component { AnimationRenderComponent animator; /** @@ -14,22 +14,13 @@ public class DemonAnimationController extends Component { public void create() { super.create(); animator = entity.getComponent(AnimationRenderComponent.class); - registerAnimationListener("demon_walk"); - registerAnimationListener("demon_cleave"); - registerAnimationListener("demon_take_hit"); - registerAnimationListener("demon_idle"); - registerAnimationListener("demon_death"); - registerAnimationListener("demon_cast_spell"); - registerAnimationListener("demon_fire_breath"); - registerAnimationListener("demon_smash"); - registerAnimationListener("demon_take_hit"); - registerAnimationListener("idle"); - registerAnimationListener("move"); - registerAnimationListener("projectile_explosion"); - registerAnimationListener("projectile_idle"); - registerAnimationListener("take_hit"); - registerAnimationListener("transform"); - registerAnimationListener("transform_reverse"); + registerAnimationListener("Patrick_Attack"); + registerAnimationListener("Patrick_Cast"); + registerAnimationListener("Patrick_Death"); + registerAnimationListener("Patrick_Hurt"); + registerAnimationListener("Patrick_Idle"); + registerAnimationListener("Patrick_Spell"); + registerAnimationListener("Patrick_Walk"); } private void registerAnimationListener(String animationName) { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DeathBringerTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java similarity index 88% rename from source/core/src/main/com/csse3200/game/components/tasks/bosstask/DeathBringerTask.java rename to source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 1165f9dd2..ad1a9b68a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DeathBringerTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -6,7 +6,7 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; -public class DeathBringerTask extends DefaultTask implements PriorityTask { +public class PatrickTask extends DefaultTask implements PriorityTask { private static final int PRIORITY = 3; private PhysicsEngine physics; private GameTime gameTime; @@ -14,7 +14,7 @@ private enum DeathBringerState { IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL } - public DeathBringerTask() { + public PatrickTask() { physics = ServiceLocator.getPhysicsService().getPhysics(); gameTime = ServiceLocator.getTimeSource(); } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index 049b12e02..a262b39ee 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -5,12 +5,10 @@ import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.components.*; import com.csse3200.game.components.bosses.DemonAnimationController; +import com.csse3200.game.components.bosses.PatrickAnimationController; import com.csse3200.game.components.npc.Boss1AnimationController; import com.csse3200.game.components.npc.Boss2AnimationController; -import com.csse3200.game.components.tasks.bosstask.DemonBossTask; -import com.csse3200.game.components.tasks.bosstask.FinalBossMovementTask; -import com.csse3200.game.components.tasks.bosstask.RangeBossTask; -import com.csse3200.game.components.tasks.bosstask.MobBossDeathTask; +import com.csse3200.game.components.tasks.bosstask.*; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.configs.MobBossConfigs; import com.csse3200.game.entities.configs.NPCConfigs; @@ -28,6 +26,8 @@ public class MobBossFactory { private static final int BOSS_MOB_AGRO_RANGE = 10; private static final int DEMON_HEALTH = 5000; private static final int DEMON_ATTACK = 0; + private static final int PATRICK_HEALTH = 2500; + private static final int PATRICK_ATTACK = 0; // Create Demon Boss public static Entity createDemonBoss() { @@ -71,6 +71,39 @@ public static Entity createDemonBoss() { return demon; } + public static Entity createPatrickBoss() { + MobBossConfigs config = configs.MobBoss; + Entity demon = createBaseBoss(); + + // Animation addition + AnimationRenderComponent animator = new AnimationRenderComponent( + ServiceLocator.getResourceService().getAsset("images/mobboss/patrick.atlas", TextureAtlas.class)); + animator.addAnimation("Patrick_Attack", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Cast", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Death", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Hurt", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Idle", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Spell", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("Patrick_Walk", 0.2f, Animation.PlayMode.NORMAL); + + // AI task addition + AITaskComponent aiTaskComponent = new AITaskComponent() + .addTask(new PatrickTask()); + + // Component addition + demon + .addComponent(animator) + .addComponent(new PatrickAnimationController()) + .addComponent(aiTaskComponent) + .addComponent(new CombatStatsComponent(PATRICK_HEALTH, PATRICK_ATTACK)); + + // Scale demon + demon.getComponent(AnimationRenderComponent.class).scaleEntity(); + demon.scaleHeight(5f); + demon.scaleWidth(5f); + return demon; + } + // Create Boss King 1 public static Entity createMobBoss1(int numLane) { MobBossConfigs config = configs.MobBoss; From 2d4a40663009d786eb434eff512f0b8c2a5879e4 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Fri, 22 Sep 2023 21:14:07 +1000 Subject: [PATCH 03/29] base task class implemented --- .../tasks/bosstask/DemonBossTask.java | 10 +++--- .../tasks/bosstask/PatrickTask.java | 34 +++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index 0445b912d..ee4ad99d2 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -53,7 +53,6 @@ public class DemonBossTask extends DefaultTask implements PriorityTask { private final GameTime gameTime; private Vector2 jumpPos; private MovementTask jumpTask; - private boolean isJumping; private DemonState state = DemonState.IDLE; private DemonState prevState; private AnimationRenderComponent animation; @@ -63,13 +62,14 @@ public class DemonBossTask extends DefaultTask implements PriorityTask { private static int xLeftBoundary = 12; private ProjectileEffects effect = ProjectileEffects.BURN; private boolean aoe = true; - private boolean slimeFlag = false; + private int deathCounter = 0; + + // Flags private boolean startFlag = false; private boolean moving = false; - private int health; + private boolean isJumping; private boolean halfHealthFlag = false; private boolean isHealing = false; - private int deathCounter = 0; /** * The different demon states @@ -133,7 +133,7 @@ public void update() { animate(); currentPos = demon.getPosition(); - health = demon.getComponent(CombatStatsComponent.class).getHealth(); + int health = demon.getComponent(CombatStatsComponent.class).getHealth(); // handle initial demon transformation if (animation.getCurrentAnimation().equals("transform") && animation.isFinished()) { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index ad1a9b68a..921911988 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -1,15 +1,31 @@ package com.csse3200.game.components.tasks.bosstask; +import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.entities.Entity; import com.csse3200.game.physics.PhysicsEngine; +import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PatrickTask extends DefaultTask implements PriorityTask { + + // Constants private static final int PRIORITY = 3; + private static final Vector2 PATRICK_SPEED = new Vector2(1f, 1f); + + // Private variables + private static final Logger logger = LoggerFactory.getLogger(PatrickTask.class); + private Vector2 currentPos; private PhysicsEngine physics; private GameTime gameTime; + private DeathBringerState state = DeathBringerState.IDLE; + private DeathBringerState prevState; + private AnimationRenderComponent animation; + private Entity patrick; private enum DeathBringerState { IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL } @@ -29,6 +45,24 @@ public void update() { } + /** + * Changes the animation of the demon if a state change occurs + */ + private void animate() { + // Check if same animation is being called + if (prevState.equals(state)) { + return; // skip rest of function + } + + switch (state) { + case IDLE -> { + + } + default -> logger.debug("Patrick animation {state} not found"); + } + prevState = state; + } + @Override public int getPriority() { return PRIORITY; From ce8f3d440891fa6a36c2e25084b144cc001fd95a Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Fri, 22 Sep 2023 22:05:03 +1000 Subject: [PATCH 04/29] fixed touchattackcomponent being added to box boy after creation problem --- source/core/assets/images/mobboss/demon.atlas | 96 +++++ .../core/assets/images/mobboss/patrick.atlas | 134 +++---- source/core/assets/images/mobs/boss2.atlas | 348 ------------------ source/core/assets/images/mobs/boss2.png | Bin 45854 -> 0 bytes .../csse3200/game/areas/ForestGameArea.java | 10 +- .../bosses/PatrickAnimationController.java | 14 +- .../tasks/bosstask/PatrickTask.java | 28 +- .../entities/factories/MobBossFactory.java | 14 +- .../entities/factories/PlayerFactory.java | 4 +- 9 files changed, 209 insertions(+), 439 deletions(-) delete mode 100644 source/core/assets/images/mobs/boss2.atlas delete mode 100644 source/core/assets/images/mobs/boss2.png diff --git a/source/core/assets/images/mobboss/demon.atlas b/source/core/assets/images/mobboss/demon.atlas index 7c058a971..612e757cc 100644 --- a/source/core/assets/images/mobboss/demon.atlas +++ b/source/core/assets/images/mobboss/demon.atlas @@ -298,6 +298,60 @@ bounds:1440,320,288,160 transform index:6 bounds:1440,160,288,160 +transform_reverse +index:2 +bounds:288,1280,288,160 +transform_reverse +index:31 +bounds:576,1440,288,160 +transform_reverse +index:18 +bounds:864,1600,288,160 +transform_reverse +index:10 +bounds:288,1120,288,160 +transform_reverse +index:23 +bounds:1152,1600,288,160 +transform_reverse +index:7 +bounds:288,960,288,160 +transform_reverse +index:15 +bounds:1152,1280,288,160 +transform_reverse +index:28 +bounds:0,480,288,160 +transform_reverse +index:20 +bounds:1728,1440,288,160 +transform_reverse +index:4 +bounds:864,800,288,160 +transform_reverse +index:12 +bounds:864,640,288,160 +transform_reverse +index:25 +bounds:1728,1120,288,160 +transform_reverse +index:9 +bounds:0,0,288,160 +transform_reverse +index:1 +bounds:1728,800,288,160 +transform_reverse +index:30 +bounds:576,0,288,160 +transform_reverse +index:17 +bounds:864,160,288,160 +transform_reverse +index:22 +bounds:1440,320,288,160 +transform_reverse +index:6 +bounds:1440,160,288,160 demon2.png size:2048,2048 @@ -518,6 +572,48 @@ bounds:1152,480,288,160 transform index:26 bounds:576,0,288,160 +transform_reverse +index:14 +bounds:576,1760,288,160 +transform_reverse +index:27 +bounds:288,1440,288,160 +transform_reverse +index:3 +bounds:1440,1760,288,160 +transform_reverse +index:32 +bounds:0,800,288,160 +transform_reverse +index:19 +bounds:576,1120,288,160 +transform_reverse +index:11 +bounds:288,800,288,160 +transform_reverse +index:24 +bounds:1152,1280,288,160 +transform_reverse +index:8 +bounds:1728,1600,288,160 +transform_reverse +index:16 +bounds:576,640,288,160 +transform_reverse +index:29 +bounds:1152,960,288,160 +transform_reverse +index:21 +bounds:1440,960,288,160 +transform_reverse +index:5 +bounds:288,160,288,160 +transform_reverse +index:13 +bounds:1152,480,288,160 +transform_reverse +index:26 +bounds:576,0,288,160 default index:3 bounds:864,1760,288,160 diff --git a/source/core/assets/images/mobboss/patrick.atlas b/source/core/assets/images/mobboss/patrick.atlas index e4388a59c..3de3867ca 100644 --- a/source/core/assets/images/mobboss/patrick.atlas +++ b/source/core/assets/images/mobboss/patrick.atlas @@ -1,198 +1,198 @@ -Patrick.png +patrick.png size:2048,512 repeat:none -Patrick_Attack +patrick_attack index:3 bounds:2,97,140,93 -Patrick_Attack +patrick_attack index:8 bounds:428,382,140,93 -Patrick_Attack +patrick_attack index:10 bounds:286,97,140,93 -Patrick_Attack +patrick_attack index:5 bounds:854,382,140,93 -Patrick_Attack +patrick_attack index:2 bounds:712,97,140,93 -Patrick_Attack +patrick_attack index:7 bounds:1138,287,140,93 -Patrick_Attack +patrick_attack index:4 bounds:996,2,140,93 -Patrick_Attack +patrick_attack index:9 bounds:1280,192,140,93 -Patrick_Attack +patrick_attack index:1 bounds:1706,382,140,93 -Patrick_Attack +patrick_attack index:6 bounds:1422,2,140,93 -Patrick_Cast +patrick_cast index:3 bounds:144,287,140,93 -Patrick_Cast +patrick_cast index:8 bounds:286,287,140,93 -Patrick_Cast +patrick_cast index:5 bounds:286,2,140,93 -Patrick_Cast +patrick_cast index:2 bounds:996,382,140,93 -Patrick_Cast +patrick_cast index:7 bounds:1138,382,140,93 -Patrick_Cast +patrick_cast index:4 bounds:1280,287,140,93 -Patrick_Cast +patrick_cast index:9 bounds:1138,97,140,93 -Patrick_Cast +patrick_cast index:1 bounds:1138,2,140,93 -Patrick_Cast +patrick_cast index:6 bounds:1422,97,140,93 -Patrick_Death +patrick_death index:4 bounds:2,192,140,93 -Patrick_Death +patrick_death index:9 bounds:144,192,140,93 -Patrick_Death +patrick_death index:1 bounds:286,192,140,93 -Patrick_Death +patrick_death index:6 bounds:712,382,140,93 -Patrick_Death +patrick_death index:3 bounds:854,287,140,93 -Patrick_Death +patrick_death index:8 bounds:996,287,140,93 -Patrick_Death +patrick_death index:10 bounds:996,192,140,93 -Patrick_Death +patrick_death index:5 bounds:1138,192,140,93 -Patrick_Death +patrick_death index:2 bounds:1422,192,140,93 -Patrick_Death +patrick_death index:7 bounds:1564,192,140,93 -Patrick_Hurt +patrick_hurt index:1 bounds:144,2,140,93 -Patrick_Hurt +patrick_hurt index:3 bounds:854,192,140,93 -Patrick_Hurt +patrick_hurt index:2 bounds:1280,2,140,93 -Patrick_Idle +patrick_idle index:7 bounds:2,287,140,93 -Patrick_Idle +patrick_idle index:4 bounds:144,97,140,93 -Patrick_Idle +patrick_idle index:1 bounds:712,287,140,93 -Patrick_Idle +patrick_idle index:6 bounds:570,97,140,93 -Patrick_Idle +patrick_idle index:3 bounds:854,97,140,93 -Patrick_Idle +patrick_idle index:8 bounds:854,2,140,93 -Patrick_Idle +patrick_idle index:5 bounds:1564,382,140,93 -Patrick_Idle +patrick_idle index:2 bounds:1848,382,140,93 -Patrick_Spell +patrick_spell index:7 bounds:2,382,140,93 -Patrick_Spell +patrick_spell index:13 bounds:144,382,140,93 -Patrick_Spell +patrick_spell index:4 bounds:2,2,140,93 -Patrick_Spell +patrick_spell index:3 bounds:2,2,140,93 -Patrick_Spell +patrick_spell index:10 bounds:428,287,140,93 -Patrick_Spell +patrick_spell index:9 bounds:428,192,140,93 -Patrick_Spell +patrick_spell index:15 bounds:570,287,140,93 -Patrick_Spell +patrick_spell index:16 bounds:570,287,140,93 -Patrick_Spell +patrick_spell index:1 bounds:570,192,140,93 -Patrick_Spell +patrick_spell index:2 bounds:570,192,140,93 -Patrick_Spell +patrick_spell index:6 bounds:428,2,140,93 -Patrick_Spell +patrick_spell index:12 bounds:712,192,140,93 -Patrick_Spell +patrick_spell index:8 bounds:1280,382,140,93 -Patrick_Spell +patrick_spell index:14 bounds:996,97,140,93 -Patrick_Spell +patrick_spell index:5 bounds:1422,287,140,93 -Patrick_Spell +patrick_spell index:11 bounds:1280,97,140,93 -Patrick_Walk +patrick_walk index:4 bounds:286,382,140,93 -Patrick_Walk +patrick_walk index:1 bounds:570,382,140,93 -Patrick_Walk +patrick_walk index:6 bounds:428,97,140,93 -Patrick_Walk +patrick_walk index:3 bounds:570,2,140,93 -Patrick_Walk +patrick_walk index:8 bounds:712,2,140,93 -Patrick_Walk +patrick_walk index:5 bounds:1422,382,140,93 -Patrick_Walk +patrick_walk index:2 bounds:1564,287,140,93 -Patrick_Walk +patrick_walk index:7 bounds:1706,287,140,93 -Default +default index:7 -bounds:2,287,140,93 +bounds:2,287,140,93 \ No newline at end of file diff --git a/source/core/assets/images/mobs/boss2.atlas b/source/core/assets/images/mobs/boss2.atlas deleted file mode 100644 index 4b2867513..000000000 --- a/source/core/assets/images/mobs/boss2.atlas +++ /dev/null @@ -1,348 +0,0 @@ -boss2.png -size: 980, 651 -format: RGBA8888 -filter: Linear,Linear -repeat: none -Idle - rotate: false - xy: 0, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 140, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 280, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -default - rotate: false - xy: 280, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 420, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 560, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 700, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 840, 0 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 0, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Idle - rotate: false - xy: 140, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 280, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 420, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 560, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 700, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 840, 93 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 0, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 140, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 280, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Walk - rotate: false - xy: 420, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 560, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 700, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 840, 186 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 0, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 140, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 280, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 420, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 560, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 700, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A1 - rotate: false - xy: 840, 279 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 0, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 140, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 280, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 420, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 560, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Hurt - rotate: false - xy: 700, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 840, 372 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 0, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 140, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 280, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 420, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 560, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -boss_death - rotate: false - xy: 700, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Charging - rotate: false - xy: 840, 465 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Charging - rotate: false - xy: 0, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Charging - rotate: false - xy: 140, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Charging - rotate: false - xy: 280, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -Charging - rotate: false - xy: 420, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A2 - rotate: false - xy: 560, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 -A2 - rotate: false - xy: 700, 558 - size: 140, 93 - orig: 140, 93 - offset: 0, 0 - index: -1 diff --git a/source/core/assets/images/mobs/boss2.png b/source/core/assets/images/mobs/boss2.png deleted file mode 100644 index a9f7d1d816b3ba6a7973bb233c6f0680cbae4190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45854 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 {} + } + } + /** + * Changes the state of patrick + * @param state state to be changed to + */ + private void changeState(PatrickState state) { + prevState = this.state; + this.state = state; } /** @@ -55,9 +73,7 @@ private void animate() { } switch (state) { - case IDLE -> { - - } + case IDLE -> patrick.getEvents().trigger("Patrick_Attack"); default -> logger.debug("Patrick animation {state} not found"); } prevState = state; diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index a262b39ee..001bc9c89 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -78,13 +78,13 @@ public static Entity createPatrickBoss() { // Animation addition AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService().getAsset("images/mobboss/patrick.atlas", TextureAtlas.class)); - animator.addAnimation("Patrick_Attack", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Cast", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Death", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Hurt", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Idle", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Spell", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("Patrick_Walk", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_attack", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_cast", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_death", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_hurt", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_idle", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("patrick_spell", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_walk", 0.2f, Animation.PlayMode.LOOP); // AI task addition AITaskComponent aiTaskComponent = new AITaskComponent() diff --git a/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java index d9e43caaf..d77ff1d1d 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java @@ -2,6 +2,7 @@ import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.components.CombatStatsComponent; +import com.csse3200.game.components.TouchAttackComponent; import com.csse3200.game.components.player.InventoryComponent; import com.csse3200.game.components.player.PlayerActions; import com.csse3200.game.components.player.PlayerStatsDisplay; @@ -43,7 +44,8 @@ public static Entity createPlayer() { .addComponent(new TextureRenderComponent("images/box_boy_leaf.png")) .addComponent(new PhysicsComponent()) .addComponent(new ColliderComponent()) - .addComponent(new HitboxComponent().setLayer(PhysicsLayer.ENGINEER)) + .addComponent(new TouchAttackComponent(PhysicsLayer.NPC)) + .addComponent(new HitboxComponent().setLayer(PhysicsLayer.HUMANS)) .addComponent(new PlayerActions()) .addComponent(new CombatStatsComponent(1000, 5000)) .addComponent(new InventoryComponent(stats.gold)) From 9edc02fa4c6d4c69c8bad0cd26572520ae755fef Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sat, 23 Sep 2023 22:38:32 +1000 Subject: [PATCH 05/29] created new teleport task for patrick but is untested any may not work --- .../csse3200/game/areas/ForestGameArea.java | 2 +- .../tasks/bosstask/DemonBossTask.java | 5 +- .../tasks/bosstask/PatrickTeleportTask.java | 67 +++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 6b7c27dba..3919c9def 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -257,7 +257,7 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); spawnDemonBoss(); - spawnPatrick(); + //spawnPatrick(); //mobBoss1 = spawnMobBoss1(); // startWaveTimer(); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index ee4ad99d2..cb94e4eca 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -145,10 +145,9 @@ public void update() { changeState(DemonState.TRANSFORM_REVERSE); demon.getComponent(CombatStatsComponent.class).addHealth(100); deathCounter += 1; + } else if (health <= 0 && deathCounter == 1) { + changeState(DemonState.TRANSFORM); } -// else if (health <= 0 && deathCounter == 1) { -// changeState(DemonState.TRANSFORM); -// } // detect half health if (health <= demon.getComponent(CombatStatsComponent.class).getMaxHealth() / 2 && diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java new file mode 100644 index 000000000..0e77de3dc --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java @@ -0,0 +1,67 @@ +package com.csse3200.game.components.tasks.bosstask; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.components.tasks.MovementTask; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PatrickTeleportTask extends DefaultTask { + private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); + private Entity entity; + private Vector2 location; + private boolean isCasting = false; + private PatrickState state; + private AnimationRenderComponent animation; + private Status status; + private enum PatrickState { + CAST, APPEAR, SPELL + } + + public PatrickTeleportTask(Entity entity, Vector2 location) { + this.entity = entity; + this.location = location; + } + + @Override + public void start() { + super.start(); + animation = owner.getEntity().getComponent(AnimationRenderComponent.class); + owner.getEntity().getEvents().trigger("patrick_cast"); + state = PatrickState.CAST; + status = Status.ACTIVE; + } + + @Override + public void update() { + switch (state) { + case CAST -> { + if (animation.isFinished()) { + ServiceLocator.getEntityService().unregister(entity); + owner.getEntity().getEvents().trigger("patrick_spell"); + state = PatrickState.SPELL; + } + } + case SPELL -> { + if (animation.isFinished()) { + ServiceLocator.getEntityService().register(entity); + owner.getEntity().getEvents().trigger("patrick_appear"); + state = PatrickState.APPEAR; + } + } + case APPEAR -> { + if (animation.isFinished()) { + status = Status.FINISHED; + } + } + } + } + + @Override + public Status getStatus() { + return status; + } +} From 4a48156e0e42cc50fcda355e421620908587733d Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sat, 23 Sep 2023 23:03:01 +1000 Subject: [PATCH 06/29] Removed registering and unregistering patrick during teleport task and just made him teleport and reset his health --- .../com/csse3200/game/areas/ForestGameArea.java | 2 +- .../components/tasks/bosstask/DemonBossTask.java | 1 + .../tasks/bosstask/PatrickTeleportTask.java | 13 +++++++------ .../game/entities/factories/MobBossFactory.java | 5 ++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 3919c9def..3065ad413 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -407,7 +407,7 @@ private void spawnDemonBoss() { } private void spawnPatrick() { - Entity patrick = MobBossFactory.createPatrickBoss(); + Entity patrick = MobBossFactory.createPatrickBoss(2500); spawnEntityAt(patrick, new GridPoint2(19, 3), true, false); } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index cb94e4eca..ee996da5f 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -104,6 +104,7 @@ public void start() { @Override public void run() { changeState(DemonState.TRANSFORM); + animate(); startFlag = true; } }, 0.1f); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java index 0e77de3dc..87b473959 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java @@ -2,21 +2,21 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.rendering.AnimationRenderComponent; -import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PatrickTeleportTask extends DefaultTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private Entity entity; - private Vector2 location; - private boolean isCasting = false; + private final Entity entity; + private final Vector2 location; private PatrickState state; private AnimationRenderComponent animation; private Status status; + private int health; private enum PatrickState { CAST, APPEAR, SPELL } @@ -33,6 +33,7 @@ public void start() { owner.getEntity().getEvents().trigger("patrick_cast"); state = PatrickState.CAST; status = Status.ACTIVE; + health = owner.getEntity().getComponent(CombatStatsComponent.class).getHealth(); } @Override @@ -40,20 +41,20 @@ public void update() { switch (state) { case CAST -> { if (animation.isFinished()) { - ServiceLocator.getEntityService().unregister(entity); + entity.setPosition(location); owner.getEntity().getEvents().trigger("patrick_spell"); state = PatrickState.SPELL; } } case SPELL -> { if (animation.isFinished()) { - ServiceLocator.getEntityService().register(entity); owner.getEntity().getEvents().trigger("patrick_appear"); state = PatrickState.APPEAR; } } case APPEAR -> { if (animation.isFinished()) { + entity.getComponent(CombatStatsComponent.class).setHealth(health); status = Status.FINISHED; } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index 001bc9c89..9c300629d 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -26,7 +26,6 @@ public class MobBossFactory { private static final int BOSS_MOB_AGRO_RANGE = 10; private static final int DEMON_HEALTH = 5000; private static final int DEMON_ATTACK = 0; - private static final int PATRICK_HEALTH = 2500; private static final int PATRICK_ATTACK = 0; // Create Demon Boss @@ -71,7 +70,7 @@ public static Entity createDemonBoss() { return demon; } - public static Entity createPatrickBoss() { + public static Entity createPatrickBoss(int health) { MobBossConfigs config = configs.MobBoss; Entity demon = createBaseBoss(); @@ -95,7 +94,7 @@ public static Entity createPatrickBoss() { .addComponent(animator) .addComponent(new PatrickAnimationController()) .addComponent(aiTaskComponent) - .addComponent(new CombatStatsComponent(PATRICK_HEALTH, PATRICK_ATTACK)); + .addComponent(new CombatStatsComponent(health, PATRICK_ATTACK)); // Scale demon demon.getComponent(AnimationRenderComponent.class).scaleEntity(); From 2869a78c7193cea041817eb9335a56d479da08ef Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 21:25:36 +1000 Subject: [PATCH 07/29] implemented range attack which fires 3 projectiles of random effects then changes state back to cast --- .../csse3200/game/areas/ForestGameArea.java | 2 +- .../tasks/bosstask/PatrickTask.java | 62 +++++++++++++++++-- .../entities/factories/MobBossFactory.java | 2 +- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 3065ad413..39f361c8d 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -257,7 +257,7 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); spawnDemonBoss(); - //spawnPatrick(); + spawnPatrick(); //mobBoss1 = spawnMobBoss1(); // startWaveTimer(); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 18dd73135..56ec516d8 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -1,10 +1,15 @@ package com.csse3200.game.components.tasks.bosstask; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.components.ProjectileEffects; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsEngine; +import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.GameTime; @@ -27,8 +32,13 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private PatrickState prevState; private AnimationRenderComponent animation; private Entity patrick; + private int shotsFired; + + // Flags + private boolean meleeFlag = false; + private boolean rangeFlag = false; private enum PatrickState { - IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL + IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL, APPEAR } public PatrickTask() { @@ -43,14 +53,38 @@ public void start() { animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation currentPos = owner.getEntity().getPosition(); // get current position patrick.getComponent(PhysicsMovementComponent.class).setSpeed(PATRICK_SPEED); // set speed - changeState(PatrickState.IDLE); + changeState(PatrickState.APPEAR); } @Override public void update() { animate(); switch (state) { - case IDLE -> {} + case APPEAR -> { + if (animation.isFinished()) { + if (rangeFlag) { + changeState(PatrickState.IDLE); + } else if (meleeFlag) { + changeState(PatrickState.ATTACK); + } + } + } + case IDLE -> { + if (animation.isFinished()) { + if (shotsFired == 3) { + shotsFired = 0; + changeState(PatrickState.CAST); + } + Entity projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.HUMANS, + new Vector2(0f, patrick.getPosition().y), new Vector2(2, 2), + getEffect(), false); + projectile.setPosition(patrick.getPosition().x, patrick.getPosition().y); + projectile.setScale(-1f, 1f); + ServiceLocator.getEntityService().register(projectile); + changeState(PatrickState.IDLE); + shotsFired++; + } + } } } @@ -73,7 +107,9 @@ private void animate() { } switch (state) { - case IDLE -> patrick.getEvents().trigger("Patrick_Attack"); + case IDLE -> { + + } default -> logger.debug("Patrick animation {state} not found"); } prevState = state; @@ -83,4 +119,22 @@ private void animate() { public int getPriority() { return PRIORITY; } + + private ProjectileEffects getEffect() { + int randomNumber = MathUtils.random(0, 3); + switch (randomNumber) { + case 1 -> { + return ProjectileEffects.BURN; + } + case 2 -> { + return ProjectileEffects.SLOW; + } + case 3 -> { + return ProjectileEffects.STUN; + } + default -> { + return ProjectileEffects.FIREBALL; + } + } + } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index 9c300629d..e7d01b135 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -81,7 +81,7 @@ public static Entity createPatrickBoss(int health) { animator.addAnimation("patrick_cast", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_death", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_hurt", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("patrick_idle", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("patrick_idle", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_spell", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_walk", 0.2f, Animation.PlayMode.LOOP); From b7a47920b2cd383137b03976abf84ea4f9b12617 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 21:29:08 +1000 Subject: [PATCH 08/29] after appearing, patrick can change into 3 different states: cast, attack, idle(range) cast is the dictating state --- .../game/components/tasks/bosstask/PatrickTask.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 56ec516d8..b17f1664d 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -37,6 +37,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { // Flags private boolean meleeFlag = false; private boolean rangeFlag = false; + private boolean spawnFlag = false; private enum PatrickState { IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL, APPEAR } @@ -53,6 +54,7 @@ public void start() { animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation currentPos = owner.getEntity().getPosition(); // get current position patrick.getComponent(PhysicsMovementComponent.class).setSpeed(PATRICK_SPEED); // set speed + spawnFlag = true; changeState(PatrickState.APPEAR); } @@ -62,12 +64,17 @@ public void update() { switch (state) { case APPEAR -> { if (animation.isFinished()) { - if (rangeFlag) { - changeState(PatrickState.IDLE); + if (spawnFlag) { + changeState(PatrickState.CAST); } else if (meleeFlag) { changeState(PatrickState.ATTACK); + } else if (rangeFlag) { + changeState(PatrickState.IDLE); } } + } + case CAST -> { + } case IDLE -> { if (animation.isFinished()) { From 12f02bde6761ffec8c039fbc8d3f1b882fccc016 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 21:48:07 +1000 Subject: [PATCH 09/29] added new method to EntityService which returns the closest entity of PhysicsLayer HUMANS --- .../tasks/bosstask/PatrickTask.java | 31 ++++++++++++++++++- .../csse3200/game/entities/EntityService.java | 31 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index b17f1664d..1b1f10b9f 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -22,6 +22,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { // Constants private static final int PRIORITY = 3; private static final Vector2 PATRICK_SPEED = new Vector2(1f, 1f); + private static final float MAX_RADIUS = 20f; // Private variables private static final Logger logger = LoggerFactory.getLogger(PatrickTask.class); @@ -38,6 +39,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private boolean meleeFlag = false; private boolean rangeFlag = false; private boolean spawnFlag = false; + private boolean attackFlag = false; private enum PatrickState { IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL, APPEAR } @@ -66,15 +68,23 @@ public void update() { if (animation.isFinished()) { if (spawnFlag) { changeState(PatrickState.CAST); + spawnFlag = false; } else if (meleeFlag) { changeState(PatrickState.ATTACK); + meleeFlag = false; } else if (rangeFlag) { changeState(PatrickState.IDLE); + rangeFlag = false; } } } case CAST -> { - + if (animation.isFinished()) { + if (attackFlag) { + PatrickTeleportTask teleportTask = new PatrickTeleportTask(patrick, + getHuman()); + } + } } case IDLE -> { if (animation.isFinished()) { @@ -144,4 +154,23 @@ private ProjectileEffects getEffect() { } } } + + private Entity getHuman() { + Array nearbyEntities = ServiceLocator.getEntityService(). + getNearbyEntities(patrick, MAX_RADIUS); + Entity human = null; + float closestDistance = MAX_RADIUS; + + for (int i = 0; i < nearbyEntities.size; i++) { + Entity targetEntity = nearbyEntities.get(i); + Vector2 targetPosition = targetEntity.getPosition(); + float distance = currentPos.dst(targetPosition); + + if (distance < closestDistance) { + closestEntity = targetEntity; + closestDistance = distance; + } + } + return human; + } } diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index bafc5bfde..3667f5a0f 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -7,6 +7,8 @@ import com.badlogic.gdx.utils.Array; import com.csse3200.game.components.npc.DropComponent; import com.csse3200.game.input.DropInputComponent; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.rendering.RenderService; import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; @@ -26,6 +28,7 @@ public class EntityService { private static final Logger logger = LoggerFactory.getLogger(EntityService.class); private static final int INITIAL_CAPACITY = 16; private final Array entities = new Array<>(false, INITIAL_CAPACITY); + private static final float MAX_RADIUS = 20f; public static void removeEntity(Entity clickedEntity) { clickedEntity.dispose(); @@ -100,6 +103,34 @@ public Array getNearbyEntities(Entity source, float radius) { } return nearbyEntities; } + + public Entity getClosestHuman(Entity source) { + Entity closestHuman = null; + Vector2 sourcePos = source.getPosition(); + float closestDistance = MAX_RADIUS; + + for (int i = 0; i < getEntities().size; i++) { + Entity targetEntity = getEntities().get(i); + + // check if target is human + HitboxComponent targetHitbox = targetEntity.getComponent(HitboxComponent.class); + if (targetHitbox == null) { + break; + } + if (!PhysicsLayer.contains(PhysicsLayer.HUMANS, targetHitbox.getLayer())) { + break; + } + + // check how close target is to source + Vector2 targetPosition = targetEntity.getPosition(); + float distance = sourcePos.dst(targetPosition); + if (distance < closestDistance) { + closestHuman = targetEntity; + closestDistance = distance; + } + } + return closestHuman; + } public Entity getEntityAtPosition(float x, float y) { entities.sort(Comparator.comparingInt(Entity::getLayer)); From 8a005f7bbff87bd80b48e63ebb5bcf738fa299b8 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 21:56:30 +1000 Subject: [PATCH 10/29] added attack sequence which teleports patrick to closest human and changes state to attack --- .../tasks/bosstask/PatrickTask.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 1b1f10b9f..8967532f2 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -2,7 +2,6 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.ProjectileEffects; @@ -34,6 +33,8 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private AnimationRenderComponent animation; private Entity patrick; private int shotsFired; + private PatrickTeleportTask teleportTask; + private Vector2 initialPos; // Flags private boolean meleeFlag = false; @@ -63,6 +64,11 @@ public void start() { @Override public void update() { animate(); + + if (teleportTask.getStatus().equals(Status.FINISHED)) { + changeState(PatrickState.APPEAR); + } + switch (state) { case APPEAR -> { if (animation.isFinished()) { @@ -81,8 +87,10 @@ public void update() { case CAST -> { if (animation.isFinished()) { if (attackFlag) { - PatrickTeleportTask teleportTask = new PatrickTeleportTask(patrick, - getHuman()); + initialPos = patrick.getPosition(); + teleport(ServiceLocator.getEntityService().getClosestHuman(patrick).getPosition()); + } else { + teleport(initialPos); } } } @@ -155,22 +163,7 @@ private ProjectileEffects getEffect() { } } - private Entity getHuman() { - Array nearbyEntities = ServiceLocator.getEntityService(). - getNearbyEntities(patrick, MAX_RADIUS); - Entity human = null; - float closestDistance = MAX_RADIUS; - - for (int i = 0; i < nearbyEntities.size; i++) { - Entity targetEntity = nearbyEntities.get(i); - Vector2 targetPosition = targetEntity.getPosition(); - float distance = currentPos.dst(targetPosition); - - if (distance < closestDistance) { - closestEntity = targetEntity; - closestDistance = distance; - } - } - return human; + private void teleport(Vector2 pos) { + teleportTask = new PatrickTeleportTask(patrick, pos); } } From 3e30cff0bf21c01d02dd75d28d0332136856e783 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:09:49 +1000 Subject: [PATCH 11/29] removed cast state because its handled by teleport task. added melee attack method which deals damage to target and teleports back to original position --- .../tasks/bosstask/PatrickTask.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 8967532f2..4ad203f11 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.ProjectileEffects; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.ProjectileFactory; @@ -22,6 +23,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private static final int PRIORITY = 3; private static final Vector2 PATRICK_SPEED = new Vector2(1f, 1f); private static final float MAX_RADIUS = 20f; + private static final int ATTACK_DAMAGE = 100; // Private variables private static final Logger logger = LoggerFactory.getLogger(PatrickTask.class); @@ -35,12 +37,12 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private int shotsFired; private PatrickTeleportTask teleportTask; private Vector2 initialPos; + private Entity meleeTarget; // Flags private boolean meleeFlag = false; private boolean rangeFlag = false; private boolean spawnFlag = false; - private boolean attackFlag = false; private enum PatrickState { IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL, APPEAR } @@ -73,7 +75,8 @@ public void update() { case APPEAR -> { if (animation.isFinished()) { if (spawnFlag) { - changeState(PatrickState.CAST); + meleeAttack(); + meleeFlag = true; spawnFlag = false; } else if (meleeFlag) { changeState(PatrickState.ATTACK); @@ -84,16 +87,6 @@ public void update() { } } } - case CAST -> { - if (animation.isFinished()) { - if (attackFlag) { - initialPos = patrick.getPosition(); - teleport(ServiceLocator.getEntityService().getClosestHuman(patrick).getPosition()); - } else { - teleport(initialPos); - } - } - } case IDLE -> { if (animation.isFinished()) { if (shotsFired == 3) { @@ -110,6 +103,12 @@ public void update() { shotsFired++; } } + case ATTACK -> { + if (animation.isFinished()) { + meleeTarget.getComponent(CombatStatsComponent.class).hit(ATTACK_DAMAGE); + teleport(initialPos); + } + } } } @@ -166,4 +165,10 @@ private ProjectileEffects getEffect() { private void teleport(Vector2 pos) { teleportTask = new PatrickTeleportTask(patrick, pos); } + + private void meleeAttack() { + initialPos = patrick.getPosition(); + meleeTarget = ServiceLocator.getEntityService().getClosestHuman(patrick); + teleport(meleeTarget.getPosition()); + } } From 51e82de5051230906d22c6a33f6aeab6ba886a18 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:15:38 +1000 Subject: [PATCH 12/29] cleaned up code and got fixed remaining cast state call in rangeAttack to fully utilise teleport method --- .../tasks/bosstask/PatrickTask.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 4ad203f11..fdb7333a9 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -44,7 +44,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private boolean rangeFlag = false; private boolean spawnFlag = false; private enum PatrickState { - IDLE, WALK, ATTACK, HURT, DEATH, CAST, SPELL, APPEAR + IDLE, WALK, ATTACK, HURT, DEATH, SPELL, APPEAR } public PatrickTask() { @@ -89,18 +89,7 @@ public void update() { } case IDLE -> { if (animation.isFinished()) { - if (shotsFired == 3) { - shotsFired = 0; - changeState(PatrickState.CAST); - } - Entity projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.HUMANS, - new Vector2(0f, patrick.getPosition().y), new Vector2(2, 2), - getEffect(), false); - projectile.setPosition(patrick.getPosition().x, patrick.getPosition().y); - projectile.setScale(-1f, 1f); - ServiceLocator.getEntityService().register(projectile); - changeState(PatrickState.IDLE); - shotsFired++; + rangeAttack(); } } case ATTACK -> { @@ -171,4 +160,20 @@ private void meleeAttack() { meleeTarget = ServiceLocator.getEntityService().getClosestHuman(patrick); teleport(meleeTarget.getPosition()); } + + private void rangeAttack() { + if (shotsFired == 3) { + shotsFired = 0; + meleeAttack(); + meleeFlag = true; + } + Entity projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.HUMANS, + new Vector2(0f, patrick.getPosition().y), new Vector2(2, 2), + getEffect(), false); + projectile.setPosition(patrick.getPosition().x, patrick.getPosition().y); + projectile.setScale(-1f, 1f); + ServiceLocator.getEntityService().register(projectile); + changeState(PatrickState.IDLE); + shotsFired++; + } } From 3d2ae2ad6aa07043737fc1e44418f23c5ed9bc7d Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:21:51 +1000 Subject: [PATCH 13/29] APPEAR state in PatrickTask is just for carrying out the sequence because the teleport task takes care of the cast, appear, spell states, functionality has not yet been tested --- .../tasks/bosstask/PatrickTask.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index fdb7333a9..3fd0dab39 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -73,18 +73,16 @@ public void update() { switch (state) { case APPEAR -> { - if (animation.isFinished()) { - if (spawnFlag) { - meleeAttack(); - meleeFlag = true; - spawnFlag = false; - } else if (meleeFlag) { - changeState(PatrickState.ATTACK); - meleeFlag = false; - } else if (rangeFlag) { - changeState(PatrickState.IDLE); - rangeFlag = false; - } + if (spawnFlag) { + meleeAttack(); + meleeFlag = true; + spawnFlag = false; + } else if (meleeFlag) { + changeState(PatrickState.ATTACK); + meleeFlag = false; + } else if (rangeFlag) { + changeState(PatrickState.IDLE); + rangeFlag = false; } } case IDLE -> { @@ -159,6 +157,7 @@ private void meleeAttack() { initialPos = patrick.getPosition(); meleeTarget = ServiceLocator.getEntityService().getClosestHuman(patrick); teleport(meleeTarget.getPosition()); + changeState(PatrickState.ATTACK); } private void rangeAttack() { From b8c71a61dd91eb634c8f4eb5937399ed6d4fc224 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:22:24 +1000 Subject: [PATCH 14/29] removed patrick from being spawned in forest game area because im pushing --- .../core/src/main/com/csse3200/game/areas/ForestGameArea.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 39f361c8d..3065ad413 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -257,7 +257,7 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); spawnDemonBoss(); - spawnPatrick(); + //spawnPatrick(); //mobBoss1 = spawnMobBoss1(); // startWaveTimer(); From b65fb74ec9c9493e6c644eba114d315e4fabc356 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:32:01 +1000 Subject: [PATCH 15/29] changed range attack functionality so that in between shots, patrick will teleport to random pos --- .../game/components/tasks/bosstask/PatrickTask.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 3fd0dab39..558220197 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -161,18 +161,25 @@ private void meleeAttack() { } private void rangeAttack() { + // detect if 3 shots have been fired if (shotsFired == 3) { shotsFired = 0; - meleeAttack(); - meleeFlag = true; + rangeFlag = false; + spawnFlag = true; } + + // spawn random projectile Entity projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.HUMANS, new Vector2(0f, patrick.getPosition().y), new Vector2(2, 2), getEffect(), false); projectile.setPosition(patrick.getPosition().x, patrick.getPosition().y); projectile.setScale(-1f, 1f); ServiceLocator.getEntityService().register(projectile); - changeState(PatrickState.IDLE); shotsFired++; + + // teleport to random position + float randomX = MathUtils.random(10f, 19f); + float randomY = MathUtils.random(1f, 6f); + teleport(new Vector2(randomX, randomY)); } } From 602df84230bec59c6d00ab753e0be70a343b359e Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:44:28 +1000 Subject: [PATCH 16/29] added new half health sequence --- .../tasks/bosstask/PatrickTask.java | 66 +++++++++++++++---- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 558220197..0446b10b8 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -24,6 +24,11 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private static final Vector2 PATRICK_SPEED = new Vector2(1f, 1f); private static final float MAX_RADIUS = 20f; private static final int ATTACK_DAMAGE = 100; + private static final float RANGE_MIN_X = 10f; + private static final float RANGE_MAX_X = 18f; + private static final float RANGE_MIN_Y = 1f; + private static final float RANGE_MAX_Y = 6f; + private static final int HALF_HEALTH_ATTACKS = 5; // Private variables private static final Logger logger = LoggerFactory.getLogger(PatrickTask.class); @@ -43,6 +48,7 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private boolean meleeFlag = false; private boolean rangeFlag = false; private boolean spawnFlag = false; + private boolean halfHealthFlag = false; private enum PatrickState { IDLE, WALK, ATTACK, HURT, DEATH, SPELL, APPEAR } @@ -66,11 +72,22 @@ public void start() { @Override public void update() { animate(); + int health = patrick.getComponent(CombatStatsComponent.class).getHealth(); + // check if patrick has just teleported if (teleportTask.getStatus().equals(Status.FINISHED)) { changeState(PatrickState.APPEAR); } + // handle half health special ability + // detect half health + if (health <= patrick.getComponent(CombatStatsComponent.class).getMaxHealth() / 2 && + !halfHealthFlag) { + halfHealth(); + halfHealthFlag = true; + } + + // handle state switches switch (state) { case APPEAR -> { if (spawnFlag) { @@ -92,6 +109,10 @@ public void update() { } case ATTACK -> { if (animation.isFinished()) { + if (halfHealthFlag) { + + break; + } meleeTarget.getComponent(CombatStatsComponent.class).hit(ATTACK_DAMAGE); teleport(initialPos); } @@ -160,26 +181,49 @@ private void meleeAttack() { changeState(PatrickState.ATTACK); } - private void rangeAttack() { - // detect if 3 shots have been fired - if (shotsFired == 3) { - shotsFired = 0; - rangeFlag = false; - spawnFlag = true; - } - + private void spawnRandProjectile(Vector2 destination) { // spawn random projectile Entity projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.HUMANS, - new Vector2(0f, patrick.getPosition().y), new Vector2(2, 2), + destination, new Vector2(2, 2), getEffect(), false); projectile.setPosition(patrick.getPosition().x, patrick.getPosition().y); projectile.setScale(-1f, 1f); ServiceLocator.getEntityService().register(projectile); shotsFired++; + } + private void randomTeleport() { // teleport to random position - float randomX = MathUtils.random(10f, 19f); - float randomY = MathUtils.random(1f, 6f); + float randomX = MathUtils.random(RANGE_MIN_X, RANGE_MAX_X); + float randomY = MathUtils.random(RANGE_MIN_Y, RANGE_MAX_Y); teleport(new Vector2(randomX, randomY)); } + + private void rangeAttack() { + // detect if 3 shots have been fired + if (shotsFired == 3) { + shotsFired = 0; + rangeFlag = false; + spawnFlag = true; + } + randomTeleport(); + spawnRandProjectile(new Vector2(0f, patrick.getPosition().y)); + } + + private void halfHealth() { + float startAngle = (float) Math.toRadians(135); + float endAngle = (float) Math.toRadians(225); + float angleIncrement = (endAngle - startAngle) / (HALF_HEALTH_ATTACKS - 1); + + for (int i = 0; i < HALF_HEALTH_ATTACKS; i++) { + randomTeleport(); + + // calculate unit vectors for projectiles + float currentAngle = startAngle + i * angleIncrement; + float x = MathUtils.cos(currentAngle) * 20; + float y = MathUtils.sin(currentAngle) * 20; + Vector2 destination = new Vector2(x, y); + spawnRandProjectile(destination); + } + } } From 1d75bffeb52e533ea9c65ba62dcd7e1cd84cec89 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:47:00 +1000 Subject: [PATCH 17/29] added end to sequence --- .../csse3200/game/components/tasks/bosstask/PatrickTask.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 0446b10b8..e2a5efa1d 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -225,5 +225,8 @@ private void halfHealth() { Vector2 destination = new Vector2(x, y); spawnRandProjectile(destination); } + if (shotsFired == HALF_HEALTH_ATTACKS) { + meleeFlag = true; + } } } From 606d89b5325b2f6db777c57fa8d5399a81eaa563 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:26:17 +1000 Subject: [PATCH 18/29] patrick atlas wasn't being recognised cos forestgamearea was reading from mob file instead of mobboss. added animation triggers to PatrickTask --- source/core/assets/images/mobboss/patrick.atlas | 4 ++-- .../src/main/com/csse3200/game/areas/ForestGameArea.java | 4 ++-- .../game/components/tasks/bosstask/PatrickTask.java | 9 ++++++--- .../csse3200/game/entities/factories/MobBossFactory.java | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/source/core/assets/images/mobboss/patrick.atlas b/source/core/assets/images/mobboss/patrick.atlas index 3de3867ca..6e1e1df86 100644 --- a/source/core/assets/images/mobboss/patrick.atlas +++ b/source/core/assets/images/mobboss/patrick.atlas @@ -194,5 +194,5 @@ patrick_walk index:7 bounds:1706,287,140,93 default -index:7 -bounds:2,287,140,93 \ No newline at end of file +index:2 +bounds:1848,382,140,93 \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 3065ad413..90c0e41dc 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -109,7 +109,7 @@ public class ForestGameArea extends GameArea { "images/mobboss/demon.png", "images/mobboss/demon2.png", "images/mobs/fire_worm.png", - "images/mobs/patrick.png" + "images/mobboss/patrick.png" }; private static final String[] forestTextureAtlases = { "images/economy/econ-tower.atlas", @@ -145,7 +145,7 @@ public class ForestGameArea extends GameArea { "images/mobboss/demon.atlas", "images/mobs/fire_worm.atlas", "images/mobs/dragon_knight.atlas", - "images/mobs/patrick.atlas" + "images/mobboss/patrick.atlas" }; private static final String[] forestSounds = { "sounds/Impact4.ogg", diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index e2a5efa1d..2740396af 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -139,9 +139,12 @@ private void animate() { } switch (state) { - case IDLE -> { - - } + case IDLE -> owner.getEntity().getEvents().trigger("patrick_idle"); + case WALK -> owner.getEntity().getEvents().trigger("patrick_walk"); + case HURT -> owner.getEntity().getEvents().trigger("patrick_hurt"); + case SPELL -> owner.getEntity().getEvents().trigger("patrick_spell"); + case APPEAR -> owner.getEntity().getEvents().trigger("patrick_death"); + case ATTACK -> owner.getEntity().getEvents().trigger("patrick_attack"); default -> logger.debug("Patrick animation {state} not found"); } prevState = state; diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index e7d01b135..2d7afee83 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -79,7 +79,7 @@ public static Entity createPatrickBoss(int health) { ServiceLocator.getResourceService().getAsset("images/mobboss/patrick.atlas", TextureAtlas.class)); animator.addAnimation("patrick_attack", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_cast", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("patrick_death", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("patrick_death", 0.2f, Animation.PlayMode.REVERSED); animator.addAnimation("patrick_hurt", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_idle", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("patrick_spell", 0.2f, Animation.PlayMode.NORMAL); From c0e9f6c1aba8fca751ec17253b95515a473551f2 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:56:10 +1000 Subject: [PATCH 19/29] removed transform reverse from demon atlas because it wasnt working --- source/core/assets/images/mobboss/demon.atlas | 98 +------------------ .../csse3200/game/areas/ForestGameArea.java | 5 +- .../tasks/bosstask/PatrickTask.java | 29 +++++- .../csse3200/game/entities/EntityService.java | 2 +- .../entities/factories/MobBossFactory.java | 14 ++- 5 files changed, 41 insertions(+), 107 deletions(-) diff --git a/source/core/assets/images/mobboss/demon.atlas b/source/core/assets/images/mobboss/demon.atlas index 612e757cc..93f1e2e6f 100644 --- a/source/core/assets/images/mobboss/demon.atlas +++ b/source/core/assets/images/mobboss/demon.atlas @@ -298,60 +298,6 @@ bounds:1440,320,288,160 transform index:6 bounds:1440,160,288,160 -transform_reverse -index:2 -bounds:288,1280,288,160 -transform_reverse -index:31 -bounds:576,1440,288,160 -transform_reverse -index:18 -bounds:864,1600,288,160 -transform_reverse -index:10 -bounds:288,1120,288,160 -transform_reverse -index:23 -bounds:1152,1600,288,160 -transform_reverse -index:7 -bounds:288,960,288,160 -transform_reverse -index:15 -bounds:1152,1280,288,160 -transform_reverse -index:28 -bounds:0,480,288,160 -transform_reverse -index:20 -bounds:1728,1440,288,160 -transform_reverse -index:4 -bounds:864,800,288,160 -transform_reverse -index:12 -bounds:864,640,288,160 -transform_reverse -index:25 -bounds:1728,1120,288,160 -transform_reverse -index:9 -bounds:0,0,288,160 -transform_reverse -index:1 -bounds:1728,800,288,160 -transform_reverse -index:30 -bounds:576,0,288,160 -transform_reverse -index:17 -bounds:864,160,288,160 -transform_reverse -index:22 -bounds:1440,320,288,160 -transform_reverse -index:6 -bounds:1440,160,288,160 demon2.png size:2048,2048 @@ -572,48 +518,6 @@ bounds:1152,480,288,160 transform index:26 bounds:576,0,288,160 -transform_reverse -index:14 -bounds:576,1760,288,160 -transform_reverse -index:27 -bounds:288,1440,288,160 -transform_reverse -index:3 -bounds:1440,1760,288,160 -transform_reverse -index:32 -bounds:0,800,288,160 -transform_reverse -index:19 -bounds:576,1120,288,160 -transform_reverse -index:11 -bounds:288,800,288,160 -transform_reverse -index:24 -bounds:1152,1280,288,160 -transform_reverse -index:8 -bounds:1728,1600,288,160 -transform_reverse -index:16 -bounds:576,640,288,160 -transform_reverse -index:29 -bounds:1152,960,288,160 -transform_reverse -index:21 -bounds:1440,960,288,160 -transform_reverse -index:5 -bounds:288,160,288,160 -transform_reverse -index:13 -bounds:1152,480,288,160 -transform_reverse -index:26 -bounds:576,0,288,160 default -index:3 +index:29 bounds:864,1760,288,160 diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 90c0e41dc..94b7cd016 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -257,7 +257,7 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); spawnDemonBoss(); - //spawnPatrick(); +// spawnPatrick(); //mobBoss1 = spawnMobBoss1(); // startWaveTimer(); @@ -266,7 +266,7 @@ public void create() { // spawnTNTTower(); // // spawnGapScanners(); -// spawnDroidTower(); + spawnDroidTower(); // // mobBoss2 = spawnMobBoss2(); @@ -684,6 +684,7 @@ private void spawnDroidTower() { for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); Entity weaponTower = TowerFactory.createDroidTower(); + System.out.println(weaponTower); spawnEntityAt(weaponTower, randomPos, true, true); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 2740396af..ba62aafc1 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -2,6 +2,7 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Timer; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.CombatStatsComponent; @@ -49,6 +50,8 @@ public class PatrickTask extends DefaultTask implements PriorityTask { private boolean rangeFlag = false; private boolean spawnFlag = false; private boolean halfHealthFlag = false; + private boolean teleportFlag = false; + private boolean startFlag = false; private enum PatrickState { IDLE, WALK, ATTACK, HURT, DEATH, SPELL, APPEAR } @@ -65,21 +68,34 @@ public void start() { animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation currentPos = owner.getEntity().getPosition(); // get current position patrick.getComponent(PhysicsMovementComponent.class).setSpeed(PATRICK_SPEED); // set speed - spawnFlag = true; - changeState(PatrickState.APPEAR); + + // give game time to load + Timer.schedule(new Timer.Task() { + @Override + public void run() { + changeState(PatrickState.APPEAR); + animate(); + startFlag = true; + spawnFlag = true; + } + }, 0.1f); } @Override public void update() { + // give game time to load + if (!startFlag) { + return; + } animate(); int health = patrick.getComponent(CombatStatsComponent.class).getHealth(); // check if patrick has just teleported - if (teleportTask.getStatus().equals(Status.FINISHED)) { + if (teleportFlag && teleportTask.getStatus().equals(Status.FINISHED)) { changeState(PatrickState.APPEAR); + teleportFlag = false; } - // handle half health special ability // detect half health if (health <= patrick.getComponent(CombatStatsComponent.class).getMaxHealth() / 2 && !halfHealthFlag) { @@ -92,7 +108,6 @@ public void update() { case APPEAR -> { if (spawnFlag) { meleeAttack(); - meleeFlag = true; spawnFlag = false; } else if (meleeFlag) { changeState(PatrickState.ATTACK); @@ -174,14 +189,18 @@ private ProjectileEffects getEffect() { } private void teleport(Vector2 pos) { + teleportFlag = true; teleportTask = new PatrickTeleportTask(patrick, pos); } private void meleeAttack() { initialPos = patrick.getPosition(); meleeTarget = ServiceLocator.getEntityService().getClosestHuman(patrick); + System.out.println(ServiceLocator.getEntityService().getEntities()); + System.out.println(ServiceLocator.getEntityService().getClosestHuman(patrick)); teleport(meleeTarget.getPosition()); changeState(PatrickState.ATTACK); + meleeFlag = true; } private void spawnRandProjectile(Vector2 destination) { diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index 3667f5a0f..8a7109730 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -28,7 +28,7 @@ public class EntityService { private static final Logger logger = LoggerFactory.getLogger(EntityService.class); private static final int INITIAL_CAPACITY = 16; private final Array entities = new Array<>(false, INITIAL_CAPACITY); - private static final float MAX_RADIUS = 20f; + private static final float MAX_RADIUS = 50f; public static void removeEntity(Entity clickedEntity) { clickedEntity.dispose(); diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index 2d7afee83..d3f7e3e87 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -35,7 +35,8 @@ public static Entity createDemonBoss() { // Animation addition AnimationRenderComponent animator = new AnimationRenderComponent( - ServiceLocator.getResourceService().getAsset("images/mobboss/demon.atlas", TextureAtlas.class)); + ServiceLocator.getResourceService().getAsset("images/mobboss/demon.atlas", + TextureAtlas.class)); animator.addAnimation("demon_cast_spell", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("demon_cleave", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("demon_death", 0.2f, Animation.PlayMode.NORMAL); @@ -50,7 +51,6 @@ public static Entity createDemonBoss() { animator.addAnimation("projectile_idle", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("take_hit", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("transform", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("transform_reverse", 0.2f, Animation.PlayMode.REVERSED); // AI task addition AITaskComponent aiTaskComponent = new AITaskComponent() @@ -70,6 +70,16 @@ public static Entity createDemonBoss() { return demon; } + public static Entity slimeyBoy() { + Entity slimeyBoy = createBaseBoss(); + + // Animation + AnimationRenderComponent animator = new AnimationRenderComponent( + ServiceLocator.getResourceService().getAsset("images/mobboss/demon.atlas", + TextureAtlas.class)); + + } + public static Entity createPatrickBoss(int health) { MobBossConfigs config = configs.MobBoss; Entity demon = createBaseBoss(); From 329c862f3c1a06083af7265af0e9de03e59ba815 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:59:02 +1000 Subject: [PATCH 20/29] created new slimey boy entity which spawns after demon boss dies --- .../entities/factories/MobBossFactory.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index d3f7e3e87..ef8eee5d1 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -45,11 +45,6 @@ public static Entity createDemonBoss() { animator.addAnimation("demon_smash", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("demon_take_hit", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("demon_walk", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("idle", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("move", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("projectile_explosion", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("projectile_idle", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("take_hit", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("transform", 0.2f, Animation.PlayMode.NORMAL); // AI task addition @@ -77,7 +72,29 @@ public static Entity slimeyBoy() { AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService().getAsset("images/mobboss/demon.atlas", TextureAtlas.class)); + animator.addAnimation("idle", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("move", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("projectile_explosion", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("projectile_idle", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("take_hit", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("transform", 0.2f, Animation.PlayMode.REVERSED); + // AI task addition + AITaskComponent aiTaskComponent = new AITaskComponent() + .addTask(new SlimeyBoyTask()); + + // Component addition + slimeyBoy + .addComponent(animator) + .addComponent(new DemonAnimationController()) + .addComponent(aiTaskComponent) + .addComponent(new CombatStatsComponent(500, 0)); + + // Scale demon + slimeyBoy.getComponent(AnimationRenderComponent.class).scaleEntity(); + slimeyBoy.scaleHeight(5f); + slimeyBoy.scaleWidth(5f); + return slimeyBoy; } public static Entity createPatrickBoss(int health) { From 7f270506fdb8a0626ce3ca0ff449d4b8374a441f Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:09:15 +1000 Subject: [PATCH 21/29] added states and animate and change state function --- .../tasks/bosstask/DemonBossTask.java | 4 +- .../tasks/bosstask/SlimeyBoyTask.java | 74 +++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index ee996da5f..9234760c4 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -96,8 +96,8 @@ public DemonBossTask() { public void start() { super.start(); demon = owner.getEntity(); - animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation - currentPos = owner.getEntity().getPosition(); // get current position + animation = demon.getComponent(AnimationRenderComponent.class); // get animation + currentPos = demon.getPosition(); // get current position demon.getComponent(PhysicsMovementComponent.class).setSpeed(DEMON_SPEED); // set speed Timer.schedule(new Timer.Task() { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java new file mode 100644 index 000000000..e3516e467 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -0,0 +1,74 @@ +package com.csse3200.game.components.tasks.bosstask; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.physics.components.PhysicsMovementComponent; +import com.csse3200.game.rendering.AnimationRenderComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SlimeyBoyTask extends DefaultTask implements PriorityTask { + + // Constants + private static final int PRIORITY = 3; + private static final Vector2 SLIMEY_SPEED = new Vector2(0.5f, 0.5f); + + // Private variables + private static final Logger logger = LoggerFactory.getLogger(SlimeyBoyTask.class); + private Entity slimey; + private AnimationRenderComponent animation; + private Vector2 currentPos; + private SlimeState state = SlimeState.IDLE; + private SlimeState prevState; + + private enum SlimeState { + IDLE, MOVE, PROJECTILE_EXPLOSION, PROJECTILE_IDLE, TAKE_HIT, TRANSFORM + } + + @Override + public void start() { + super.start(); + slimey = owner.getEntity(); + animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation + currentPos = owner.getEntity().getPosition(); // get current position + slimey.getComponent(PhysicsMovementComponent.class).setSpeed(SLIMEY_SPEED); // set speed + changeState(SlimeState.IDLE); + } + + /** + * Changes the state of the demon + * @param state state to be changed to + */ + private void changeState(SlimeState state) { + prevState = this.state; + this.state = state; + } + + /** + * Changes the animation of the demon if a state change occurs + */ + private void animate() { + // Check if same animation is being called + if (prevState.equals(state)) { + return; // skip rest of function + } + + switch (state) { + case IDLE -> slimey.getEvents().trigger("idle"); + case MOVE -> slimey.getEvents().trigger("move"); + case PROJECTILE_EXPLOSION -> slimey.getEvents().trigger("projectile_explosion"); + case PROJECTILE_IDLE -> slimey.getEvents().trigger("projectile_idle"); + case TAKE_HIT -> slimey.getEvents().trigger("take_hit"); + case TRANSFORM -> slimey.getEvents().trigger("transform"); + default -> logger.debug("Slimey boy animation {state} not found"); + } + prevState = state; + } + + @Override + public int getPriority() { + return PRIORITY; + } +} From f4f111e93a1202fa1eb568cddad7d7dc2502f293 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:30:32 +1000 Subject: [PATCH 22/29] added/reworked some methods in Entity service to detect entities in a certain layer/proximity --- .../tasks/bosstask/PatrickTask.java | 5 +- .../tasks/bosstask/SlimeyBoyTask.java | 68 ++++++++++++++++++- .../csse3200/game/entities/EntityService.java | 34 ++++++++-- 3 files changed, 96 insertions(+), 11 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index ba62aafc1..ee35c22ce 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -195,9 +195,8 @@ private void teleport(Vector2 pos) { private void meleeAttack() { initialPos = patrick.getPosition(); - meleeTarget = ServiceLocator.getEntityService().getClosestHuman(patrick); - System.out.println(ServiceLocator.getEntityService().getEntities()); - System.out.println(ServiceLocator.getEntityService().getClosestHuman(patrick)); + meleeTarget = ServiceLocator.getEntityService().getClosestEntityOfLayer( + patrick, PhysicsLayer.HUMANS); teleport(meleeTarget.getPosition()); changeState(PatrickState.ATTACK); meleeFlag = true; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java index e3516e467..1f1ee2281 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -1,11 +1,16 @@ package com.csse3200.game.components.tasks.bosstask; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.components.CombatStatsComponent; +import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,14 +19,16 @@ public class SlimeyBoyTask extends DefaultTask implements PriorityTask { // Constants private static final int PRIORITY = 3; private static final Vector2 SLIMEY_SPEED = new Vector2(0.5f, 0.5f); + private static final Vector2 DEFAULT_POS = new Vector2(0, 4); // Private variables private static final Logger logger = LoggerFactory.getLogger(SlimeyBoyTask.class); private Entity slimey; private AnimationRenderComponent animation; private Vector2 currentPos; - private SlimeState state = SlimeState.IDLE; + private SlimeState state = SlimeState.PROJECTILE_EXPLOSION; // set initial state to random unused state private SlimeState prevState; + private Entity targetEntity; private enum SlimeState { IDLE, MOVE, PROJECTILE_EXPLOSION, PROJECTILE_IDLE, TAKE_HIT, TRANSFORM @@ -37,6 +44,23 @@ public void start() { changeState(SlimeState.IDLE); } + @Override + public void update() { + animate(); + currentPos = slimey.getPosition(); + + switch (state) { + case IDLE -> seekAndDestroy(); + case MOVE -> { + if (targetFound()) { + // do aoe damage based on how much health slime has left + applyAoeDamage(getNearbyHumans(SMASH_RADIUS), + slimey.getComponent(CombatStatsComponent.class).getHealth()); + } + } + } + } + /** * Changes the state of the demon * @param state state to be changed to @@ -67,6 +91,48 @@ private void animate() { prevState = state; } + /** + * Find the closest human entity and start moving towards them + */ + private void seekAndDestroy() { + changeState(SlimeState.MOVE); + targetEntity = ServiceLocator.getEntityService().getClosestEntityOfLayer( + slimey, PhysicsLayer.HUMANS); + Vector2 targetPos; + if (targetEntity == null) { + targetPos = DEFAULT_POS; + } else { + targetPos = targetEntity.getPosition(); + } + MovementTask slimeyMovementTask = new MovementTask(targetPos); + slimeyMovementTask.create(owner); + slimeyMovementTask.start(); + slimey.getComponent(PhysicsMovementComponent.class).setSpeed(SLIMEY_SPEED); + } + + /** + * @return if target has been reached or not + */ + private boolean targetFound() { + return currentPos.dst(targetEntity.getPosition()) < 1; + } + + /** + * Applies aoe damage to nearby human entities + * @param targets array of human entities to deal damage to + */ + private void applyAoeDamage(Array targets, int damage) { + for (int i = 0; i < targets.size; i++) { + Entity targetEntity = targets.get(i); + + CombatStatsComponent targetCombatStats = targetEntity. + getComponent(CombatStatsComponent.class); + if (targetCombatStats != null) { + targetCombatStats.hit(damage); + } + } + } + @Override public int getPriority() { return PRIORITY; diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index 8a7109730..e9c004501 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -104,22 +104,42 @@ public Array getNearbyEntities(Entity source, float radius) { return nearbyEntities; } - public Entity getClosestHuman(Entity source) { - Entity closestHuman = null; - Vector2 sourcePos = source.getPosition(); - float closestDistance = MAX_RADIUS; + /** + * Get entities within a certain radius of a given entity. + * + * @param source The reference entity to check distance from. + * @param radius The radius within which to fetch entities. + * @param layer Desired layer for entities to be in + * @return An array containing entities within the given radius. + */ + public Array getEntitiesInLayer(Entity source, float radius, short layer) { + Array entities = new Array(); + Array allEntities = getNearbyEntities(source, radius); - for (int i = 0; i < getEntities().size; i++) { + for (int i = 0; i < allEntities.size; i++) { Entity targetEntity = getEntities().get(i); - // check if target is human + // check targets layer HitboxComponent targetHitbox = targetEntity.getComponent(HitboxComponent.class); if (targetHitbox == null) { break; } - if (!PhysicsLayer.contains(PhysicsLayer.HUMANS, targetHitbox.getLayer())) { + if (!PhysicsLayer.contains(layer, targetHitbox.getLayer())) { break; } + entities.add(targetEntity); + } + return entities; + } + + public Entity getClosestEntityOfLayer(Entity source, short layer) { + Entity closestHuman = null; + Vector2 sourcePos = source.getPosition(); + float closestDistance = MAX_RADIUS; + Array entitiesInLayer = getEntitiesInLayer(source, MAX_RADIUS, layer); + + for (int i = 0; i < entitiesInLayer.size; i++) { + Entity targetEntity = entitiesInLayer.get(i); // check how close target is to source Vector2 targetPosition = targetEntity.getPosition(); From 5a8b0fde7232d79ff7a87a1cfafd003fee3c315f Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:34:49 +1000 Subject: [PATCH 23/29] fully implemented slimey boy task --- .../game/components/tasks/bosstask/SlimeyBoyTask.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java index 1f1ee2281..27d554ee7 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -20,6 +20,7 @@ public class SlimeyBoyTask extends DefaultTask implements PriorityTask { private static final int PRIORITY = 3; private static final Vector2 SLIMEY_SPEED = new Vector2(0.5f, 0.5f); private static final Vector2 DEFAULT_POS = new Vector2(0, 4); + private static final float MAX_RADIUS = 40f; // Private variables private static final Logger logger = LoggerFactory.getLogger(SlimeyBoyTask.class); @@ -48,16 +49,21 @@ public void start() { public void update() { animate(); currentPos = slimey.getPosition(); + int health = slimey.getComponent(CombatStatsComponent.class).getHealth(); switch (state) { case IDLE -> seekAndDestroy(); case MOVE -> { if (targetFound()) { // do aoe damage based on how much health slime has left - applyAoeDamage(getNearbyHumans(SMASH_RADIUS), - slimey.getComponent(CombatStatsComponent.class).getHealth()); + applyAoeDamage(ServiceLocator.getEntityService().getEntitiesInLayer( + slimey, MAX_RADIUS, PhysicsLayer.HUMANS), health); + changeState(SlimeState.TAKE_HIT); } } + case TAKE_HIT -> { + slimey.setFlagForDelete(true); + } } } From e5c8be4ff07d61cfefa9f7dd514d07443254e444 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:40:52 +1000 Subject: [PATCH 24/29] removed all slime functionality from demonBossTask and should now spawn slimey on death --- .../tasks/bosstask/DemonBossTask.java | 64 +++---------------- .../entities/factories/MobBossFactory.java | 2 +- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index 9234760c4..264ea4a0a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -10,6 +10,7 @@ import com.csse3200.game.components.ProjectileEffects; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.MobBossFactory; import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; @@ -40,11 +41,9 @@ public class DemonBossTask extends DefaultTask implements PriorityTask { private static final int MOVE_FORWARD_DELAY = 30; private static final float BREATH_DURATION = 4.2f; private static final int SMASH_DAMAGE = 30; - private static final Vector2 SLIME_SPEED = new Vector2(0.5f, 0.5f); private static final int CLEAVE_DAMAGE = 50; private static final int HEAL_TIMES = 10; private static final int HEALTH_TO_ADD = 10; - private static final Vector2 DEFAULT_POS = new Vector2(0, 4); // Private variables private static final Logger logger = LoggerFactory.getLogger(DemonBossTask.class); @@ -62,11 +61,9 @@ public class DemonBossTask extends DefaultTask implements PriorityTask { private static int xLeftBoundary = 12; private ProjectileEffects effect = ProjectileEffects.BURN; private boolean aoe = true; - private int deathCounter = 0; // Flags private boolean startFlag = false; - private boolean moving = false; private boolean isJumping; private boolean halfHealthFlag = false; private boolean isHealing = false; @@ -142,12 +139,13 @@ public void update() { } // detect death stages - if (health <= 0 && deathCounter == 0) { - changeState(DemonState.TRANSFORM_REVERSE); - demon.getComponent(CombatStatsComponent.class).addHealth(100); - deathCounter += 1; - } else if (health <= 0 && deathCounter == 1) { - changeState(DemonState.TRANSFORM); + if (health <= 0) { + // spawn slimey boy + Entity slimey = MobBossFactory.createSlimeyBoy(); + slimey.setPosition(demon.getPosition().x, demon.getPosition().y); + slimey.setScale(5f, 5f); + ServiceLocator.getEntityService().register(slimey); + demon.setFlagForDelete(true); } // detect half health @@ -187,28 +185,6 @@ public void update() { } } } - case TRANSFORM_REVERSE -> { - if (animation.isFinished()) { - changeState(DemonState.SLIME_MOVE); - } - } - case SLIME_MOVE -> { - if (!moving) { - seekAndDestroy(); - moving = true; - } else { - if (targetFound()) { - // do aoe damage based on how much health slime has left - applyAoeDamage(getNearbyHumans(SMASH_RADIUS), - demon.getComponent(CombatStatsComponent.class).getHealth()); - } - } - } - case DEATH -> { - if (animation.isFinished()) { - demon.setFlagForDelete(true); - } - } } } @@ -443,30 +419,6 @@ public void run() { }, 2f); } - /** - * Find the closest human entity and start moving towards them - */ - private void seekAndDestroy() { - Entity targetEntity = getClosestHuman(getNearbyHumans(20)); - Vector2 targetPos; - if (targetEntity == null) { - targetPos = DEFAULT_POS; - } else { - targetPos = targetEntity.getPosition(); - } - MovementTask slimeMovementTask = new MovementTask(targetPos); - slimeMovementTask.create(owner); - slimeMovementTask.start(); - demon.getComponent(PhysicsMovementComponent.class).setSpeed(SLIME_SPEED); - } - - /** - * @return if target has been reached or not - */ - private boolean targetFound() { - return !getNearbyHumans(1).isEmpty(); - } - /** * When at half health demon starts healing by a certain amount every second */ diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index ef8eee5d1..edd254b85 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -65,7 +65,7 @@ public static Entity createDemonBoss() { return demon; } - public static Entity slimeyBoy() { + public static Entity createSlimeyBoy() { Entity slimeyBoy = createBaseBoss(); // Animation From d52e8500cbb6dd5de5021e46d580243fcbd18f13 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:53:18 +1000 Subject: [PATCH 25/29] fixed bug in getEntitiesInLayer where during layer checking it would break out of the loop instead of continue --- .../com/csse3200/game/areas/ForestGameArea.java | 1 - .../components/tasks/bosstask/SlimeyBoyTask.java | 15 ++++++++++++--- .../com/csse3200/game/entities/EntityService.java | 13 ++++++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 94b7cd016..5f2a16dd0 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -684,7 +684,6 @@ private void spawnDroidTower() { for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); Entity weaponTower = TowerFactory.createDroidTower(); - System.out.println(weaponTower); spawnEntityAt(weaponTower, randomPos, true, true); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java index 27d554ee7..ccf744288 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -27,7 +27,7 @@ public class SlimeyBoyTask extends DefaultTask implements PriorityTask { private Entity slimey; private AnimationRenderComponent animation; private Vector2 currentPos; - private SlimeState state = SlimeState.PROJECTILE_EXPLOSION; // set initial state to random unused state + private SlimeState state = SlimeState.IDLE; // set initial state to random unused state private SlimeState prevState; private Entity targetEntity; @@ -42,7 +42,7 @@ public void start() { animation = owner.getEntity().getComponent(AnimationRenderComponent.class); // get animation currentPos = owner.getEntity().getPosition(); // get current position slimey.getComponent(PhysicsMovementComponent.class).setSpeed(SLIMEY_SPEED); // set speed - changeState(SlimeState.IDLE); + changeState(SlimeState.TRANSFORM); } @Override @@ -52,7 +52,11 @@ public void update() { int health = slimey.getComponent(CombatStatsComponent.class).getHealth(); switch (state) { - case IDLE -> seekAndDestroy(); + case TRANSFORM -> { + if (animation.isFinished()) { + seekAndDestroy(); + } + } case MOVE -> { if (targetFound()) { // do aoe damage based on how much health slime has left @@ -104,6 +108,8 @@ private void seekAndDestroy() { changeState(SlimeState.MOVE); targetEntity = ServiceLocator.getEntityService().getClosestEntityOfLayer( slimey, PhysicsLayer.HUMANS); +// System.out.println(ServiceLocator.getEntityService().getEntitiesInLayer(slimey, MAX_RADIUS, PhysicsLayer.HUMANS)); +// System.out.println(ServiceLocator.getEntityService().getClosestEntityOfLayer(slimey, PhysicsLayer.HUMANS)); Vector2 targetPos; if (targetEntity == null) { targetPos = DEFAULT_POS; @@ -120,6 +126,9 @@ private void seekAndDestroy() { * @return if target has been reached or not */ private boolean targetFound() { + if (targetEntity == null) { + return false; + } return currentPos.dst(targetEntity.getPosition()) < 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index e9c004501..812f0d9c7 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -115,23 +115,30 @@ public Array getNearbyEntities(Entity source, float radius) { public Array getEntitiesInLayer(Entity source, float radius, short layer) { Array entities = new Array(); Array allEntities = getNearbyEntities(source, radius); + System.out.println(allEntities); for (int i = 0; i < allEntities.size; i++) { - Entity targetEntity = getEntities().get(i); + Entity targetEntity = allEntities.get(i); // check targets layer HitboxComponent targetHitbox = targetEntity.getComponent(HitboxComponent.class); if (targetHitbox == null) { - break; + continue; } if (!PhysicsLayer.contains(layer, targetHitbox.getLayer())) { - break; + continue; } entities.add(targetEntity); } return entities; } + /** + * Returns the closest entity to the source of provided layer + * @param source source entity + * @param layer layer for desired entity to be returned + * @return closest entity of correct layer + */ public Entity getClosestEntityOfLayer(Entity source, short layer) { Entity closestHuman = null; Vector2 sourcePos = source.getPosition(); From eb71ad9a15af8a6246dec990cd71dc4c8d7b6636 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:55:08 +1000 Subject: [PATCH 26/29] removed getClosestHuman function in DemonBossTask because getClosestEntityOfLayer in EntityService can be used --- .../tasks/bosstask/DemonBossTask.java | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index 264ea4a0a..00f2ebb27 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -381,34 +381,13 @@ private void applyAoeDamage(Array targets, int damage) { } } - /** - * Return closest entity given an array of human entities - * @param targets array of human entities - * @return closest human entity - */ - private Entity getClosestHuman(Array targets) { - Entity closestEntity = null; - float closestDistance = SMASH_RADIUS; - - for (int i = 0; i < targets.size; i++) { - Entity targetEntity = targets.get(i); - Vector2 targetPosition = targetEntity.getPosition(); - float distance = currentPos.dst(targetPosition); - - if (distance < closestDistance) { - closestEntity = targetEntity; - closestDistance = distance; - } - } - return closestEntity; - } - /** * Change state to cleave and deal damage to target */ private void cleave() { changeState(DemonState.CLEAVE); - Entity target = getClosestHuman(getNearbyHumans(SMASH_RADIUS)); + Entity target = ServiceLocator.getEntityService().getClosestEntityOfLayer(demon, + PhysicsLayer.HUMANS); CombatStatsComponent targetCombatStats = target. getComponent(CombatStatsComponent.class); Timer.schedule(new Timer.Task() { From a56fa083a466499823afdd5790700f7a6ebd0327 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 19:42:11 +1000 Subject: [PATCH 27/29] made PatrickTeleportTask use changeState and animate like the other tasks --- .../csse3200/game/areas/ForestGameArea.java | 6 +- .../tasks/bosstask/PatrickTask.java | 25 +++++---- .../tasks/bosstask/PatrickTeleportTask.java | 55 ++++++++++++++----- .../tasks/bosstask/SlimeyBoyTask.java | 2 - .../csse3200/game/entities/EntityService.java | 1 - .../entities/factories/MobBossFactory.java | 4 +- 6 files changed, 60 insertions(+), 33 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 5f2a16dd0..1f5b6fc58 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -256,8 +256,8 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); - spawnDemonBoss(); -// spawnPatrick(); + //spawnDemonBoss(); + spawnPatrick(); //mobBoss1 = spawnMobBoss1(); // startWaveTimer(); @@ -408,7 +408,7 @@ private void spawnDemonBoss() { private void spawnPatrick() { Entity patrick = MobBossFactory.createPatrickBoss(2500); - spawnEntityAt(patrick, new GridPoint2(19, 3), true, false); + spawnEntityAt(patrick, new GridPoint2(18, 5), true, false); } private Entity spawnMobBoss1() { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index ee35c22ce..70b13121c 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -83,6 +83,9 @@ public void run() { @Override public void update() { + if(animation.isFinished()) { + teleport(ServiceLocator.getEntityService().getClosestEntityOfLayer(patrick, PhysicsLayer.HUMANS).getPosition()); + } // give game time to load if (!startFlag) { return; @@ -106,15 +109,17 @@ public void update() { // handle state switches switch (state) { case APPEAR -> { - if (spawnFlag) { - meleeAttack(); - spawnFlag = false; - } else if (meleeFlag) { - changeState(PatrickState.ATTACK); - meleeFlag = false; - } else if (rangeFlag) { - changeState(PatrickState.IDLE); - rangeFlag = false; + if (animation.isFinished()) { + if (spawnFlag) { + meleeAttack(); + spawnFlag = false; + } else if (meleeFlag) { + changeState(PatrickState.ATTACK); + meleeFlag = false; + } else if (rangeFlag) { + changeState(PatrickState.IDLE); + rangeFlag = false; + } } } case IDLE -> { @@ -189,8 +194,8 @@ private ProjectileEffects getEffect() { } private void teleport(Vector2 pos) { - teleportFlag = true; teleportTask = new PatrickTeleportTask(patrick, pos); + teleportFlag = true; } private void meleeAttack() { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java index 87b473959..cfb17e5c5 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java @@ -11,18 +11,19 @@ public class PatrickTeleportTask extends DefaultTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private final Entity entity; + private final Entity patrick; private final Vector2 location; - private PatrickState state; + private PatrickState state = PatrickState.IDLE; + private PatrickState prevState; private AnimationRenderComponent animation; - private Status status; + private Status status = Status.INACTIVE; private int health; private enum PatrickState { - CAST, APPEAR, SPELL + CAST, APPEAR, SPELL, IDLE } - public PatrickTeleportTask(Entity entity, Vector2 location) { - this.entity = entity; + public PatrickTeleportTask(Entity patrick, Vector2 location) { + this.patrick = patrick; this.location = location; } @@ -30,37 +31,61 @@ public PatrickTeleportTask(Entity entity, Vector2 location) { public void start() { super.start(); animation = owner.getEntity().getComponent(AnimationRenderComponent.class); - owner.getEntity().getEvents().trigger("patrick_cast"); - state = PatrickState.CAST; - status = Status.ACTIVE; health = owner.getEntity().getComponent(CombatStatsComponent.class).getHealth(); + changeState(PatrickState.CAST); } @Override public void update() { + animate(); + switch (state) { case CAST -> { if (animation.isFinished()) { - entity.setPosition(location); - owner.getEntity().getEvents().trigger("patrick_spell"); - state = PatrickState.SPELL; + patrick.setPosition(location); + changeState(PatrickState.SPELL); } } case SPELL -> { if (animation.isFinished()) { - owner.getEntity().getEvents().trigger("patrick_appear"); - state = PatrickState.APPEAR; + changeState(PatrickState.APPEAR); } } case APPEAR -> { if (animation.isFinished()) { - entity.getComponent(CombatStatsComponent.class).setHealth(health); status = Status.FINISHED; } } } } + /** + * Changes the state of patrick + * @param state state to be changed to + */ + private void changeState(PatrickState state) { + prevState = this.state; + this.state = state; + } + + /** + * Changes the animation of the demon if a state change occurs + */ + private void animate() { + // Check if same animation is being called + if (prevState.equals(state)) { + return; // skip rest of function + } + + switch (state) { + case SPELL -> owner.getEntity().getEvents().trigger("patrick_spell"); + case APPEAR -> owner.getEntity().getEvents().trigger("patrick_death"); + case CAST -> owner.getEntity().getEvents().trigger("patrick_cast"); + default -> logger.debug("Patrick animation {state} not found"); + } + prevState = state; + } + @Override public Status getStatus() { return status; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java index ccf744288..5cef0c8ec 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -108,8 +108,6 @@ private void seekAndDestroy() { changeState(SlimeState.MOVE); targetEntity = ServiceLocator.getEntityService().getClosestEntityOfLayer( slimey, PhysicsLayer.HUMANS); -// System.out.println(ServiceLocator.getEntityService().getEntitiesInLayer(slimey, MAX_RADIUS, PhysicsLayer.HUMANS)); -// System.out.println(ServiceLocator.getEntityService().getClosestEntityOfLayer(slimey, PhysicsLayer.HUMANS)); Vector2 targetPos; if (targetEntity == null) { targetPos = DEFAULT_POS; diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index 812f0d9c7..5f3fe9d74 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -115,7 +115,6 @@ public Array getNearbyEntities(Entity source, float radius) { public Array getEntitiesInLayer(Entity source, float radius, short layer) { Array entities = new Array(); Array allEntities = getNearbyEntities(source, radius); - System.out.println(allEntities); for (int i = 0; i < allEntities.size; i++) { Entity targetEntity = allEntities.get(i); diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index edd254b85..6c71a0796 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -125,8 +125,8 @@ public static Entity createPatrickBoss(int health) { // Scale demon demon.getComponent(AnimationRenderComponent.class).scaleEntity(); - demon.scaleHeight(5f); - demon.scaleWidth(5f); + demon.scaleHeight(4f); + demon.scaleWidth(4f); return demon; } From dcb8627cd77e358996d92ca3b366d2c10f1b07e0 Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 20:32:21 +1000 Subject: [PATCH 28/29] fixed error where teleport task wasn't being called properly so the task wasn't updating --- .../csse3200/game/areas/ForestGameArea.java | 2 +- .../tasks/bosstask/DemonBossTask.java | 2 +- .../tasks/bosstask/PatrickTask.java | 33 ++++++++++--------- .../tasks/bosstask/PatrickTeleportTask.java | 3 +- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 1f5b6fc58..3f6dbc48c 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -256,7 +256,7 @@ public void create() { // spawnDragonKnight(); // spawnFireWorm(); - //spawnDemonBoss(); +// spawnDemonBoss(); spawnPatrick(); //mobBoss1 = spawnMobBoss1(); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index 00f2ebb27..042c734df 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -107,7 +107,7 @@ public void run() { }, 0.1f); // shift demon's boundary left every 30s - for (int i = 0; i < 5; i++) { + for (int i = 1; i < 6; i++) { Timer.schedule(new Timer.Task() { @Override public void run() { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 70b13121c..953b94d77 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -74,7 +74,6 @@ public void start() { @Override public void run() { changeState(PatrickState.APPEAR); - animate(); startFlag = true; spawnFlag = true; } @@ -83,13 +82,16 @@ public void run() { @Override public void update() { - if(animation.isFinished()) { - teleport(ServiceLocator.getEntityService().getClosestEntityOfLayer(patrick, PhysicsLayer.HUMANS).getPosition()); - } // give game time to load if (!startFlag) { return; } + + // update teleport task while teleporting + if (teleportFlag) { + teleportTask.update(); + } + animate(); int health = patrick.getComponent(CombatStatsComponent.class).getHealth(); @@ -109,17 +111,15 @@ public void update() { // handle state switches switch (state) { case APPEAR -> { - if (animation.isFinished()) { - if (spawnFlag) { - meleeAttack(); - spawnFlag = false; - } else if (meleeFlag) { - changeState(PatrickState.ATTACK); - meleeFlag = false; - } else if (rangeFlag) { - changeState(PatrickState.IDLE); - rangeFlag = false; - } + if (spawnFlag) { + meleeAttack(); + spawnFlag = false; + } else if (meleeFlag) { + changeState(PatrickState.ATTACK); + meleeFlag = false; + } else if (rangeFlag) { + changeState(PatrickState.IDLE); + rangeFlag = false; } } case IDLE -> { @@ -130,7 +130,6 @@ public void update() { case ATTACK -> { if (animation.isFinished()) { if (halfHealthFlag) { - break; } meleeTarget.getComponent(CombatStatsComponent.class).hit(ATTACK_DAMAGE); @@ -195,6 +194,8 @@ private ProjectileEffects getEffect() { private void teleport(Vector2 pos) { teleportTask = new PatrickTeleportTask(patrick, pos); + teleportTask.create(owner); + teleportTask.start(); teleportFlag = true; } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java index cfb17e5c5..54ef0e71a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTeleportTask.java @@ -5,13 +5,14 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.MobBossFactory; import com.csse3200.game.rendering.AnimationRenderComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PatrickTeleportTask extends DefaultTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private final Entity patrick; + private Entity patrick; private final Vector2 location; private PatrickState state = PatrickState.IDLE; private PatrickState prevState; From badb46e8c52f1c606b97cb2f6875489f4581328d Mon Sep 17 00:00:00 2001 From: gregchan550 <86044792+gregchan550@users.noreply.github.com> Date: Mon, 25 Sep 2023 21:05:22 +1000 Subject: [PATCH 29/29] fixed sequencing for patrick boss. fully functional for now --- .../tasks/bosstask/PatrickTask.java | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java index 953b94d77..bbfb4d4e0 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickTask.java @@ -90,17 +90,17 @@ public void update() { // update teleport task while teleporting if (teleportFlag) { teleportTask.update(); + if (teleportTask.getStatus().equals(Status.FINISHED)) { + teleportFlag = false; + changeState(PatrickState.APPEAR); + } else { + return; + } } animate(); int health = patrick.getComponent(CombatStatsComponent.class).getHealth(); - // check if patrick has just teleported - if (teleportFlag && teleportTask.getStatus().equals(Status.FINISHED)) { - changeState(PatrickState.APPEAR); - teleportFlag = false; - } - // detect half health if (health <= patrick.getComponent(CombatStatsComponent.class).getMaxHealth() / 2 && !halfHealthFlag) { @@ -118,8 +118,14 @@ public void update() { changeState(PatrickState.ATTACK); meleeFlag = false; } else if (rangeFlag) { - changeState(PatrickState.IDLE); - rangeFlag = false; + // shoot 3 projectiles + if (shotsFired > 2) { + rangeFlag = false; + spawnFlag = true; + shotsFired = 0; // reset shots fired + } else { + changeState(PatrickState.IDLE); + } } } case IDLE -> { @@ -129,11 +135,9 @@ public void update() { } case ATTACK -> { if (animation.isFinished()) { - if (halfHealthFlag) { - break; - } meleeTarget.getComponent(CombatStatsComponent.class).hit(ATTACK_DAMAGE); teleport(initialPos); + rangeFlag = true; } } } @@ -204,7 +208,6 @@ private void meleeAttack() { meleeTarget = ServiceLocator.getEntityService().getClosestEntityOfLayer( patrick, PhysicsLayer.HUMANS); teleport(meleeTarget.getPosition()); - changeState(PatrickState.ATTACK); meleeFlag = true; } @@ -227,12 +230,6 @@ private void randomTeleport() { } private void rangeAttack() { - // detect if 3 shots have been fired - if (shotsFired == 3) { - shotsFired = 0; - rangeFlag = false; - spawnFlag = true; - } randomTeleport(); spawnRandProjectile(new Vector2(0f, patrick.getPosition().y)); }