From 1e18d77f559ad31370fc36a00f784187499274ab Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Mon, 4 Sep 2023 15:16:14 +1000 Subject: [PATCH 01/32] Made changes to xenoAnimationController and ForestGameArea to support the second xeno melee. --- .../game/components/npc/XenoAnimationController.java | 11 ++++++----- .../csse3200/game/entities/factories/NPCFactory.java | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java index c125babe9..e55076a4e 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java @@ -14,19 +14,20 @@ public class XenoAnimationController extends Component { public void create() { super.create(); animator = this.entity.getComponent(AnimationRenderComponent.class); - entity.getEvents().addListener("wanderStart", this::animateWander); - entity.getEvents().addListener("chaseStart", this::animateChase); + entity.getEvents().addListener("wanderStart", this::animateRun); + entity.getEvents().addListener("runHurt", this::animateHurt); + entity.getEvents().addListener("meleeStart", this::animateMelee1); entity.getEvents().addListener("meleeStart", this::animateMelee2); entity.getEvents().addListener("shootStart", this::animateShoot); entity.getEvents().addListener("dieStart", this::animateDie); } - void animateWander() { + void animateRun() { animator.startAnimation("xeno_run"); } - void animateChase() { - animator.startAnimation("xeno_run"); + void animateHurt() { + animator.startAnimation("xeno_hurt"); } void animateShoot() { diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 3f3278de4..24f28cb37 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -113,7 +113,8 @@ public static Entity createXenoGrunt(Entity target) { new AnimationRenderComponent( ServiceLocator.getResourceService().getAsset("images/xenoGrunt.atlas", TextureAtlas.class)); animator.addAnimation("xeno_run", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("xeno_shoot", 0.1f, Animation.PlayMode.NORMAL); + animator.addAnimation("xeno_hurt", 0.1f, Animation.PlayMode.LOOP); + animator.addAnimation("xeno_shoot", 0.1f, Animation.PlayMode.LOOP); animator.addAnimation("xeno_melee_1", 0.1f, Animation.PlayMode.NORMAL); animator.addAnimation("xeno_melee_2", 0.1f, Animation.PlayMode.NORMAL); animator.addAnimation("xeno_die", 0.1f, Animation.PlayMode.NORMAL); @@ -123,7 +124,7 @@ public static Entity createXenoGrunt(Entity target) { .addComponent(animator) .addComponent(new XenoAnimationController()); - xenoGrunt.getComponent(AnimationRenderComponent.class).scaleEntity(); +// xenoGrunt.getComponent(AnimationRenderComponent.class).scaleEntity(); return xenoGrunt; } From ab853e02cb1706f23dc8700246dd7326c67ebaef Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Fri, 8 Sep 2023 13:28:20 +1000 Subject: [PATCH 02/32] Removed the rescaling of projectiles in MobAttackTask --- .../main/com/csse3200/game/components/tasks/MobAttackTask.java | 1 - 1 file changed, 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index aaba29da7..85831508e 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -128,7 +128,6 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.PLAYER, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); - newProjectile.setScale(-1f, 0.5f); ServiceLocator.getEntityService().register(newProjectile); mobState = STATE.STOW; owner.getEntity().getEvents().trigger("shootStart"); From 9780bc88ab5ea86b70631312dff3b360a26e2852 Mon Sep 17 00:00:00 2001 From: bojyyy <140468434+bojyyy@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:42:54 +1000 Subject: [PATCH 03/32] Modifies spawning functionality of mobs to correspond with the lanes of the map --- .../com/csse3200/game/areas/ForestGameArea.java | 14 ++++++-------- .../game/components/tasks/SpawnWaveTask.java | 8 ++++---- 2 files changed, 10 insertions(+), 12 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 0288f8a46..d218b1359 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -19,13 +19,11 @@ import com.csse3200.game.components.gamearea.GameAreaDisplay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; -import static com.csse3200.game.entities.factories.NPCFactory.createGhost; -import java.util.ArrayList; +import static com.csse3200.game.entities.factories.NPCFactory.createGhost; /** Forest area for the demo game with trees, a player, and some enemies. */ public class ForestGameArea extends GameArea { @@ -343,14 +341,14 @@ private void spawnProjectile(Vector2 position, short targetLayer, int space, in private void spawnXenoGrunts() { - GridPoint2 minPos = terrain.getMapBounds(0).sub(1, 5); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(1, 25); + int[] pickedLanes = new Random().ints(0, 8) + .distinct().limit(5).toArray(); for (int i = 0; i < NUM_GRUNTS; i++) { - GridPoint2 randomPos = RandomUtils.random(maxPos, minPos); + GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); System.out.println(randomPos); Entity xenoGrunt = NPCFactory.createXenoGrunt(player); xenoGrunt.setScale(1.5f, 1.5f); - spawnEntityAt(xenoGrunt, randomPos, true, true); + spawnEntityAt(xenoGrunt, randomPos, true, false); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java index cb326b8b4..7fa219b6a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java @@ -1,21 +1,21 @@ package com.csse3200.game.components.tasks; -import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; -import com.csse3200.game.ai.tasks.Task; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * A task which spawns a new wave of mobs at a set spawning interval + * + */ public class SpawnWaveTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(SpawnWaveTask.class); private final GameTime globalTime; private long endTime; - private final int SPAWNING_INTERVAL = 10; - public SpawnWaveTask() { this.globalTime = ServiceLocator.getTimeSource(); } From 6888d3853dc1deadb39b8a3c6138f6adcc85d4d0 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Sat, 9 Sep 2023 09:49:25 +1000 Subject: [PATCH 04/32] Refactored xeno files into mobs folder --- source/core/assets/images/{ => mobs}/xeno-Grunt.png | Bin .../core/assets/images/{ => mobs}/xenoGrunt.atlas | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename source/core/assets/images/{ => mobs}/xeno-Grunt.png (100%) rename source/core/assets/images/{ => mobs}/xenoGrunt.atlas (100%) diff --git a/source/core/assets/images/xeno-Grunt.png b/source/core/assets/images/mobs/xeno-Grunt.png similarity index 100% rename from source/core/assets/images/xeno-Grunt.png rename to source/core/assets/images/mobs/xeno-Grunt.png diff --git a/source/core/assets/images/xenoGrunt.atlas b/source/core/assets/images/mobs/xenoGrunt.atlas similarity index 100% rename from source/core/assets/images/xenoGrunt.atlas rename to source/core/assets/images/mobs/xenoGrunt.atlas From 0e68b7bfd800ae910dd4e0201a925d182b161c13 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Sat, 9 Sep 2023 09:50:26 +1000 Subject: [PATCH 05/32] Updated references to xeno atlas --- .../core/src/main/com/csse3200/game/areas/ForestGameArea.java | 2 +- .../main/com/csse3200/game/entities/factories/NPCFactory.java | 2 +- 2 files changed, 2 insertions(+), 2 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 422057ab1..df0b0302b 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -106,7 +106,7 @@ public class ForestGameArea extends GameArea { "images/ghostKing.atlas", "images/towers/turret.atlas", "images/towers/turret01.atlas", - "images/xenoGrunt.atlas", + "images/mobs/xenoGrunt.atlas", "images/mobs/robot.atlas", "images/mobs/rangeBossRight.atlas", "images/towers/TNTTower.atlas", diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 2f8390040..72df053a1 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -116,7 +116,7 @@ public static Entity createXenoGrunt(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( - ServiceLocator.getResourceService().getAsset("images/xenoGrunt.atlas", TextureAtlas.class)); + ServiceLocator.getResourceService().getAsset("images/mobs/xenoGrunt.atlas", TextureAtlas.class)); animator.addAnimation("xeno_run", 0.1f, Animation.PlayMode.LOOP); animator.addAnimation("xeno_hurt", 0.1f, Animation.PlayMode.LOOP); animator.addAnimation("xeno_shoot", 0.1f, Animation.PlayMode.LOOP); From cdc8b5956b2f010ff413a5e425d8d4d2e837e9f3 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Sat, 9 Sep 2023 10:36:44 +1000 Subject: [PATCH 06/32] Cleaned up CreateXeno function in NPC factory. Added animation triggers to MobAttackTask and MobDeathTask --- .../game/components/npc/XenoAnimationController.java | 5 +++++ .../com/csse3200/game/components/tasks/MobAttackTask.java | 3 +-- .../com/csse3200/game/components/tasks/MobDeathTask.java | 1 + .../com/csse3200/game/entities/factories/NPCFactory.java | 8 ++++---- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java index e55076a4e..efe0858b4 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java @@ -20,6 +20,7 @@ public void create() { entity.getEvents().addListener("meleeStart", this::animateMelee2); entity.getEvents().addListener("shootStart", this::animateShoot); entity.getEvents().addListener("dieStart", this::animateDie); + entity.getEvents().addListener("stop", this::stopAnimation); } void animateRun() { @@ -45,4 +46,8 @@ void animateMelee2() { void animateDie() { animator.startAnimation("xeno_die"); } + + void stopAnimation() { + animator.stopAnimation(); + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index e6a83c610..e696a39d2 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -24,7 +24,7 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final String STOW = "stowStart"; private static final String DEPLOY = "deployStart"; - private static final String FIRING = "firingStart"; + private static final String FIRING = "shootStart"; private static final String IDLE = "idleStart"; private final int priority; @@ -131,7 +131,6 @@ public void updateMobState() { newProjectile.setScale(-1f, 0.5f); ServiceLocator.getEntityService().register(newProjectile); mobState = STATE.STOW; - owner.getEntity().getEvents().trigger("shootStart"); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java index f04ad39a0..e8e480980 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java @@ -50,6 +50,7 @@ public void start() { this.mobPosition = owner.getEntity().getCenterPosition(); //sets endTime endTime = timeSource.getTime() + (INTERVAL * 500); + this.owner.getEntity().getEvents().trigger("dieStart"); } @Override diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 72df053a1..b5f5c4dc7 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -119,10 +119,10 @@ public static Entity createXenoGrunt(Entity target) { ServiceLocator.getResourceService().getAsset("images/mobs/xenoGrunt.atlas", TextureAtlas.class)); animator.addAnimation("xeno_run", 0.1f, Animation.PlayMode.LOOP); animator.addAnimation("xeno_hurt", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("xeno_shoot", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("xeno_melee_1", 0.1f, Animation.PlayMode.NORMAL); - animator.addAnimation("xeno_melee_2", 0.1f, Animation.PlayMode.NORMAL); - animator.addAnimation("xeno_die", 0.1f, Animation.PlayMode.NORMAL); + animator.addAnimation("xeno_shoot", 0.1f); + animator.addAnimation("xeno_melee_1", 0.1f); + animator.addAnimation("xeno_melee_2", 0.1f); + animator.addAnimation("xeno_die", 0.1f); xenoGrunt .addComponent(new CombatStatsComponent(config.fullHeath, config.baseAttack, drops, melee, projectiles)) .addComponent(animator) From b581bc9ffa7f104c285d82116adf495f79315ad6 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 10:47:14 +1000 Subject: [PATCH 07/32] Updated and removed redundant code in MobAttackTask --- .../game/components/tasks/MobAttackTask.java | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 85831508e..81122c34f 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -22,9 +22,9 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final short TARGET = PhysicsLayer.OBSTACLE; // mobs detecting for towers // ^ fix this - private static final String STOW = "stowStart"; - private static final String DEPLOY = "deployStart"; - private static final String FIRING = "firingStart"; +// private static final String STOW = "stowStart"; +// private static final String DEPLOY = "deployStart"; + private static final String FIRING = "shootStart"; private static final String IDLE = "idleStart"; private final int priority; @@ -69,7 +69,6 @@ public void start() { this.maxRangePosition.set(0, mobPosition.y); owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); - owner.getEntity().getEvents().trigger("shootStart"); } /** @@ -80,7 +79,7 @@ public void start() { public void update() { updateMobState(); - if (mobState == STATE.STOW) { + if (mobState == STATE.IDLE) { status = Status.FINISHED; } } @@ -95,55 +94,56 @@ public void updateMobState() { // if (statsComp != null) { // System.out.println("is the target visible " + isTargetVisible()); // } - if (!isTargetVisible()) { - System.out.println("target is not visible for " + owner.getEntity().getId()); - } +// if (!isTargetVisible()) { +// System.out.println("target is not visible for " + owner.getEntity().getId()); +// } switch (mobState) { case IDLE -> { if (isTargetVisible()) { // targets detected in idle mode - start deployment - owner.getEntity().getEvents().trigger(DEPLOY); - mobState = STATE.DEPLOY; - } - } - - case DEPLOY -> { - // currently deploying, - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(FIRING); + //owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.FIRING; - } else { - owner.getEntity().getEvents().trigger(STOW); - mobState = STATE.STOW; } } +// case DEPLOY -> { +// // currently deploying, +// if (isTargetVisible()) { +// //owner.getEntity().getEvents().trigger(FIRING); +// mobState = STATE.FIRING; +// owner.getEntity().getEvents().trigger("shootStart"); +// } else { +// //owner.getEntity().getEvents().trigger(STOW); +// mobState = STATE.STOW; +// } +// } + case FIRING -> { // targets gone - stop firing if (!isTargetVisible()) { - owner.getEntity().getEvents().trigger(STOW); - mobState = STATE.STOW; + //owner.getEntity().getEvents().trigger(STOW); + mobState = STATE.IDLE; } else { - owner.getEntity().getEvents().trigger(FIRING); + //owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.PLAYER, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); - mobState = STATE.STOW; - owner.getEntity().getEvents().trigger("shootStart"); +// mobState = STATE.IDLE; + owner.getEntity().getEvents().trigger(FIRING); } } - case STOW -> { - // currently stowing - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(DEPLOY); - mobState = STATE.DEPLOY; - } else { - owner.getEntity().getEvents().trigger(IDLE); - mobState = STATE.IDLE; - } - } +// case STOW -> { +// // currently stowing +// if (isTargetVisible()) { +// //owner.getEntity().getEvents().trigger(DEPLOY); +// mobState = STATE.DEPLOY; +// } else { +// //owner.getEntity().getEvents().trigger(IDLE); +// mobState = STATE.IDLE; +// } +// } } } @@ -153,7 +153,7 @@ public void updateMobState() { @Override public void stop() { super.stop(); - owner.getEntity().getEvents().trigger(STOW); + owner.getEntity().getEvents().trigger(IDLE); } /** From cd4895e112c7acaaf7e934b64468f9dc664f1930 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 15:54:13 +1000 Subject: [PATCH 08/32] Added comments for testing --- .../main/com/csse3200/game/components/tasks/MobAttackTask.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 81122c34f..7842b8c38 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -67,7 +67,7 @@ public void start() { startTime = timeSource.getTime(); this.mobPosition = owner.getEntity().getCenterPosition(); this.maxRangePosition.set(0, mobPosition.y); - owner.getEntity().getEvents().trigger(IDLE); +// owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); } @@ -91,6 +91,7 @@ public void update() { public void updateMobState() { // TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class); CombatStatsComponent statsComp = owner.getEntity().getComponent(CombatStatsComponent.class); + System.out.println(owner.getEntity().getId() + " health: " + statsComp.getHealth()); // if (statsComp != null) { // System.out.println("is the target visible " + isTargetVisible()); // } From 0954648dbf4cde666988a8cfc9f2a3b4d725fd82 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 15:58:29 +1000 Subject: [PATCH 09/32] Added in print statements for testing --- .../csse3200/game/components/tasks/MobAttackTask.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 7842b8c38..667bc32fa 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -19,7 +19,7 @@ */ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final int INTERVAL = 1; // time interval to scan for towers in - private static final short TARGET = PhysicsLayer.OBSTACLE; // mobs detecting for towers + private static final short TARGET = PhysicsLayer.HUMANS; // mobs detecting for towers // ^ fix this // private static final String STOW = "stowStart"; @@ -91,7 +91,6 @@ public void update() { public void updateMobState() { // TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class); CombatStatsComponent statsComp = owner.getEntity().getComponent(CombatStatsComponent.class); - System.out.println(owner.getEntity().getId() + " health: " + statsComp.getHealth()); // if (statsComp != null) { // System.out.println("is the target visible " + isTargetVisible()); // } @@ -102,10 +101,14 @@ public void updateMobState() { case IDLE -> { if (isTargetVisible()) { + System.out.println("IDLE: target visible for " + owner.getEntity().getId()); // targets detected in idle mode - start deployment //owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.FIRING; } + else { + System.out.println("IDLE: target not visible for " + owner.getEntity().getId()); + } } // case DEPLOY -> { @@ -125,12 +128,14 @@ public void updateMobState() { if (!isTargetVisible()) { //owner.getEntity().getEvents().trigger(STOW); mobState = STATE.IDLE; + System.out.println("FIRING: target not visible for " + owner.getEntity().getId()); } else { //owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.PLAYER, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); // mobState = STATE.IDLE; + System.out.println("FIRING: target visible for " + owner.getEntity().getId()); owner.getEntity().getEvents().trigger(FIRING); } } From a9aedbc785f823e6071fb4a9ece880899950bb0d Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sat, 9 Sep 2023 18:38:52 +1000 Subject: [PATCH 10/32] got mobs to stop when firing --- .../csse3200/game/areas/ForestGameArea.java | 10 ++--- .../game/components/tasks/MobAttackTask.java | 42 +++++++++++++++---- 2 files changed, 38 insertions(+), 14 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 94146d3ea..fc6fcd736 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -134,9 +134,9 @@ public void create() { displayUI(); spawnTerrain(); - spawnBuilding1(); - spawnBuilding2(); - spawnMountains(); +// spawnBuilding1(); +// spawnBuilding2(); +// spawnMountains(); player = spawnPlayer(); player.getEvents().addListener("spawnWave", this::spawnXenoGrunts); @@ -149,9 +149,9 @@ public void create() { spawnXenoGrunts(); spawnGhosts(); - spawnWeaponTower(); +// spawnWeaponTower(); spawnIncome(); - spawnScrap(); +// spawnScrap(); bossKing1 = spawnBossKing1(); bossKing2 = spawnBossKing2(); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 45632f99c..51d727bfe 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -8,6 +8,7 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.services.GameTime; @@ -66,10 +67,11 @@ public void start() { super.start(); startTime = timeSource.getTime(); this.mobPosition = owner.getEntity().getCenterPosition(); - this.maxRangePosition.set(0, mobPosition.y); + this.maxRangePosition.set(4, mobPosition.y); owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); owner.getEntity().getEvents().trigger("shootStart"); + System.out.println("mob attack started for " + owner.getEntity().getId()); } /** @@ -95,9 +97,9 @@ public void updateMobState() { // if (statsComp != null) { // System.out.println("is the target visible " + isTargetVisible()); // } - if (!isTargetVisible()) { - System.out.println("target is not visible for " + owner.getEntity().getId()); - } +// if (!isTargetVisible()) { +// System.out.println("target is not visible for " + owner.getEntity().getId()); +// } switch (mobState) { case IDLE -> { @@ -106,6 +108,8 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } + System.out.println("idle for " + owner.getEntity().getId()); + } case DEPLOY -> { @@ -113,13 +117,18 @@ public void updateMobState() { if (isTargetVisible()) { owner.getEntity().getEvents().trigger(FIRING); mobState = STATE.FIRING; + owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); } else { owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; + } + System.out.println("deploying for " + owner.getEntity().getId()); + } case FIRING -> { +// owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); // targets gone - stop firing if (!isTargetVisible()) { owner.getEntity().getEvents().trigger(STOW); @@ -133,6 +142,9 @@ public void updateMobState() { mobState = STATE.STOW; owner.getEntity().getEvents().trigger("shootStart"); } + System.out.println("firing for " + owner.getEntity().getId()); + owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); + } case STOW -> { @@ -144,6 +156,8 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(IDLE); mobState = STATE.IDLE; } + System.out.println("stowing for " + owner.getEntity().getId()); + } } } @@ -153,8 +167,14 @@ public void updateMobState() { */ @Override public void stop() { - super.stop(); - owner.getEntity().getEvents().trigger(STOW); + if (mobState == STATE.FIRING || mobState == STATE.DEPLOY) { + this.updateMobState(); + } else { +// owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); + System.out.println("mob attack stopped for " + owner.getEntity().getId()); + super.stop(); + owner.getEntity().getEvents().trigger(STOW); + } } /** @@ -176,7 +196,7 @@ public int getPriority() { * @return (int) active priority if a target is visible, -1 otherwise */ private int getActivePriority() { - if ((startTime + delay) < timeSource.getTime()) { + if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { // if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) { // System.out.println("ready to fire while active"); return priority; @@ -192,7 +212,7 @@ private int getActivePriority() { */ private int getInactivePriority() { // return isTargetVisible() ? priority : 0; - if ((startTime + delay) < timeSource.getTime()) { + if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { // if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) { // System.out.println("ready to fire while inactive"); return priority; @@ -207,6 +227,10 @@ private int getInactivePriority() { * @return true if a target is visible, false otherwise */ private boolean isTargetVisible() { - return physics.raycast(mobPosition, maxRangePosition, TARGET, hit); + Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); + return physics.raycast(owner.getEntity().getPosition(), newVector, TARGET, hit); } + +// private boolean meleeOrProjectile() { +// } } From 0aa993a882e3a9aba76b33a7897c870d9b0df915 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 18:50:53 +1000 Subject: [PATCH 11/32] Removed extra print statements for testing and moved position of mobball --- .../game/components/tasks/MobAttackTask.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 08f07f7c7..835786ea0 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -20,7 +20,6 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final int INTERVAL = 1; // time interval to scan for towers in private static final short TARGET = PhysicsLayer.HUMANS; // mobs detecting for towers - // ^ fix this // private static final String STOW = "stowStart"; // private static final String DEPLOY = "deployStart"; @@ -101,13 +100,10 @@ public void updateMobState() { case IDLE -> { if (isTargetVisible()) { - System.out.println("IDLE: target visible for " + owner.getEntity().getId()); // targets detected in idle mode - start deployment //owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.FIRING; - } - else { - System.out.println("IDLE: target not visible for " + owner.getEntity().getId()); + owner.getEntity().getEvents().trigger(FIRING); } } @@ -128,14 +124,11 @@ public void updateMobState() { if (!isTargetVisible()) { //owner.getEntity().getEvents().trigger(STOW); mobState = STATE.IDLE; - System.out.println("FIRING: target not visible for " + owner.getEntity().getId()); } else { owner.getEntity().getEvents().trigger(FIRING); - Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); + Entity newProjectile = ProjectileFactory.createMobBall(TARGET, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x - 1), (float) (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); -// mobState = STATE.IDLE; - System.out.println("FIRING: target visible for " + owner.getEntity().getId()); owner.getEntity().getEvents().trigger(FIRING); } } From 111f0225f57e6722d608179eedd8e9c2df8e77db Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:03:25 +1000 Subject: [PATCH 12/32] Fixed build errors of missing commas --- .../src/main/com/csse3200/game/areas/ForestGameArea.java | 5 +++-- .../com/csse3200/game/components/tasks/MobAttackTask.java | 4 ++-- 2 files changed, 5 insertions(+), 4 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 edade1e2a..ab782d5dd 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -93,10 +93,11 @@ public class ForestGameArea extends GameArea { "images/economy/crystal.png", "images/economy/econ-tower.png", "images/towers/mine_tower.png", - "images/towers/TNTTower.png" + "images/towers/TNTTower.png", "images/economy/scrap.png", "images/towers/mine_tower.png" }; + private static final String[] forestTextureAtlases = { "images/economy/econ-tower.atlas", "images/terrain_iso_grass.atlas", @@ -109,7 +110,7 @@ public class ForestGameArea extends GameArea { "images/mobs/rangeBossRight.atlas", "images/towers/TNTTower.atlas", "images/projectiles/basic_projectile.atlas", - "images/projectiles/mobProjectile.atlas" + "images/projectiles/mobProjectile.atlas", "images/mobs/rangeBossRight.atlas" }; private static final String[] forestSounds = { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 3fcf0692d..222067a12 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -22,8 +22,8 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final int INTERVAL = 1; // time interval to scan for towers in private static final short TARGET = PhysicsLayer.HUMANS; // mobs detecting for towers -// private static final String STOW = "stowStart"; -// private static final String DEPLOY = "deployStart"; + private static final String STOW = "stowStart"; + private static final String DEPLOY = "deployStart"; private static final String FIRING = "shootStart"; private static final String IDLE = "idleStart"; From bde19c525992292901d2732031a020b9c1ee2c9c Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sat, 9 Sep 2023 19:11:01 +1000 Subject: [PATCH 13/32] created raycast function to find fixture --- .../game/components/tasks/MobAttackTask.java | 12 ++++++++++-- .../com/csse3200/game/physics/PhysicsEngine.java | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 51d727bfe..a533d69b5 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tasks; +import com.badlogic.gdx.physics.box2d.Fixture; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.CombatStatsComponent; @@ -144,6 +145,7 @@ public void updateMobState() { } System.out.println("firing for " + owner.getEntity().getId()); owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); + System.out.println("the fixture for " + owner.getEntity().getId() + " is " + this.meleeOrProjectile()); } @@ -231,6 +233,12 @@ private boolean isTargetVisible() { return physics.raycast(owner.getEntity().getPosition(), newVector, TARGET, hit); } -// private boolean meleeOrProjectile() { -// } + private Fixture meleeOrProjectile() { +// RaycastHit[] hits = physics.raycastAll(owner.getEntity().getPosition(), new Vector2(0, 0), TARGET); +// owner.getEntity().getComponent(CombatStatsComponent.class); + Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); + Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET, hit); + System.out.println("hit fixture if worked is: " + hitraycast); + return hitraycast; + } } diff --git a/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java b/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java index f4db690cb..90e612cae 100644 --- a/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java +++ b/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java @@ -141,6 +141,13 @@ public boolean raycast(Vector2 from, Vector2 to, short layerMask, RaycastHit hit return singleHitCallback.didHit; } + public Fixture raycastGetHit(Vector2 from, Vector2 to, short layerMask, RaycastHit hit) { + singleHitCallback.didHit = false; + singleHitCallback.layerMask = layerMask; + world.rayCast(singleHitCallback, from, to); + return singleHitCallback.hit.fixture; + } + /** * Cast a ray in a straight line from one point to another, checking for all collision against * colliders in the specified layers. From 88086709491d26e14dc49f9ee2563957aa7e9618 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:11:19 +1000 Subject: [PATCH 14/32] Commented out some spawning of entities for testing purposes --- .../core/src/main/com/csse3200/game/areas/ForestGameArea.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 ab782d5dd..97959bbdf 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -169,8 +169,8 @@ public void create() { spawnWeaponTower(); spawnEngineer(); spawnWeaponTower(); - spawnIncome(); - spawnScrap(); +// spawnIncome(); +// spawnScrap(); bossKing1 = spawnBossKing1(); bossKing2 = spawnBossKing2(); From da3b8047566964b840853e9bf4a8e01effcaaf81 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:48:32 +1000 Subject: [PATCH 15/32] Fixed issues with mob not stopping when moving --- .../game/components/tasks/MobAttackTask.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 6061c339c..834e2a6e7 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -22,6 +22,7 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final int INTERVAL = 1; // time interval to scan for towers in private static final short TARGET = PhysicsLayer.HUMANS; // mobs detecting for towers + // ^ fix this private static final String STOW = "stowStart"; private static final String DEPLOY = "deployStart"; @@ -70,7 +71,7 @@ public void start() { this.maxRangePosition.set(4, mobPosition.y); owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); - owner.getEntity().getEvents().trigger("shootStart"); +// owner.getEntity().getEvents().trigger(FIRING); System.out.println("mob attack started for " + owner.getEntity().getId()); } @@ -82,7 +83,7 @@ public void start() { public void update() { updateMobState(); - if (mobState == STATE.IDLE) { + if (mobState == STATE.STOW) { status = Status.FINISHED; } } @@ -105,9 +106,8 @@ public void updateMobState() { case IDLE -> { if (isTargetVisible()) { // targets detected in idle mode - start deployment - //owner.getEntity().getEvents().trigger(DEPLOY); - mobState = STATE.FIRING; - owner.getEntity().getEvents().trigger(FIRING); + owner.getEntity().getEvents().trigger(DEPLOY); + mobState = STATE.DEPLOY; } System.out.println("idle for " + owner.getEntity().getId()); @@ -132,14 +132,14 @@ public void updateMobState() { // owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); // targets gone - stop firing if (!isTargetVisible()) { - //owner.getEntity().getEvents().trigger(STOW); - mobState = STATE.IDLE; + owner.getEntity().getEvents().trigger(STOW); + mobState = STATE.STOW; } else { owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(TARGET, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x - 1), (float) (owner.getEntity().getPosition().y)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x - 0.5), (float) (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); - owner.getEntity().getEvents().trigger(FIRING); + mobState = STATE.STOW; } System.out.println("firing for " + owner.getEntity().getId()); owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); @@ -196,11 +196,11 @@ public int getPriority() { * @return (int) active priority if a target is visible, -1 otherwise */ private int getActivePriority() { - if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { + if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { // if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) { // System.out.println("ready to fire while active"); - return priority; - } + return priority; + } // System.out.println("not ready to fire while active"); // return !isTargetVisible() ? -1 : priority; return -1; From 4d3ab823b6caa4caaabc3e48437718537b877a0e Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Sun, 10 Sep 2023 10:54:11 +1000 Subject: [PATCH 16/32] Animation checks added to XenoAnimation controller to assist with animation timing. --- .../components/npc/XenoAnimationController.java | 13 ++++++++++++- .../game/components/tasks/MobAttackTask.java | 2 ++ .../game/entities/factories/NPCFactory.java | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java index efe0858b4..d8eaa7be5 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/XenoAnimationController.java @@ -1,8 +1,11 @@ package com.csse3200.game.components.npc; +import com.badlogic.gdx.graphics.g2d.Animation; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import java.util.Objects; + /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. @@ -24,26 +27,34 @@ public void create() { } void animateRun() { - animator.startAnimation("xeno_run"); + if (!Objects.equals(animator.getCurrentAnimation(), "xeno_shoot")) { + animator.stopAnimation(); + animator.startAnimation("xeno_run"); + } } void animateHurt() { + animator.stopAnimation(); animator.startAnimation("xeno_hurt"); } void animateShoot() { + animator.stopAnimation(); animator.startAnimation("xeno_shoot"); } void animateMelee1() { + animator.stopAnimation(); animator.startAnimation("xeno_melee_1"); } void animateMelee2() { + animator.stopAnimation(); animator.startAnimation("xeno_melee_2"); } void animateDie() { + animator.stopAnimation(); animator.startAnimation("xeno_die"); } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index e696a39d2..4a1b808f9 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -9,6 +9,7 @@ import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.raycast.RaycastHit; +import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.services.GameTime; import com.csse3200.game.entities.factories.ProjectileFactory; @@ -125,6 +126,7 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } else { + System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index b5f5c4dc7..ef50acb70 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -128,7 +128,7 @@ public static Entity createXenoGrunt(Entity target) { .addComponent(animator) .addComponent(new XenoAnimationController()); -// xenoGrunt.getComponent(AnimationRenderComponent.class).scaleEntity(); + xenoGrunt.getComponent(AnimationRenderComponent.class).scaleEntity(); return xenoGrunt; } From bb66ce40e658ccefc2c340cd17e83a8df12a06a3 Mon Sep 17 00:00:00 2001 From: max9753 Date: Sun, 10 Sep 2023 11:33:30 +1000 Subject: [PATCH 17/32] Added death animation and currency dropping to the WanderTask.java. Mobs will now die when shot & drop currency. --- .../game/components/tasks/WanderTask.java | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java b/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java index 6fd754880..088d32775 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java @@ -1,13 +1,25 @@ package com.csse3200.game.components.tasks; +import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.ai.tasks.Task; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.components.CombatStatsComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.components.ColliderComponent; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.utils.math.RandomUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.TimeUnit; + /** * Wander around by moving a random position within a range of the starting position. Wait a little * bit between movements. Requires an entity with a PhysicsMovementComponent. @@ -21,6 +33,8 @@ public class WanderTask extends DefaultTask implements PriorityTask { private MovementTask movementTask; private WaitTask waitTask; private Task currentTask; + private boolean isDead = false; + private Vector2 mobPosition; /** * @param wanderRange Distance in X and Y the entity can move from its position when start() is @@ -58,14 +72,47 @@ public void start() { @Override public void update() { - if (currentTask.getStatus() != Status.ACTIVE) { - if (currentTask == movementTask) { - startWaiting(); - } else { - startMoving(); + + //Update the position of the mob + mobPosition = owner.getEntity().getPosition(); + + // If the mob is at zero health, kill the mob, + // play the death animation and stop the task + // This method is the idea of Ahmad who very kindly helped + // with section, massive props to him for his help! + if (!isDead && owner.getEntity().getComponent(CombatStatsComponent.class).isDead()) { + owner.getEntity().getEvents().trigger("dieStart"); + //owner.getEntity().getComponent(ColliderComponent.class).setLayer(PhysicsLayer.NONE); + //owner.getEntity().getComponent(HitboxComponent.class).setLayer(PhysicsLayer.NONE); + currentTask.stop(); + isDead = true; + } + + // Check if the mob has finished death animation + else if (isDead && owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { + + // Drop scrap at the mobs location for player + // to collect. + Entity scrap = DropFactory.createScrapDrop(); + scrap.setPosition(mobPosition.x,mobPosition.y); + ServiceLocator.getEntityService().register(scrap); + + // Delete the mob. + owner.getEntity().setFlagForDelete(true); + + } + // If not dead, do normal things... + else if (!isDead) { + + if (currentTask.getStatus() != Status.ACTIVE) { + if (currentTask == movementTask) { + startWaiting(); + } else { + startMoving(); + } } + currentTask.update(); } - currentTask.update(); } private void startWaiting() { From c2c873c11663282aa102f8b465e0e5007e5bb3cb Mon Sep 17 00:00:00 2001 From: max9753 Date: Sun, 10 Sep 2023 11:37:14 +1000 Subject: [PATCH 18/32] Added comments to abandoned MobDeathTask.java --- .../com/csse3200/game/components/tasks/MobDeathTask.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java index f04ad39a0..e10ebc0bd 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java @@ -16,7 +16,14 @@ /** - * Task that prints a message to the terminal whenever it is called. + * THIS TASK IS NO LONGER USED. It may be deleted at a later date. + * Do not read this aweful task. + * + * DOES NOT DO ANYTHING. + * + * This task didn't work with the Wander & ShootTasks, + * and then it was + * decided to have mob death in wanderTask. */ public class MobDeathTask extends DefaultTask implements PriorityTask { private static final int INTERVAL = 1; // time interval to scan for towers in From 72c1ca409cada9d94c1de2911844135cd3fa9e44 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Sun, 10 Sep 2023 12:24:03 +1000 Subject: [PATCH 19/32] Changed the hitbox properties of the NPC entities to suit the Xeno --- .../game/components/tasks/MobAttackTask.java | 22 +++++++++---------- .../game/entities/factories/NPCFactory.java | 7 +++--- .../csse3200/game/physics/PhysicsLayer.java | 1 + .../csse3200/game/physics/PhysicsUtils.java | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 4a1b808f9..aff533638 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -23,7 +23,7 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final short TARGET = PhysicsLayer.OBSTACLE; // mobs detecting for towers // ^ fix this - private static final String STOW = "stowStart"; + private static final String STOW = "wanderStart"; private static final String DEPLOY = "deployStart"; private static final String FIRING = "shootStart"; private static final String IDLE = "idleStart"; @@ -68,9 +68,8 @@ public void start() { startTime = timeSource.getTime(); this.mobPosition = owner.getEntity().getCenterPosition(); this.maxRangePosition.set(0, mobPosition.y); - owner.getEntity().getEvents().trigger(IDLE); + //owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); - owner.getEntity().getEvents().trigger("shootStart"); } /** @@ -104,7 +103,7 @@ public void updateMobState() { case IDLE -> { if (isTargetVisible()) { // targets detected in idle mode - start deployment - owner.getEntity().getEvents().trigger(DEPLOY); + //owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } } @@ -112,10 +111,10 @@ public void updateMobState() { case DEPLOY -> { // currently deploying, if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(FIRING); + //owner.getEntity().getEvents().trigger(FIRING); mobState = STATE.FIRING; } else { - owner.getEntity().getEvents().trigger(STOW); + //owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } } @@ -123,15 +122,16 @@ public void updateMobState() { case FIRING -> { // targets gone - stop firing if (!isTargetVisible()) { - owner.getEntity().getEvents().trigger(STOW); + //owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } else { - System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); - owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); newProjectile.setScale(-1f, 0.5f); ServiceLocator.getEntityService().register(newProjectile); + + System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); + owner.getEntity().getEvents().trigger(FIRING); mobState = STATE.STOW; } } @@ -139,10 +139,10 @@ public void updateMobState() { case STOW -> { // currently stowing if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(DEPLOY); + //owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } else { - owner.getEntity().getEvents().trigger(IDLE); + //owner.getEntity().getEvents().trigger(IDLE); mobState = STATE.IDLE; } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index ef50acb70..31485fe72 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -128,6 +128,7 @@ public static Entity createXenoGrunt(Entity target) { .addComponent(animator) .addComponent(new XenoAnimationController()); + xenoGrunt.getComponent(HitboxComponent.class).setAsBoxAligned(new Vector2(.3f, .5f), PhysicsComponent.AlignX.RIGHT, PhysicsComponent.AlignY.BOTTOM); xenoGrunt.getComponent(AnimationRenderComponent.class).scaleEntity(); return xenoGrunt; @@ -149,11 +150,11 @@ public static Entity createBaseNPC(Entity target) { .addComponent(new PhysicsComponent()) .addComponent(new PhysicsMovementComponent()) .addComponent(new ColliderComponent()) - .addComponent(new HitboxComponent().setLayer(PhysicsLayer.NPC)) - .addComponent(new TouchAttackComponent(PhysicsLayer.HUMANS, 1.5f)) + .addComponent(new HitboxComponent().setLayer(PhysicsLayer.XENO)) + .addComponent(new TouchAttackComponent(PhysicsLayer.HUMANS)) .addComponent(aiComponent); - PhysicsUtils.setScaledCollider(npc, 0.9f, 0.4f); + PhysicsUtils.setScaledCollider(npc, 0.3f, 0.5f); return npc; } diff --git a/source/core/src/main/com/csse3200/game/physics/PhysicsLayer.java b/source/core/src/main/com/csse3200/game/physics/PhysicsLayer.java index 73c5904aa..b91b9bfcc 100644 --- a/source/core/src/main/com/csse3200/game/physics/PhysicsLayer.java +++ b/source/core/src/main/com/csse3200/game/physics/PhysicsLayer.java @@ -11,6 +11,7 @@ public class PhysicsLayer { public static final short PROJECTILE = (1 << 4); public static final short TOWER = (1 << 5); + public static final short XENO = (1 << 3); public static final short HUMANS = (1 << 1) | (1 << 5); public static final short ALL = ~0; diff --git a/source/core/src/main/com/csse3200/game/physics/PhysicsUtils.java b/source/core/src/main/com/csse3200/game/physics/PhysicsUtils.java index 44936b077..168065d1b 100644 --- a/source/core/src/main/com/csse3200/game/physics/PhysicsUtils.java +++ b/source/core/src/main/com/csse3200/game/physics/PhysicsUtils.java @@ -13,7 +13,7 @@ public static void setScaledCollider(Entity entity, float scaleX, float scaleY) entity .getComponent(ColliderComponent.class) .setAsBoxAligned( - boundingBox, PhysicsComponent.AlignX.CENTER, PhysicsComponent.AlignY.BOTTOM); + boundingBox, PhysicsComponent.AlignX.RIGHT, PhysicsComponent.AlignY.BOTTOM); } private PhysicsUtils() { From f8102bf08640f040d8c1f944eeb3b3af9ab6d0d6 Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sun, 10 Sep 2023 13:23:18 +1000 Subject: [PATCH 20/32] for each attack task start, choose between melee and projectiles --- .../csse3200/game/areas/ForestGameArea.java | 12 ++--- .../game/components/CombatStatsComponent.java | 8 +++ .../game/components/TouchAttackComponent.java | 12 +++++ .../game/components/tasks/MobAttackTask.java | 52 +++++++++++-------- .../game/entities/PredefinedWeapons.java | 12 +++-- .../game/entities/factories/NPCFactory.java | 4 +- 6 files changed, 67 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 fc6fcd736..ea814d49c 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -134,9 +134,9 @@ public void create() { displayUI(); spawnTerrain(); -// spawnBuilding1(); -// spawnBuilding2(); -// spawnMountains(); + spawnBuilding1(); + spawnBuilding2(); + spawnMountains(); player = spawnPlayer(); player.getEvents().addListener("spawnWave", this::spawnXenoGrunts); @@ -148,10 +148,10 @@ public void create() { spawnMultiProjectile(new Vector2(0, 10), player, towardsMobs, 20, new Vector2(2f, 2f), 7); spawnXenoGrunts(); - spawnGhosts(); -// spawnWeaponTower(); +// spawnGhosts(); + spawnWeaponTower(); spawnIncome(); -// spawnScrap(); + spawnScrap(); bossKing1 = spawnBossKing1(); bossKing2 = spawnBossKing2(); diff --git a/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java b/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java index 282deac9b..665896bd7 100644 --- a/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java @@ -218,4 +218,12 @@ public void changeState() { public String getState() { return this.state; } + + public ArrayList getCloseRangeAbilities() { + return this.closeRangeAbilities; + } + + public ArrayList getLongRangeAbilities() { + return this.longRangeAbilities; + } } diff --git a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java index 152f49c91..7f6cc73e4 100644 --- a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java +++ b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.Fixture; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.Weapon; import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.HitboxComponent; @@ -100,6 +101,17 @@ private void onCollisionStart(Fixture me, Fixture other) { } } + public Weapon chooseWeapon(Fixture other) { + Entity target = ((BodyUserData) other.getBody().getUserData()).entity; +// System.out.println("Target is " + target); + Weapon weapon = null; + if (target.getComponent(CombatStatsComponent.class) != null) { +// System.out.println("Combat stats are " + combatStats.getCloseRangeAbilities() + " " + combatStats.getLongRangeAbilities()); + weapon = combatStats.getWeapon(target); + } + return weapon; + } + private void onCollisionEnd(Fixture me, Fixture other) { // Nothing to do on collision end } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index a533d69b5..7c72820f0 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -7,6 +7,9 @@ import com.csse3200.game.components.TouchAttackComponent; import com.csse3200.game.entities.Entity; import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.entities.Melee; +import com.csse3200.game.entities.Weapon; +import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.PhysicsMovementComponent; @@ -72,7 +75,7 @@ public void start() { owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); owner.getEntity().getEvents().trigger("shootStart"); - System.out.println("mob attack started for " + owner.getEntity().getId()); +// System.out.println("mob attack started for " + owner.getEntity().getId()); } /** @@ -109,7 +112,7 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } - System.out.println("idle for " + owner.getEntity().getId()); +// System.out.println("idle for " + owner.getEntity().getId()); } @@ -124,17 +127,18 @@ public void updateMobState() { mobState = STATE.STOW; } - System.out.println("deploying for " + owner.getEntity().getId()); +// System.out.println("deploying for " + owner.getEntity().getId()); } case FIRING -> { // owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); // targets gone - stop firing - if (!isTargetVisible()) { + if (!isTargetVisible() || this.meleeOrProjectile() == null) { owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } else { + System.out.println("weapon chosen is " + this.meleeOrProjectile()); owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createFireBall(owner.getEntity(), new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); @@ -145,7 +149,8 @@ public void updateMobState() { } System.out.println("firing for " + owner.getEntity().getId()); owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); - System.out.println("the fixture for " + owner.getEntity().getId() + " is " + this.meleeOrProjectile()); +// this.meleeOrProjectile(); +// System.out.println("the fixture for " + owner.getEntity().getId() + " is " + this.meleeOrProjectile()); } @@ -158,7 +163,7 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(IDLE); mobState = STATE.IDLE; } - System.out.println("stowing for " + owner.getEntity().getId()); +// System.out.println("stowing for " + owner.getEntity().getId()); } } @@ -173,7 +178,7 @@ public void stop() { this.updateMobState(); } else { // owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); - System.out.println("mob attack stopped for " + owner.getEntity().getId()); +// System.out.println("mob attack stopped for " + owner.getEntity().getId()); super.stop(); owner.getEntity().getEvents().trigger(STOW); } @@ -190,7 +195,6 @@ public int getPriority() { return getActivePriority(); } return getInactivePriority(); -// return isTargetVisible() ? getActivePriority() : getInactivePriority(); } /** @@ -199,12 +203,8 @@ public int getPriority() { */ private int getActivePriority() { if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { -// if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) { -// System.out.println("ready to fire while active"); return priority; } -// System.out.println("not ready to fire while active"); -// return !isTargetVisible() ? -1 : priority; return -1; } @@ -213,15 +213,10 @@ private int getActivePriority() { * @return (int) -1 if a target is not visible, active priority otherwise */ private int getInactivePriority() { -// return isTargetVisible() ? priority : 0; if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { -// if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) { -// System.out.println("ready to fire while inactive"); return priority; } return -1; -// System.out.println("not ready to fire while inactive"); -// return isTargetVisible() ? priority : -1; } /** @@ -233,12 +228,25 @@ private boolean isTargetVisible() { return physics.raycast(owner.getEntity().getPosition(), newVector, TARGET, hit); } - private Fixture meleeOrProjectile() { -// RaycastHit[] hits = physics.raycastAll(owner.getEntity().getPosition(), new Vector2(0, 0), TARGET); -// owner.getEntity().getComponent(CombatStatsComponent.class); + /** + * Uses a custom raycast method to find the closest target to the mob. Based on the distance to the + * target, the mob will choose a weapon to attack with. + * + * If the object does not have a CombatStatsComponent (which handles dealing damage etc), then + * the function will return null. If it returns null when the mob is in state FIRING or DEPLOY, it will not fire + * and will STOW. + * */ + private Weapon meleeOrProjectile() { Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET, hit); - System.out.println("hit fixture if worked is: " + hitraycast); - return hitraycast; + TouchAttackComponent comp = owner.getEntity().getComponent(TouchAttackComponent.class); + Weapon chosenWeapon = null; + if (comp != null) { + chosenWeapon = comp.chooseWeapon(hitraycast); + if (chosenWeapon != null) { + } + } + + return chosenWeapon; } } diff --git a/source/core/src/main/com/csse3200/game/entities/PredefinedWeapons.java b/source/core/src/main/com/csse3200/game/entities/PredefinedWeapons.java index a9be6e6c4..5955f34f6 100644 --- a/source/core/src/main/com/csse3200/game/entities/PredefinedWeapons.java +++ b/source/core/src/main/com/csse3200/game/entities/PredefinedWeapons.java @@ -1,5 +1,8 @@ package com.csse3200.game.entities; +import com.csse3200.game.entities.configs.NPCConfigs; +import com.csse3200.game.entities.configs.ProjectileConfig; + public class PredefinedWeapons { // Melee attacks public static Melee sword = new Melee(10, 4, "fire", 1, 1); @@ -7,8 +10,11 @@ public class PredefinedWeapons { public static Melee axe = new Melee(9, 3, "fire", 1, 1); public static Melee kick = new Melee(2, 1, "earth", 1, 1); + public static ProjectileConfig fireBall = new ProjectileConfig(); + public static ProjectileConfig frostBall = new ProjectileConfig(); + // Projectile attacks TODO: change Weapon and Melee to Projectile class - public static Weapon fireBall = new Melee(9, 20, "fire", 1, 1); - public static Weapon frostBall = new Melee(6, 20, "ice", 1, 1); - public static Weapon hurricane = new Melee(7, 20, "air", 1, 1); +// public static Weapon fireBall = new Melee(9, 20, "fire", 1, 1); +// public static Weapon frostBall = new Melee(6, 20, "ice", 1, 1); +// public static Weapon hurricane = new Melee(7, 20, "air", 1, 1); } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 316cf8190..16fd70a44 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -109,8 +109,8 @@ public static Entity createXenoGrunt(Entity target) { Entity xenoGrunt = createBaseNPC(target); BaseEnemyConfig config = configs.xenoGrunt; ArrayList melee = new ArrayList<>(Arrays.asList(PredefinedWeapons.sword, PredefinedWeapons.kick)); - ArrayList projectiles = new ArrayList<>(); -// ArrayList projectiles = new ArrayList<>(Arrays.asList(PredefinedWeapons.fireBall, PredefinedWeapons.hurricane)); +// ArrayList projectiles = new ArrayList<>(); + ArrayList projectiles = new ArrayList<>(Arrays.asList(PredefinedWeapons.fireBall, PredefinedWeapons.frostBall)); // ArrayList drops = new ArrayList<>(Arrays.asList(1, 2)); ArrayList drops = new ArrayList<>(); From 9372179be337ee46c73f6255c4cbc40073c9063b Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sun, 10 Sep 2023 13:28:45 +1000 Subject: [PATCH 21/32] clean up --- .../game/components/CombatStatsComponent.java | 8 ------ .../game/components/TouchAttackComponent.java | 2 -- .../game/components/tasks/MobAttackTask.java | 28 +++---------------- .../game/entities/factories/NPCFactory.java | 3 +- .../csse3200/game/physics/PhysicsEngine.java | 13 ++++++++- 5 files changed, 17 insertions(+), 37 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java b/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java index 665896bd7..282deac9b 100644 --- a/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/CombatStatsComponent.java @@ -218,12 +218,4 @@ public void changeState() { public String getState() { return this.state; } - - public ArrayList getCloseRangeAbilities() { - return this.closeRangeAbilities; - } - - public ArrayList getLongRangeAbilities() { - return this.longRangeAbilities; - } } diff --git a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java index 7f6cc73e4..9d5f46787 100644 --- a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java +++ b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java @@ -103,10 +103,8 @@ private void onCollisionStart(Fixture me, Fixture other) { public Weapon chooseWeapon(Fixture other) { Entity target = ((BodyUserData) other.getBody().getUserData()).entity; -// System.out.println("Target is " + target); Weapon weapon = null; if (target.getComponent(CombatStatsComponent.class) != null) { -// System.out.println("Combat stats are " + combatStats.getCloseRangeAbilities() + " " + combatStats.getLongRangeAbilities()); weapon = combatStats.getWeapon(target); } return weapon; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 7c72820f0..703fccf29 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -75,7 +75,6 @@ public void start() { owner.getEntity().getEvents().trigger(IDLE); endTime = timeSource.getTime() + (INTERVAL * 500); owner.getEntity().getEvents().trigger("shootStart"); -// System.out.println("mob attack started for " + owner.getEntity().getId()); } /** @@ -96,14 +95,6 @@ public void update() { * triggers the appropriate events corresponding to the STATE enum. */ public void updateMobState() { -// TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class); - CombatStatsComponent statsComp = owner.getEntity().getComponent(CombatStatsComponent.class); -// if (statsComp != null) { -// System.out.println("is the target visible " + isTargetVisible()); -// } -// if (!isTargetVisible()) { -// System.out.println("target is not visible for " + owner.getEntity().getId()); -// } switch (mobState) { case IDLE -> { @@ -112,8 +103,6 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } -// System.out.println("idle for " + owner.getEntity().getId()); - } case DEPLOY -> { @@ -127,18 +116,14 @@ public void updateMobState() { mobState = STATE.STOW; } -// System.out.println("deploying for " + owner.getEntity().getId()); - } case FIRING -> { -// owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); - // targets gone - stop firing + // targets gone or cannot be attacked - stop firing if (!isTargetVisible() || this.meleeOrProjectile() == null) { owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } else { - System.out.println("weapon chosen is " + this.meleeOrProjectile()); owner.getEntity().getEvents().trigger(FIRING); Entity newProjectile = ProjectileFactory.createFireBall(owner.getEntity(), new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); @@ -147,10 +132,7 @@ public void updateMobState() { mobState = STATE.STOW; owner.getEntity().getEvents().trigger("shootStart"); } - System.out.println("firing for " + owner.getEntity().getId()); owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); -// this.meleeOrProjectile(); -// System.out.println("the fixture for " + owner.getEntity().getId() + " is " + this.meleeOrProjectile()); } @@ -163,8 +145,6 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(IDLE); mobState = STATE.IDLE; } -// System.out.println("stowing for " + owner.getEntity().getId()); - } } } @@ -177,8 +157,6 @@ public void stop() { if (mobState == STATE.FIRING || mobState == STATE.DEPLOY) { this.updateMobState(); } else { -// owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); -// System.out.println("mob attack stopped for " + owner.getEntity().getId()); super.stop(); owner.getEntity().getEvents().trigger(STOW); } @@ -235,10 +213,12 @@ private boolean isTargetVisible() { * If the object does not have a CombatStatsComponent (which handles dealing damage etc), then * the function will return null. If it returns null when the mob is in state FIRING or DEPLOY, it will not fire * and will STOW. + * + * returns the Weapon (Melee or Projectile) the mob will use to attack the target. null if immune target or no target * */ private Weapon meleeOrProjectile() { Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); - Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET, hit); + Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); TouchAttackComponent comp = owner.getEntity().getComponent(TouchAttackComponent.class); Weapon chosenWeapon = null; if (comp != null) { diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 16fd70a44..341813d08 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -109,9 +109,8 @@ public static Entity createXenoGrunt(Entity target) { Entity xenoGrunt = createBaseNPC(target); BaseEnemyConfig config = configs.xenoGrunt; ArrayList melee = new ArrayList<>(Arrays.asList(PredefinedWeapons.sword, PredefinedWeapons.kick)); -// ArrayList projectiles = new ArrayList<>(); + // tester projectiles ArrayList projectiles = new ArrayList<>(Arrays.asList(PredefinedWeapons.fireBall, PredefinedWeapons.frostBall)); -// ArrayList drops = new ArrayList<>(Arrays.asList(1, 2)); ArrayList drops = new ArrayList<>(); AnimationRenderComponent animator = diff --git a/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java b/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java index 90e612cae..da7bbf2b6 100644 --- a/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java +++ b/source/core/src/main/com/csse3200/game/physics/PhysicsEngine.java @@ -141,7 +141,18 @@ public boolean raycast(Vector2 from, Vector2 to, short layerMask, RaycastHit hit return singleHitCallback.didHit; } - public Fixture raycastGetHit(Vector2 from, Vector2 to, short layerMask, RaycastHit hit) { + + /** + * Cast a ray in a straight line from one point to another, checking for a collision + * against colliders in the specified layers. + * + * @param from The starting point of the ray. + * @param to The end point of the ray. + * @param layerMask The physics layer mask which specifies layers that can be hit. Other layers + * will be ignored. + * @return The fixture of the closest collider hit by the ray, or null if no collider was hit. + * */ + public Fixture raycastGetHit(Vector2 from, Vector2 to, short layerMask) { singleHitCallback.didHit = false; singleHitCallback.layerMask = layerMask; world.rayCast(singleHitCallback, from, to); From f832a84343c6c506afaabb18605d6c7418ff4fae Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sun, 10 Sep 2023 13:30:49 +1000 Subject: [PATCH 22/32] will only activate shoot task if target is attackable --- .../com/csse3200/game/components/tasks/MobAttackTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 703fccf29..4d7ac4690 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -180,7 +180,7 @@ public int getPriority() { * @return (int) active priority if a target is visible, -1 otherwise */ private int getActivePriority() { - if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { + if ((startTime + delay) < timeSource.getTime() && isTargetVisible() && this.meleeOrProjectile() != null) { return priority; } return -1; @@ -191,7 +191,7 @@ private int getActivePriority() { * @return (int) -1 if a target is not visible, active priority otherwise */ private int getInactivePriority() { - if ((startTime + delay) < timeSource.getTime() && isTargetVisible()) { + if ((startTime + delay) < timeSource.getTime() && isTargetVisible() && this.meleeOrProjectile() != null) { return priority; } return -1; From b4ebcc1b21ddd406fa03881a3e0c22e974333844 Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sun, 10 Sep 2023 15:51:22 +1000 Subject: [PATCH 23/32] mobs stopping when shooting again and fixed spawning coordinates --- .../com/csse3200/game/areas/ForestGameArea.java | 4 ++-- .../game/components/tasks/MobAttackTask.java | 16 +++++++--------- 2 files changed, 9 insertions(+), 11 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 df0b0302b..0006c54f2 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -336,8 +336,8 @@ private void spawnProjectile(Vector2 position, short targetLayer, int space, in private void spawnXenoGrunts() { - GridPoint2 minPos = terrain.getMapBounds(0).sub(1, 5); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(1, 25); + GridPoint2 minPos = terrain.getMapBounds(0).sub(1, 0); + GridPoint2 maxPos = terrain.getMapBounds(0).sub(1, 10); for (int i = 0; i < NUM_GRUNTS; i++) { GridPoint2 randomPos = RandomUtils.random(maxPos, minPos); System.out.println(randomPos); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 9c4b32366..60df50b4a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -101,18 +101,19 @@ public void updateMobState() { case IDLE -> { if (isTargetVisible()) { // targets detected in idle mode - start deployment - //owner.getEntity().getEvents().trigger(DEPLOY); + owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } } case DEPLOY -> { // currently deploying, - if (isTargetVisible()) { - //owner.getEntity().getEvents().trigger(FIRING); + if (isTargetVisible() || this.meleeOrProjectile() != null) { + owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false); + owner.getEntity().getEvents().trigger(FIRING); mobState = STATE.FIRING; } else { - //owner.getEntity().getEvents().trigger(STOW); + owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } } @@ -139,10 +140,10 @@ public void updateMobState() { case STOW -> { // currently stowing if (isTargetVisible()) { - //owner.getEntity().getEvents().trigger(DEPLOY); + owner.getEntity().getEvents().trigger(DEPLOY); mobState = STATE.DEPLOY; } else { - //owner.getEntity().getEvents().trigger(IDLE); + owner.getEntity().getEvents().trigger(IDLE); mobState = STATE.IDLE; } } @@ -168,7 +169,6 @@ public void stop() { */ @Override public int getPriority() { -// return -1; if (status == Status.ACTIVE) { return getActivePriority(); } @@ -223,8 +223,6 @@ private Weapon meleeOrProjectile() { Weapon chosenWeapon = null; if (comp != null) { chosenWeapon = comp.chooseWeapon(hitraycast); - if (chosenWeapon != null) { - } } return chosenWeapon; From bdbb628e312da0773ac0117d145c3d9ee60d47a2 Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Sun, 10 Sep 2023 19:53:03 +1000 Subject: [PATCH 24/32] clean up --- .../com/csse3200/game/components/tasks/MobAttackTask.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 60df50b4a..703024c8d 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -124,6 +124,9 @@ public void updateMobState() { owner.getEntity().getEvents().trigger(STOW); mobState = STATE.STOW; } else { + if (this.meleeOrProjectile() instanceof Melee) { + + } Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); newProjectile.setScale(-1f, 0.5f); @@ -227,4 +230,9 @@ private Weapon meleeOrProjectile() { return chosenWeapon; } + + private void setTarget() { + Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); + Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); + } } From e303bd526abd32ebc1cc8d2aed224f307cd10d22 Mon Sep 17 00:00:00 2001 From: max9753 Date: Mon, 11 Sep 2023 09:45:05 +1000 Subject: [PATCH 25/32] Removed MobDeathTask.java use from NPCFactory.java as it is not longer used or maintained. --- .../main/com/csse3200/game/entities/factories/NPCFactory.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 31485fe72..869cdfbdd 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -143,8 +143,7 @@ public static Entity createBaseNPC(Entity target) { AITaskComponent aiComponent = new AITaskComponent() .addTask(new WanderTask(new Vector2(2f, 2f), 2f)) - .addTask(new MobAttackTask(2, 40)) - .addTask(new MobDeathTask(2)); + .addTask(new MobAttackTask(2, 40)); Entity npc = new Entity() .addComponent(new PhysicsComponent()) From c1ca0127cf7f17692582906ae15ff21ec82d41e7 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Mon, 11 Sep 2023 10:57:35 +1000 Subject: [PATCH 26/32] Some basic tests added for NPCFactory regarding Xeno creation. --- .../entities/factories/NPCFactoryTest.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java diff --git a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java new file mode 100644 index 000000000..dd8fdbbde --- /dev/null +++ b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java @@ -0,0 +1,65 @@ +package com.csse3200.game.entities.factories; + +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.physics.components.ColliderComponent; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ResourceService; +import com.csse3200.game.services.ServiceLocator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class NPCFactoryTest { + + private Entity xenoGrunt; + private Entity towerTarget; + private Entity engineerTarget; + private String[] atlas = {"images/mobs/xenoGrunt.atlas"}; + + + @BeforeEach + public void setUp() { + GameTime gameTime = mock(GameTime.class); + when(gameTime.getDeltaTime()).thenReturn(0.02f); + ServiceLocator.registerTimeSource(gameTime); + ServiceLocator.registerPhysicsService(new PhysicsService()); + RenderService render = new RenderService(); + render.setDebug(mock(DebugRenderer.class)); + ServiceLocator.registerRenderService(render); + ResourceService resourceService = new ResourceService(); + ServiceLocator.registerResourceService(resourceService); + resourceService.loadTextureAtlases(atlas); + resourceService.loadAll(); + ServiceLocator.getResourceService() + .getAsset("images/towers/turret01.atlas", TextureAtlas.class); + towerTarget = TowerFactory.createBaseTower(); + engineerTarget = EngineerFactory.createEngineer(); + xenoGrunt = NPCFactory.createXenoGrunt(towerTarget); + } + + @Test + public void testCreateXenoGruntNotNull() { + assertNotNull(xenoGrunt, "Xeno Grunt should not be null"); + } + + @Test + public void testCreateXenoGruntHasColliderComponent() { + assertNotNull(xenoGrunt.getComponent(ColliderComponent.class), + "Xeno Grunt should have ColliderComponent"); + } + + @Test + public void testCreateXenoGruntHasHitboxComponent() { + assertNotNull(xenoGrunt.getComponent(HitboxComponent.class), + "Xeno Grunt should have HitboxComponent"); + } + +} From 783bd7ec2bba1123722246c5e3d49001b0a93607 Mon Sep 17 00:00:00 2001 From: BlairCannon97 Date: Mon, 11 Sep 2023 11:35:09 +1000 Subject: [PATCH 27/32] More tests added for NPCFactory regarding Xeno creation. --- .../game/entities/configs/NPCConfigs.java | 5 +- .../entities/factories/NPCFactoryTest.java | 51 +++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/configs/NPCConfigs.java b/source/core/src/main/com/csse3200/game/entities/configs/NPCConfigs.java index 146e364a4..3bc7d9eb2 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/NPCConfigs.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/NPCConfigs.java @@ -16,9 +16,12 @@ public class NPCConfigs { public BaseEntityConfig projectile = new ProjectileConfig(); public GhostKingConfig ghostKing = new GhostKingConfig(); public BaseEnemyConfig xenoGrunt = new BaseEnemyConfig( + 10, + 100, new ArrayList(), new ArrayList(), - new ArrayList()); + new ArrayList(), + 10); public BossKingConfigs BossKing = new BossKingConfigs(); diff --git a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java index dd8fdbbde..9c02ba0c4 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java @@ -1,10 +1,14 @@ package com.csse3200.game.entities.factories; import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.entities.Entity; +import com.csse3200.game.extensions.GameExtension; import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.physics.components.ColliderComponent; import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.physics.components.PhysicsComponent; +import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.rendering.RenderService; import com.csse3200.game.services.GameTime; @@ -12,17 +16,32 @@ import com.csse3200.game.services.ServiceLocator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@ExtendWith(GameExtension.class) public class NPCFactoryTest { private Entity xenoGrunt; private Entity towerTarget; private Entity engineerTarget; - private String[] atlas = {"images/mobs/xenoGrunt.atlas"}; + private Entity playerTarget; + + private String[] texture = { + "images/towers/turret_deployed.png", + "images/towers/turret01.png", + "images/towers/wallTower.png" + }; + private String[] atlas = {"images/towers/turret01.atlas", + "images/mobs/xenoGrunt.atlas"}; + private static final String[] sounds = { + "sounds/towers/gun_shot_trimmed.mp3", + "sounds/towers/deploy.mp3", + "sounds/towers/stow.mp3" + }; @BeforeEach @@ -36,13 +55,16 @@ public void setUp() { ServiceLocator.registerRenderService(render); ResourceService resourceService = new ResourceService(); ServiceLocator.registerResourceService(resourceService); + resourceService.loadTextures(texture); resourceService.loadTextureAtlases(atlas); + resourceService.loadSounds(sounds); resourceService.loadAll(); ServiceLocator.getResourceService() - .getAsset("images/towers/turret01.atlas", TextureAtlas.class); + .getAsset("images/mobs/xenoGrunt.atlas", TextureAtlas.class); + //playerTarget = PlayerFactory.createPlayer(); towerTarget = TowerFactory.createBaseTower(); - engineerTarget = EngineerFactory.createEngineer(); - xenoGrunt = NPCFactory.createXenoGrunt(towerTarget); + //engineerTarget = EngineerFactory.createEngineer(); + xenoGrunt = NPCFactory.createXenoGrunt(playerTarget); } @Test @@ -62,4 +84,23 @@ public void testCreateXenoGruntHasHitboxComponent() { "Xeno Grunt should have HitboxComponent"); } + @Test + public void testCreateXenoGruntHasPhysicsComponent() { + assertNotNull(xenoGrunt.getComponent(PhysicsComponent.class), + "Xeno Grunt should have PhysicsComponent"); + } + + @Test + public void testXenoGruntCombatStatsComponent() { + assertEquals(100, xenoGrunt.getComponent(CombatStatsComponent.class).getHealth(), + "Health should be 100"); + assertEquals(10, xenoGrunt.getComponent(CombatStatsComponent.class).getBaseAttack(), + "BaseAttack should be 10"); + } + + @Test + public void xenoGruntHasAnimationComponent() { + assertNotNull(xenoGrunt.getComponent(AnimationRenderComponent.class)); + } + } From 28de0587aeb78920f9ec9998cdf1632adc6a014f Mon Sep 17 00:00:00 2001 From: bojyyy <140468434+bojyyy@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:35:44 +1000 Subject: [PATCH 28/32] Adds unit testing for SpawnWaveTask --- .../game/components/tasks/SpawnWaveTask.java | 4 +- .../components/tasks/SpawnWaveTaskTest.java | 42 +++++++++++++++++++ .../game/components/tasks/WaitTaskTest.java | 1 - 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 source/core/src/test/com/csse3200/game/components/tasks/SpawnWaveTaskTest.java diff --git a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java index 7fa219b6a..ea4d4cfd7 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java @@ -14,7 +14,7 @@ public class SpawnWaveTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(SpawnWaveTask.class); private final GameTime globalTime; - private long endTime; + private long endTime = 0; private final int SPAWNING_INTERVAL = 10; public SpawnWaveTask() { this.globalTime = ServiceLocator.getTimeSource(); @@ -22,7 +22,7 @@ public SpawnWaveTask() { @Override public int getPriority() { - return 10; // Low priority task + return 10; // High priority task } @Override diff --git a/source/core/src/test/com/csse3200/game/components/tasks/SpawnWaveTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/SpawnWaveTaskTest.java new file mode 100644 index 000000000..55a00537d --- /dev/null +++ b/source/core/src/test/com/csse3200/game/components/tasks/SpawnWaveTaskTest.java @@ -0,0 +1,42 @@ +package com.csse3200.game.components.tasks; + +import com.csse3200.game.ai.tasks.AITaskComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.events.listeners.EventListener0; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.utils.math.Vector2Utils; +import com.csse3200.game.physics.components.PhysicsMovementComponent; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(GameExtension.class) +@ExtendWith(MockitoExtension.class) +class SpawnWaveTaskTest { + + @Test + void shouldTriggerSpawning() { + GameTime time = mock(GameTime.class); + when(time.getTime()).thenReturn(11000L); + ServiceLocator.registerTimeSource(time); + SpawnWaveTask waveTask = new SpawnWaveTask(); + + AITaskComponent aiTaskComponent = new AITaskComponent().addTask(waveTask); + Entity entity = new Entity().addComponent(aiTaskComponent).addComponent(new PhysicsMovementComponent()); + entity.create(); + + // Register callbacks + EventListener0 callback = mock(EventListener0.class); + entity.getEvents().addListener("spawnWave", callback); + + waveTask.update(); + + verify(callback).handle(); + } +} \ No newline at end of file diff --git a/source/core/src/test/com/csse3200/game/components/tasks/WaitTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/WaitTaskTest.java index 6ba90f421..59e7ea7c8 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/WaitTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/WaitTaskTest.java @@ -14,7 +14,6 @@ @ExtendWith(GameExtension.class) class WaitTaskTest { - @Disabled("Testing without use of WaitTask") @Test void shouldWaitUntilTime() { GameTime time = mock(GameTime.class); From 7d5637e4ecb1a52493993a0c36aa2a743f7a002d Mon Sep 17 00:00:00 2001 From: Samantha Sullivan Date: Mon, 11 Sep 2023 11:59:09 +1000 Subject: [PATCH 29/32] mobs will attack with melee if within range --- .../game/components/TouchAttackComponent.java | 2 +- .../game/components/tasks/MobAttackTask.java | 34 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java index 01ed762a4..6a7e7e2e1 100644 --- a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java +++ b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java @@ -64,7 +64,7 @@ public void create() { hitboxComponent = entity.getComponent(HitboxComponent.class); } - private void onCollisionStart(Fixture me, Fixture other) { + public void onCollisionStart(Fixture me, Fixture other) { if (hitboxComponent.getFixture() != me) { // Not triggered by hitbox, ignore return; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 703024c8d..a46c6f430 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -12,6 +12,7 @@ import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.rendering.AnimationRenderComponent; @@ -33,6 +34,8 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private static final String FIRING = "shootStart"; private static final String IDLE = "idleStart"; + private Fixture target; + private final int priority; private final float maxRange; private Vector2 mobPosition = new Vector2(10f,10f); @@ -125,16 +128,20 @@ public void updateMobState() { mobState = STATE.STOW; } else { if (this.meleeOrProjectile() instanceof Melee) { - + System.out.println("Melee attack"); + TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class); + HitboxComponent hitboxComp = owner.getEntity().getComponent(HitboxComponent.class); + attackComp.onCollisionStart(hitboxComp.getFixture(), target); + } else { + Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); + newProjectile.setScale(-1f, 0.5f); + ServiceLocator.getEntityService().register(newProjectile); + +// System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); + owner.getEntity().getEvents().trigger(FIRING); + mobState = STATE.STOW; } - Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); - newProjectile.setScale(-1f, 0.5f); - ServiceLocator.getEntityService().register(newProjectile); - - System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); - owner.getEntity().getEvents().trigger(FIRING); - mobState = STATE.STOW; } owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true); @@ -220,12 +227,13 @@ private boolean isTargetVisible() { * returns the Weapon (Melee or Projectile) the mob will use to attack the target. null if immune target or no target * */ private Weapon meleeOrProjectile() { - Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); - Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); +// Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); +// Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); + setTarget(); TouchAttackComponent comp = owner.getEntity().getComponent(TouchAttackComponent.class); Weapon chosenWeapon = null; if (comp != null) { - chosenWeapon = comp.chooseWeapon(hitraycast); + chosenWeapon = comp.chooseWeapon(target); } return chosenWeapon; @@ -233,6 +241,6 @@ private Weapon meleeOrProjectile() { private void setTarget() { Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); - Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); + target = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); } } From 4beb796ef975cc4394dd828398cb16d683dd74a1 Mon Sep 17 00:00:00 2001 From: max9753 Date: Mon, 11 Sep 2023 12:11:44 +1000 Subject: [PATCH 30/32] Removed several unused statements which were added for mob death from WanderTask.java --- .../src/main/com/csse3200/game/components/tasks/WanderTask.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java b/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java index 088d32775..f02852bdb 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/WanderTask.java @@ -82,8 +82,6 @@ public void update() { // with section, massive props to him for his help! if (!isDead && owner.getEntity().getComponent(CombatStatsComponent.class).isDead()) { owner.getEntity().getEvents().trigger("dieStart"); - //owner.getEntity().getComponent(ColliderComponent.class).setLayer(PhysicsLayer.NONE); - //owner.getEntity().getComponent(HitboxComponent.class).setLayer(PhysicsLayer.NONE); currentTask.stop(); isDead = true; } From e07561638447a07f264cc4bba4bbf631d8f6282b Mon Sep 17 00:00:00 2001 From: bojyyy <140468434+bojyyy@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:28:30 +1000 Subject: [PATCH 31/32] Modifies mob spawning to correspond to new allowable game area --- .../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 67df1a4bf..36cb3e2b4 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -369,7 +369,7 @@ private void spawnProjectile(Vector2 position, short targetLayer, int space, in private void spawnXenoGrunts() { - int[] pickedLanes = new Random().ints(0, 8) + int[] pickedLanes = new Random().ints(1, 7) .distinct().limit(5).toArray(); for (int i = 0; i < NUM_GRUNTS; i++) { GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); From 4a23ae5437327e85178c2f053acabd1f5b70cf21 Mon Sep 17 00:00:00 2001 From: meganroxburgh <128758122+meganroxburgh@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:14:32 +1000 Subject: [PATCH 32/32] Removed scale down of mob balls in MobAttackTask --- .../main/com/csse3200/game/components/tasks/MobAttackTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index 3b12cccc8..1292d116b 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -133,7 +133,7 @@ public void updateMobState() { } else { Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y)); - newProjectile.setScale(-1f, 0.5f); +// newProjectile.setScale(-1f, 0.5f); ServiceLocator.getEntityService().register(newProjectile); // System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n");