From 49de631626ae2bdb3387e414ab4e7595d3f57427 Mon Sep 17 00:00:00 2001 From: MiniSoda17 Date: Sun, 10 Sep 2023 01:29:13 +1000 Subject: [PATCH 01/22] Slightly adjusting spawning of projectiles for engineers and mob kings --- .../csse3200/game/components/tasks/RangeBossMovementTask.java | 2 +- .../com/csse3200/game/components/tasks/TowerCombatTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/RangeBossMovementTask.java b/source/core/src/main/com/csse3200/game/components/tasks/RangeBossMovementTask.java index be0e655c6..81e0399d1 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/RangeBossMovementTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/RangeBossMovementTask.java @@ -79,7 +79,7 @@ public void update() { switchMobKingBallState(); // newProjectile.scaleHeight(-1f); newProjectile.setScale(-1.3f, 0.82f); - newProjectile.setPosition((float) (currentPos.x), (float) (currentPos.y+0.75f)); + newProjectile.setPosition((float) (currentPos.x), (float) (currentPos.y + 0.55f)); ServiceLocator.getEntityService().register(newProjectile); startWaiting(); } else { diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java index e7addaab5..962c933f6 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java @@ -116,7 +116,7 @@ public void updateTowerState() { Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f,2f)); newProjectile.setScale(1.1f, 0.8f); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.75), (float) (owner.getEntity().getPosition().y + 0.5)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.5), (float) (owner.getEntity().getPosition().y + 0.5)); ServiceLocator.getEntityService().register(newProjectile); // * TEMPRORARYYYYYYYY PLS DON'T DELETE THIS From 6fda7f78271830faf612a973b0221b5fc901c81a Mon Sep 17 00:00:00 2001 From: freshc0w <121275444+freshc0w@users.noreply.github.com> Date: Sun, 10 Sep 2023 18:12:38 +1000 Subject: [PATCH 02/22] Add collisoin end event disposing self component --- .../game/components/TouchAttackComponent.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 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 9570f7d25..b0530fc26 100644 --- a/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java +++ b/source/core/src/main/com/csse3200/game/components/TouchAttackComponent.java @@ -59,7 +59,7 @@ public TouchAttackComponent(short targetLayer, float knockback, boolean disposeO @Override public void create() { entity.getEvents().addListener("collisionStart", this::onCollisionStart); - // entity.getEvents().addListener("collisionEnd", this::onCollisionEnd); + entity.getEvents().addListener("collisionEnd", this::onCollisionEnd); combatStats = entity.getComponent(CombatStatsComponent.class); hitboxComponent = entity.getComponent(HitboxComponent.class); } @@ -108,8 +108,23 @@ public void setDisposeOnHit(boolean disposeOnHit) { public void setKnockBack(float knockback) { this.knockbackForce = knockback; } - // private void onCollisionEnd(Fixture me, Fixture other) { - // // Nothing to do on collision end - // } + + private void onCollisionEnd(Fixture me, Fixture other) { + // Nothing to do on collision end + if (hitboxComponent.getFixture() != me) { + // Not triggered by hitbox, ignore + return; + } + + if (!PhysicsLayer.contains(targetLayer, other.getFilterData().categoryBits)) { + // Doesn't match our target layer, ignore + return; + } + + if (disposeOnHit) { + Entity projectile = ((BodyUserData) me.getBody().getUserData()).entity; + projectile.setFlagForDelete(true); + } + } } From fedd09e0c0c7ce2c6aad8b64ed5ebc4bd02df1da Mon Sep 17 00:00:00 2001 From: JSLLW Date: Sun, 10 Sep 2023 18:21:59 +1000 Subject: [PATCH 03/22] Implemented stun effect --- .../game/ai/tasks/AITaskComponent.java | 23 +++++++++- .../game/components/EffectsComponent.java | 46 ++++++++++++++++--- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java index 7b4dd37da..11f3bfceb 100644 --- a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java +++ b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java @@ -18,8 +18,8 @@ public class AITaskComponent extends Component implements TaskRunner { private static final Logger logger = LoggerFactory.getLogger(AITaskComponent.class); private final List priorityTasks = new ArrayList<>(2); + private final List priorityTasksToBeRestored = new ArrayList<>(2); private PriorityTask currentTask; - /** * Add a priority task to the list of tasks. This task will be run only when it has the highest * priority, and can be stopped to run a higher priority task. @@ -59,6 +59,27 @@ public void dispose() { } } + public boolean disposeAll() { + for (int i = 0; i < priorityTasks.size(); i++) { + priorityTasksToBeRestored.add(priorityTasks.get(i)); + + } + for (int i = 0; i < priorityTasks.size(); i++) { + priorityTasks.remove(i); + } + return true; + } + + public boolean restore() { + for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { + priorityTasks.add(priorityTasksToBeRestored.get(i)); + } + for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { + priorityTasksToBeRestored.remove(i); + } + return true; + } + private PriorityTask getHighestPriorityTask() { try { return Collections.max(priorityTasks, Comparator.comparingInt(PriorityTask::getPriority)); diff --git a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java index 843d65288..29210de20 100644 --- a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java @@ -1,14 +1,14 @@ package com.csse3200.game.components; +import java.util.ArrayList; + import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Fixture; +import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.entities.Entity; -import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsLayer; -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.physics.components.PhysicsMovementComponent; import com.csse3200.game.services.ServiceLocator; @@ -29,6 +29,7 @@ public class EffectsComponent extends Component { private HitboxComponent hitboxComponent; private final short targetLayer; private Array burnEntities = new Array<>(); + private ArrayList stunnedEntities = new ArrayList<>(); /** * Constructor for the AoEComponent. @@ -93,7 +94,13 @@ private void onCollisionEnd(Fixture me, Fixture other) { applySingleEffect(ProjectileEffects.SLOW, otherCombatStats, otherEntity); } } - case STUN -> {} + case STUN -> { + if (aoe) { + applyAoeEffect(ProjectileEffects.STUN); + } else { + applySingleEffect(ProjectileEffects.STUN, otherCombatStats, otherEntity); + } + } } } @@ -117,7 +124,9 @@ public void applySingleEffect(ProjectileEffects effect, CombatStatsComponent tar burnEffect(targetCombatStats, hostCombatStats); } case SLOW -> {slowEffect(targetEntity);} - case STUN -> {} + case STUN -> { + stunEffect(targetEntity); + } } } /** @@ -152,7 +161,9 @@ public void applyAoeEffect(ProjectileEffects effect) { case FIREBALL -> {fireballEffect(targetCombatStats, hostCombatStats);} case BURN -> {burnEffect(targetCombatStats, hostCombatStats);} case SLOW -> {slowEffect(targetEntity);} - case STUN -> {} + case STUN -> { + stunEffect(targetEntity); + } } } else { return; @@ -180,7 +191,6 @@ private void burnEffect(CombatStatsComponent target, CombatStatsComponent host) return; } burnEntities.add(target); - // Create a timer task to apply the effect repeatedly int numberOfTicks = 5; long delay = 1; @@ -252,4 +262,26 @@ public void run() { } }, 5); // 5 seconds delay } + + private void stunEffect(Entity targetEntity) { + AITaskComponent taskComponent = targetEntity.getComponent(AITaskComponent.class); + if (taskComponent == null) { + return; + } + if (stunnedEntities.contains(targetEntity)) { + return; + } + taskComponent.disposeAll(); + stunnedEntities.add(targetEntity); + + new java.util.Timer().schedule( + new java.util.TimerTask() { + @Override + public void run() { + taskComponent.restore(); + stunnedEntities.remove(targetEntity); + this.cancel(); + } + }, 5000); + } } From 83f1f3bfc1780ebd1db66e7202d0c1814a81d7dd Mon Sep 17 00:00:00 2001 From: freshc0w <121275444+freshc0w@users.noreply.github.com> Date: Sun, 10 Sep 2023 19:03:15 +1000 Subject: [PATCH 04/22] Init ricochetcompontent tests --- .../components/RicochetComponentTest.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java diff --git a/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java new file mode 100644 index 000000000..db1e041ed --- /dev/null +++ b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java @@ -0,0 +1,113 @@ +package com.csse3200.game.components; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.Ignore; +import org.junit.jupiter.api.BeforeEach; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.csse3200.game.entities.factories.ProjectileFactory; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.physics.components.PhysicsComponent; +import com.csse3200.game.physics.components.PhysicsMovementComponent; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ResourceService; +import com.csse3200.game.services.ServiceLocator; + +public class RicochetComponentTest { + Entity projectile; + Entity mob; + + @BeforeEach + void beforeEach() { + GameTime gameTime = mock(GameTime.class); + when(gameTime.getDeltaTime()).thenReturn(0.03f); + ServiceLocator.registerTimeSource(gameTime); + ServiceLocator.registerPhysicsService(new PhysicsService()); + ServiceLocator.registerEntityService(new EntityService()); + RenderService render = new RenderService(); + ServiceLocator.registerRenderService(render); + ResourceService resourceService = new ResourceService(); + + projectile = createProjectile(PhysicsLayer.NPC); + mob = createMobTarget(PhysicsLayer.NPC); + ServiceLocator.getEntityService().register(projectile); + ServiceLocator.getEntityService().register(mob); + ServiceLocator.registerResourceService(resourceService); + resourceService.loadAll(); + } + + @Test + void shouldHaveRicochetComponent() { + assertNotNull(projectile.getComponent(RicochetComponent.class), + "Projectile does not contain RicochetComponent"); + } + + @Test + void shouldDisposeAferCollision() { + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + + assertTrue("projectile entity flag should be true after collision", + projectile.getFlagForDelete()); + } + + // @Test + @Ignore + void shouldSpawnAnotherProjectile() { + int currentEntities = ServiceLocator.getEntityService().getEntities().size; + + // projectile.setPosition(2, 2); + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertEquals("Should spawn another ricochet projectile", currentEntities, + ServiceLocator.getEntityService().getEntities().size); + } + + Entity createProjectile(short targetLayer) { + Entity projectile = new Entity(); + + projectile + .addComponent(new PhysicsComponent()) + .addComponent(new PhysicsMovementComponent()) + .addComponent(new HitboxComponent().setLayer(PhysicsLayer.PROJECTILE)) + .addComponent(new CombatStatsComponent(0, 10)) + .addComponent(new TouchAttackComponent(targetLayer, 0f, true)) + .addComponent(new RicochetComponent(PhysicsLayer.NPC, 0)); + + return projectile; + } + + Entity createMobTarget(short layer) { + Entity target = new Entity(); + + target + .addComponent(new CombatStatsComponent(100, 0)) + .addComponent(new PhysicsComponent()) + .addComponent(new HitboxComponent().setLayer(layer)); + + return target; + } +} From dcddbd63502f20c804df0bd8f81f05664ebcabf1 Mon Sep 17 00:00:00 2001 From: gregchan550 Date: Sun, 10 Sep 2023 19:10:04 +1000 Subject: [PATCH 05/22] removed comments and now slow effect works when mobs shoot towers with slow as well --- .../main/com/csse3200/game/components/EffectsComponent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java index 29210de20..0788022fa 100644 --- a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Fixture; import com.csse3200.game.ai.tasks.AITaskComponent; +import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsLayer; @@ -228,7 +229,7 @@ private void slowEffect(Entity targetEntity) { if (PhysicsLayer.contains(PhysicsLayer.HUMANS, targetEntity.getComponent(HitboxComponent.class).getLayer())) { // towers towerFlag = true; - //targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, -30); + targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, -30); } else if (PhysicsLayer.contains(PhysicsLayer.NPC, targetEntity.getComponent(HitboxComponent.class).getLayer())) { // mobs mobFlag = true; @@ -255,7 +256,7 @@ private void slowEffect(Entity targetEntity) { @Override public void run() { if (finalTowerFlag) { - //targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 30); + targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 30); } else if (finalMobFlag) { finalTargetPhysics.setSpeed(new Vector2(finalXSpeed, finalYSpeed)); } From 2bdcf17f9f2bc69f6750e8fc122ea1645b6dc38d Mon Sep 17 00:00:00 2001 From: MiniSoda17 Date: Sun, 10 Sep 2023 19:53:05 +1000 Subject: [PATCH 06/22] Removed snow ball projectile in forestGameArea --- .../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 a3bde2263..c959826b4 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -189,7 +189,7 @@ public void create() { spawnPierceFireBall(new Vector2(2, 3), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f)); spawnRicochetFireball(new Vector2(2, 4), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f)); spawnSplitFireWorksFireBall(new Vector2(2, 5), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f), 12); - spawnEffectProjectile(new Vector2(2, 6), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f), ProjectileEffects.SLOW, false); + // spawnEffectProjectile(new Vector2(2, 6), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f), ProjectileEffects.SLOW, false); // spawnProjectileTest(new Vector2(0, 8), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f)); From 99b61447ddf3fe63e2b47cda0ae607182297b0a6 Mon Sep 17 00:00:00 2001 From: MiniSoda17 Date: Sun, 10 Sep 2023 21:06:22 +1000 Subject: [PATCH 07/22] Added Junit Testing for FireBall, MobBalls, MobKingBalls & EngineerBullets --- .../components/tasks/DroidCombatTask.java | 2 +- .../factories/ProjectileFactoryTest.java | 154 ++++++++++++++++-- 2 files changed, 141 insertions(+), 15 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java index 57b91f06e..21d587be9 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java @@ -115,7 +115,7 @@ public void updateTowerState() { owner.getEntity().getEvents().trigger(ATTACK_DOWN); Entity Projectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2,2), ProjectileEffects.SLOW, false); - Projectile.setScale(new Vector2(0.5f,0.5f)); + Projectile.setScale(new Vector2(0.45f, 0.5f)); Projectile.setPosition((float) (owner.getEntity().getPosition().x + 0.2), (float) (owner.getEntity().getPosition().y - 0.2)); ServiceLocator.getEntityService().register(Projectile); diff --git a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java index 925f44e03..dd0e04eb9 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java @@ -12,11 +12,17 @@ import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.CostComponent; +import com.csse3200.game.components.DeleteOnMapEdgeComponent; import com.csse3200.game.components.TouchAttackComponent; +import com.csse3200.game.components.projectile.EngineerBulletsAnimationController; +import com.csse3200.game.components.projectile.MobKingProjectAnimController; +import com.csse3200.game.components.projectile.MobProjectileAnimationController; +import com.csse3200.game.components.projectile.ProjectileAnimationController; import com.csse3200.game.entities.Entity; import com.csse3200.game.extensions.GameExtension; import com.csse3200.game.physics.PhysicsLayer; 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.physics.components.PhysicsMovementComponent; @@ -37,7 +43,21 @@ @ExtendWith(GameExtension.class) class ProjectileFactoryTest { - private Entity projectile; + + private final String[] atlas = { + "images/projectiles/mobProjectile.atlas", + "images/projectiles/basic_projectile.atlas", + "images/projectiles/mobKing_projectile.atlas", + "images/projectiles/engineer_projectile.atlas" + }; + + private final String[] animations = { + "rotate", + "projectile", + "projectileFinal", + "mob_boss", + "mob_bossFinal" + }; @BeforeEach public void setUp() { @@ -50,37 +70,143 @@ public void setUp() { ServiceLocator.registerRenderService(render); ResourceService resourceService = new ResourceService(); ServiceLocator.registerResourceService(resourceService); - // resourceService.loadTextures(texture); - // resourceService.loadTextureAtlases(atlas); - resourceService.loadAll(); - // ServiceLocator.getResourceService() - // .getAsset("images/projectiles/basic_projectile.atlas", TextureAtlas.class); - Vector2 destination = new Vector2(0.1f, 0.1f); - short targetLayer = PhysicsLayer.HUMANS; - Vector2 speed = new Vector2(2f, 2f); - projectile = ProjectileFactory.createBaseProjectile(targetLayer, destination, speed); + resourceService.loadTextureAtlases(atlas); + resourceService.loadAll(); + } + + @Test + public void createBaseProjectile() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(projectile); } @Test - public void testBaseProjectileNotNull() { - assertNotNull(projectile, "Base projectile is null"); + public void testBaseProjectileColliderComponent() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(projectile.getComponent(ColliderComponent.class), + "Projectile does not have a ColliderComponent"); } + @Test + public void testBaseProjectileTouchAttackComponent() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(projectile.getComponent(TouchAttackComponent.class), + "Projectile does not have a TouchAttackComponent"); + } + + @Test + public void testBaseProjectileDeleteOnMapEdgeComponent() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(projectile.getComponent(DeleteOnMapEdgeComponent.class), + "Projectile does not have a DeleteOnMapEdgeComponent"); + } + + @Test + public void testBaseProjectileSpeed() { + Vector2 testSpeed = new Vector2(1f, 1f); + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), testSpeed); + assertEquals(testSpeed, projectile.getComponent(PhysicsMovementComponent.class).getSpeed(), + "Projectile speed does not match testSpeed"); + } + @Test public void testBaseProjectileHitbox() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); assertNotNull(projectile.getComponent(HitboxComponent.class), "Projectile does not contain Hotbox component"); } @Test public void testBaseProjectilePhysics() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); assertNotNull(projectile.getComponent(PhysicsComponent.class), - "Projectile does not have Physics component"); + "Projectile does not have Physics component"); } - + @Test public void testBaseProjectilePhysicsMovement() { + Entity projectile = ProjectileFactory.createBaseProjectile(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); assertNotNull(projectile.getComponent(PhysicsMovementComponent.class), "Projectile does not have PhysicsMovement component"); } + + @Test + public void testFireBallProjectileCreation() { + Entity fireBall = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireBall); + } + + @Test + public void testFireBallAnimationRenderComponent() { + Entity fireBall = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireBall.getComponent(AnimationRenderComponent.class), + "Fire Ball does not have an AnimationRenderComponent"); + } + @Test + public void testFireBallAnimationController() { + Entity fireBall = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireBall.getComponent(ProjectileAnimationController.class), + "Fire Ball does not have an Animation Controller"); + } + + @Test + public void createMobBallProjectile() { + Entity mobBallProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobBallProjectile, "Mob King Ball is Null"); + } + + @Test + public void testMobBallProjectileAnimationRenderComponent() { + Entity mobBallProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobBallProjectile.getComponent(AnimationRenderComponent.class), + "Mob Ball Projectile does not have an AnimationRenderComponent"); + } + + @Test + public void testMobBallProjectileAnimationController() { + Entity mobBallProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobBallProjectile.getComponent(MobProjectileAnimationController.class), + "Mob Ball Projectile does not have an AnimationController"); + } + + @Test + public void testMobKingBallCreation() { + Entity mobKingBall = ProjectileFactory.createMobKingBall(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobKingBall, "Mob King Ball is null"); + } + + @Test + public void testMobKingBallAnimationRenderComponent() { + Entity mobKingBall = ProjectileFactory.createMobKingBall(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobKingBall.getComponent(AnimationRenderComponent.class), + "Mob King Ball does not have AnimationRenderComponent"); + } + + @Test + public void testMobKingBallAnimationController() { + Entity mobKingBall = ProjectileFactory.createMobKingBall(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(mobKingBall.getComponent(MobKingProjectAnimController.class), + "Mob King Ball does not have Animation Controller"); + } + + @Test + public void testEngineerBulletCreation() { + Entity engineerBullet = ProjectileFactory.createEngineerBullet(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(engineerBullet, "engineerBullet is null"); + } + + @Test + public void testEngineerBulletAnimationRenderComponent() { + Entity engineerBulllet = ProjectileFactory.createEngineerBullet(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(engineerBulllet.getComponent(AnimationRenderComponent.class), + "Engineer Bullet does not have AnimationRenderComponent"); + } + + @Test + public void testEngineerAnimationController() { + Entity engineerBullet = ProjectileFactory.createEngineerBullet(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(engineerBullet.getComponent(EngineerBulletsAnimationController.class), + "Engineer Bullet does not have Animation Controller"); + } } + From cc7e84c7c6f169478d1232ce4897576105614a09 Mon Sep 17 00:00:00 2001 From: JSLLW Date: Sun, 10 Sep 2023 21:58:55 +1000 Subject: [PATCH 08/22] docs: Added javadocs for files in components. --- .../game/ai/tasks/AITaskComponent.java | 16 +++-- .../game/components/EffectsComponent.java | 61 +++++++++---------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java index 11f3bfceb..a0a91095b 100644 --- a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java +++ b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java @@ -59,25 +59,31 @@ public void dispose() { } } - public boolean disposeAll() { + /** + * Empties the priorityTasks List. Disposes all of the entity's tasks. + */ + public void disposeAll() { + currentTask = null; for (int i = 0; i < priorityTasks.size(); i++) { priorityTasksToBeRestored.add(priorityTasks.get(i)); - } for (int i = 0; i < priorityTasks.size(); i++) { priorityTasks.remove(i); } - return true; } - public boolean restore() { + /** + * Restores the priorityTasks List. Adds all of the entity's disposed tasks + * back into priorityTasks. + */ + public void restore() { for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { priorityTasks.add(priorityTasksToBeRestored.get(i)); } for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { priorityTasksToBeRestored.remove(i); } - return true; + this.update(); } private PriorityTask getHighestPriorityTask() { diff --git a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java index 29210de20..9c0647cd4 100644 --- a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java @@ -51,7 +51,7 @@ public void create() { } private void onCollisionStart(Fixture me, Fixture other) { - // Nothing to do on collision start + // Nothing to do in collision start } private void onCollisionEnd(Fixture me, Fixture other) { @@ -73,33 +73,18 @@ private void onCollisionEnd(Fixture me, Fixture other) { return; } + System.out.println("target layer: " + otherEntity.getLayer()); + // Apply effect - switch (effect) { - case FIREBALL -> { - if (aoe) { - applyAoeEffect(ProjectileEffects.FIREBALL); - } - } - case BURN -> { - if (aoe) { - applyAoeEffect(ProjectileEffects.BURN); - } else { - applySingleEffect(ProjectileEffects.BURN, otherCombatStats, otherEntity); - } - } - case SLOW -> { - if (aoe) { - applyAoeEffect(ProjectileEffects.SLOW); - } else { - applySingleEffect(ProjectileEffects.SLOW, otherCombatStats, otherEntity); - } + if (effect == ProjectileEffects.FIREBALL) { + if (aoe) { + applyAoeEffect(ProjectileEffects.FIREBALL); } - case STUN -> { - if (aoe) { - applyAoeEffect(ProjectileEffects.STUN); - } else { - applySingleEffect(ProjectileEffects.STUN, otherCombatStats, otherEntity); - } + } else { + if (aoe) { + applyAoeEffect(effect); + } else { + applySingleEffect(effect, otherCombatStats, otherEntity); } } } @@ -124,9 +109,7 @@ public void applySingleEffect(ProjectileEffects effect, CombatStatsComponent tar burnEffect(targetCombatStats, hostCombatStats); } case SLOW -> {slowEffect(targetEntity);} - case STUN -> { - stunEffect(targetEntity); - } + case STUN -> {stunEffect(targetEntity);} } } /** @@ -263,23 +246,37 @@ public void run() { }, 5); // 5 seconds delay } + /** + * Applies stun effect to a taget entity. + * @param targetEntity Entity for stun effect to be applied to. + */ private void stunEffect(Entity targetEntity) { + CombatStatsComponent hostCombatStats = targetEntity.getComponent(CombatStatsComponent.class); AITaskComponent taskComponent = targetEntity.getComponent(AITaskComponent.class); - if (taskComponent == null) { + + if (hostCombatStats == null || taskComponent == null) { return; } + + hostCombatStats.setBaseAttack(0); + if (stunnedEntities.contains(targetEntity)) { return; } + taskComponent.disposeAll(); stunnedEntities.add(targetEntity); - + new java.util.Timer().schedule( new java.util.TimerTask() { @Override public void run() { taskComponent.restore(); - stunnedEntities.remove(targetEntity); + for (int i = 0; i < stunnedEntities.size(); i++) { + if (stunnedEntities.get(i).equals(targetEntity)) { + stunnedEntities.remove(stunnedEntities.get(i)); + } + } this.cancel(); } }, 5000); From 095372423754042ff7481e100c07d16ce33886d8 Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 00:15:02 +1000 Subject: [PATCH 09/22] Added animations for stun and burn effect. Stun implemented through StunTowerCombatTask --- .../images/projectiles/burn_effect.atlas | 55 ++++++++++++++++++ .../assets/images/projectiles/burn_effect.png | Bin 0 -> 3206 bytes .../images/projectiles/stun_effect.atlas | 41 +++++++++++++ .../assets/images/projectiles/stun_effect.png | Bin 0 -> 1146 bytes .../csse3200/game/areas/ForestGameArea.java | 8 ++- ...rnEffectProjectileAnimationController.java | 33 +++++++++++ .../ProjectileAnimationController.java | 1 + ...unEffectProjectileAnimationController.java | 27 +++++++++ .../components/tasks/StunTowerCombatTask.java | 5 +- .../entities/factories/ProjectileFactory.java | 19 +++--- 10 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 source/core/assets/images/projectiles/burn_effect.atlas create mode 100644 source/core/assets/images/projectiles/burn_effect.png create mode 100644 source/core/assets/images/projectiles/stun_effect.atlas create mode 100644 source/core/assets/images/projectiles/stun_effect.png create mode 100644 source/core/src/main/com/csse3200/game/components/projectile/BurnEffectProjectileAnimationController.java create mode 100644 source/core/src/main/com/csse3200/game/components/projectile/StunEffectProjectileAnimationController.java diff --git a/source/core/assets/images/projectiles/burn_effect.atlas b/source/core/assets/images/projectiles/burn_effect.atlas new file mode 100644 index 000000000..2d422b19f --- /dev/null +++ b/source/core/assets/images/projectiles/burn_effect.atlas @@ -0,0 +1,55 @@ + +burn_effect.png +size: 256, 64 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +projectile + rotate: false + xy: 78, 2 + size: 36, 31 + orig: 36, 31 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 2, 2 + size: 36, 31 + orig: 36, 31 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 154, 2 + size: 35, 31 + orig: 35, 31 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 40, 2 + size: 36, 31 + orig: 36, 31 + offset: 0, 0 + index: -1 +projectileFinal + rotate: false + xy: 116, 2 + size: 36, 31 + orig: 36, 31 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 191, 2 + size: 31, 31 + orig: 31, 31 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 78, 2 + size: 36, 31 + orig: 36, 31 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/projectiles/burn_effect.png b/source/core/assets/images/projectiles/burn_effect.png new file mode 100644 index 0000000000000000000000000000000000000000..18df3b6d51bd2aa439d7f060e3afbd85f8f01757 GIT binary patch literal 3206 zcmcIn=Q|sY7LFBuR+Unvl#9@!Mq48>YqX)lMbT=ks8y+w5+xC%YP3eFQKO=*5i4Sq z+BMSDEHxUfsPKzXd#~j7KF_@$?jLZ!oO9kU@2B^i_dN+Vup0ur61)HaKmdBv)D{3> z`!fQJcz}QE4xG>i0PtHuO^xkCT~^@EDK59qO;6;w`C67-$sdW%$rihO>qXX0fw#h< zPyGaVLT|Rnh)D`0YKRNJd#U92*3mraStvsR*KJzm8{5!ehreYvaxUiut-0-_;>m6; z4SOhv!mp+4y*}7=S%$BLSwC3m!q}aOGLjME;bi|$(_cTtURdc_dA3wL240-B$`d0> z>pQdr?K^FxoMyFPTJ{Eq3B?OZ00}#pjM3VyIRJQ5>LRD31BOZx_{tcyf88y+HpX@|i5wil~at zeBmlLwfLI@J+X~wh!V!oZ}9CsoU~419c+{Rf<`A{#x%c$eQ7kiy<#ynaH0zo#i`{t zLNwfx&C+4DtEt}h?3eV%#0{4RVcrar@G;cIW5Pg(dw7hpD_qHZ~_VyYbnK=bMq%ARibe;!U!XV3(q~mrH%P^fv?e#`N`P-Ovda-8#|+HNl+v zgmd5F44W2)`&adsjVH!rjkocilFb*mob$2j#BYn)3M}gDQ`%x|@+_tAsM+PEfN$3a z{!I=$?03KaAg%IHTp3cNE5@Ggi+~?e3q9ruBsFkjAl*6KFXZV3wKvnTd(P^*;t~{E z&c5~~{^pozS8o6})Et3=Bg@p+WG;;_9)YD|W@n)TK*BgWxMyfou7Dkx_h~?P8=>2iNL<$(~p|bUb!qGG4eM+p{5aKl2 z7rL^|oTZM2CqA&AHuzg4oKKnaHyO=5q}T(z2=pJF&#o=`jb*P(7x5VVtpd0s_+Zf1 zB9+lL8ac1jI^$J_ToD(I@;9+$){hP}1LRrOVw*60z0xCD^&sQDv>~0o3~{WiWXQVM zxrBEucp3MSuU#FQm%)&$)@O%>X}ld7Yx3c9$JOj^oBdwR?8W|!OxN_5m@Os1Zxs(! z!YiGU&h8+P*#+#?RH_elT5l&oo@`LU9HNak@u~aFD!b~0TF*;IeNc9T>q!oJD0qc0 zULLj7lRHXAXY@m5G;M7W4_r6kP1Pi;7vtlH?t6OdQ86Lk&}B0kb&Kyl`n;?l`E%=5u)$T}ny_5b1rQpbcl1?81P&q{^ z+li>kAt@wMr69spqEqO>`EXgsGHz91oD>)rP0D!B2jS85BIJH`_^fPw`4DXJwi%p7 zPOs9|=35LS-v{8!4eZc>yJwudUl0#x^XhZo^K`(F6xZ5QSaY`a_2EK)#OL1}bt@)q zPZ59i6E6~v3Ml|+hFtX=364wU&>eEUUP@A0+br4K#3 z+RUVp)ivWD1Co}#PxXfju#?(KN#*dDHba`(&NXRj0+e{Kcn$n(YO2P^G2${kAoHCJh`*lO<))F_3#BC z!+4pE68PFnt+n#o%ynv@w_(Y^njvZMD+d-D zRxBBO0CE|L>-B^vIR{4|vqS;6rh^l8s22gEODGS0*Ds6r&zA(O7VM}5+cO9zn+KbF zvSCUUt!Vw{p7*78#B0Y^6~5y1d5w0ZCei+}3apG9BYg%32knP3E1fAo<&b|$K_`}R z;5UpGxlX~a36AGYl6!g8Qs(?T4{X(S*n*}EY|h;w=hEeUQ8(u?=S<7EYx#W06SWdo z&6)kpa;wfHZEnb-3-ISvE;k!lH(Kpa`x`l~B|m*uBl2`3%B#0?5zB)leWwDHq8448 z8G6KR*)z75QZTo!z`i_k7huuc!rBZX9d>nzEH)^(#dVxhF9XL7{W^4U49n1k{^f&pBU-Qx2c9>qF&t|!i8NrCGehZ7ay?vWs5Z>Up7OS(Z;$ha6ma?w+0Q;SJJxnDQkLQ8dQxOHXMSJH*XpgIelr6Vjod}vro20O43>@ zov_6b)<#$k$bIL8jbLM`ucqR)#=CB0C{6xUXACI_5KJ*!|OH;`eM<0L7lSCKhEVGVUsRN z30SFCzwZ4|QOn}vicjk4ONriH!(xv4qh|InL5WOc9%sds?S>7v<0{V)Bh4?*t-zjK z;I;|ZMfaa+xL4mC0P5VVTcQzjDh4VyU zhw{a>3^?e^^W|b3!^y6gLmzi-p4vZ0Q;oaPXXe@rG(J@I zi6jx-uyx|3!TkZAcI_P6DP8%KMIMrev}WZv)gg>Izf+z_G#hTXGYqEuO8n? zK$&I~nKY%6xc9s(oNZYVooR-mZ2cU&w+i~^0*)N;4W5km6JsvW2Ex%=+oCWnhVqL{ zna0XlfAFn3nd(3dfRh}UeJN^Z9S6@t&BAtynt83588-xrwRtz5OdMaVwn}w8Onb5k zCpMKKz63NAYToQ;1cIUzt%H3FcQ3r>-XVO>Ig@$pz-gN{brNa#LjzQKh@`NVE+1Q{ zKhsWDxmmRa`W`3{OKCrzFFM|1pJ+qND1f&~=#!U{j_ss&^}Cx0!De=Udo9huYobxb z88p6sq`^^h@(Z%g93`3{lu{i_Uh~XF%1T7X^YFxa+N#>P3pI-uAl!cOK)?ZD!x=J_ z6|G6_4VYCathsYG{8oGkCo%V@7Hz9^ebYzr(W3J61E~}^TR!J!Mm>*s>ven&K5A9R zq%bIFPCL-HG|$&_fL#gD@I||l*_(e{Kf^!PL)XJ2BE#&eG04gKsg}pNkjKK{(?>rZ zS9*Q(7`7FXAZK%4BKqdtNp2dAWEWzIdxCHB-=3v7M7ZqyQ48afD%UL+<$@L7-_G`< z!OII_TBMd|_05G=DWAQ#G9W1$A(|>Ax@(NpsU)dk2Mi{lBUbGNZMprnM<16YIfU!% z1-P_mWbAA!?L}gTs~GvbXyo1-n)AJr-8Or`_Nh28fnaJ&?_Zclg(O5>2J@J4>TH1F sN1K*#KisAN#_azM-TxmnliA5)Yd@oMaWx3S|L->gY6df{y6zVJFZ?4Tr2qf` literal 0 HcmV?d00001 diff --git a/source/core/assets/images/projectiles/stun_effect.atlas b/source/core/assets/images/projectiles/stun_effect.atlas new file mode 100644 index 000000000..a50132d0b --- /dev/null +++ b/source/core/assets/images/projectiles/stun_effect.atlas @@ -0,0 +1,41 @@ + +stun_effect.png +size: 256, 32 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +projectile + rotate: false + xy: 86, 3 + size: 41, 27 + orig: 41, 27 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 2, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 129, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 44, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 86, 3 + size: 41, 27 + orig: 41, 27 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/projectiles/stun_effect.png b/source/core/assets/images/projectiles/stun_effect.png new file mode 100644 index 0000000000000000000000000000000000000000..238eac60d99c88d68091d07bfcbeeafbfad971f7 GIT binary patch literal 1146 zcmV-=1cm#FP)xDbR0;@*XVE_AP3!FTZ4ViIBqS@;4%CxT6e%I;Iliu+);68G~<8vNc_$!6Il&Ce<$Hk|^)y0>?)z$ZhtKT0E z1|D)cd2xGIuc9&>&=PrJU4DIF%WKr-w~z6-T5$g*%6W8ua}NUUiwkB-{yA!6ZF0kLFKAHAQ(~X^{#JvQXn+MMC>BIQG3d5De|JA7 zO(&6Sb&u@Be4d&6SlzDwKp<9s0C zfvu%yu>&|kLSP5M_8E0oPl2iLoq2@w)QO893m<)?W>(i6S1X%hUQ&au3qPmWb3Bki zH^miZRt&b!c)Oy+V~bfIArIZMWB~H@+@A_G)2;it+^O7~;W3cbnbC~@T9@$@Qj}El&1yDRl zq9;~uuiSph590e%&njXb0JeRqO|bwt0Z=qs#)87vJP4R-KeS?BDD;TmPe^(6ZKm2D z9rjoH5D?e>J+2mBv0vBNp8->aZ%P%v27o;Rf*b>O`g)xN9Bf+-z6g{a2&x5t8;`ba zFhe!;=z!Oa{|snKd2Znq`iy>Xph=0(b0;SFo%^fSVoNBv7CyZI3Ce?M=T3G?!OzFKE)!z#9}ie%Yyl)eOa>1$1|DZD{-F)4_9d&g z1)B6|voFuUsM;QLSo^s_phT^_dV41Q80bF-lfh)k;KJ>AADFvW { projectile.addComponent(new EffectsComponent(targetLayer, 3, ProjectileEffects.SLOW, aoe)); @@ -103,6 +99,15 @@ public static Entity createEffectProjectile(short targetLayer, Vector2 destinati } case STUN -> { projectile.addComponent(new EffectsComponent(targetLayer, 3, ProjectileEffects.STUN, aoe)); + AnimationRenderComponent animator = + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset("images/projectiles/stun_effect.atlas", TextureAtlas.class)); + animator.addAnimation(START_ANIM, 0.1f, Animation.PlayMode.LOOP); + + projectile + .addComponent(animator) + .addComponent(new StunEffectProjectileAnimationController()); } } return projectile; From 3a5d0725bda177427286a341c6585b5c6a0efbb8 Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 00:41:40 +1000 Subject: [PATCH 10/22] Added JUnit testing for stun and burn effect --- .../factories/ProjectileFactoryTest.java | 59 ++++++++++++++++--- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java index dd0e04eb9..c9bdd3d16 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java @@ -10,14 +10,8 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; -import com.csse3200.game.components.CombatStatsComponent; -import com.csse3200.game.components.CostComponent; -import com.csse3200.game.components.DeleteOnMapEdgeComponent; -import com.csse3200.game.components.TouchAttackComponent; -import com.csse3200.game.components.projectile.EngineerBulletsAnimationController; -import com.csse3200.game.components.projectile.MobKingProjectAnimController; -import com.csse3200.game.components.projectile.MobProjectileAnimationController; -import com.csse3200.game.components.projectile.ProjectileAnimationController; +import com.csse3200.game.components.*; +import com.csse3200.game.components.projectile.*; import com.csse3200.game.entities.Entity; import com.csse3200.game.extensions.GameExtension; import com.csse3200.game.physics.PhysicsLayer; @@ -48,7 +42,9 @@ class ProjectileFactoryTest { "images/projectiles/mobProjectile.atlas", "images/projectiles/basic_projectile.atlas", "images/projectiles/mobKing_projectile.atlas", - "images/projectiles/engineer_projectile.atlas" + "images/projectiles/engineer_projectile.atlas", + "images/projectiles/stun_effect.atlas", + "images/projectiles/burn_effect.atlas" }; private final String[] animations = { @@ -208,5 +204,50 @@ public void testEngineerAnimationController() { assertNotNull(engineerBullet.getComponent(EngineerBulletsAnimationController.class), "Engineer Bullet does not have Animation Controller"); } + + @Test + public void testStunProjectileCreation() { + Entity stunProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f, + 0.1f), new Vector2(2,2), ProjectileEffects.STUN, false); + assertNotNull(stunProjectile, "stunProjectile is null"); + } + + @Test + public void testStunProjectileAnimationRenderComponent() { + Entity stunProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f,01f), + new Vector2(2,2), ProjectileEffects.STUN, false); + assertNotNull(stunProjectile.getComponent(AnimationRenderComponent.class), + "Stun Projectile does not have AnimationRenderComponent"); + } + + @Test + public void testStunProjectileAnimationController() { + Entity stunProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f) + , new Vector2(2,2), ProjectileEffects.STUN, false); + assertNotNull(stunProjectile.getComponent(StunEffectProjectileAnimationController.class), + "Stun Projectile does not have Animation Controller"); + } + + @Test + public void testBurnProjectileCreation() { + Entity burnProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f, + 0.1f), new Vector2(2,2), ProjectileEffects.BURN, false); + assertNotNull(burnProjectile, "burnProjectile is null"); + } + + @Test + public void testBurnProjectileAnimationRenderComponent() { + Entity burnProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f,01f), + new Vector2(2,2), ProjectileEffects.BURN, false); + assertNotNull(burnProjectile.getComponent(AnimationRenderComponent.class), + "Burn Projectile does not have AnimationRenderComponent"); + } + @Test + public void testBurnProjectileAnimationController() { + Entity burnProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f) + , new Vector2(2,2), ProjectileEffects.BURN, false); + assertNotNull(burnProjectile.getComponent(BurnEffectProjectileAnimationController.class), + "Burn Projectile does not have Animation Controller"); + } } From 173043351e80714b8606c0d487821be12a7cd842 Mon Sep 17 00:00:00 2001 From: freshc0w <121275444+freshc0w@users.noreply.github.com> Date: Mon, 11 Sep 2023 01:09:12 +1000 Subject: [PATCH 11/22] Fix and add more test cases for RicochetComponent --- .../components/RicochetComponentTest.java | 98 ++++++++++++++++--- 1 file changed, 86 insertions(+), 12 deletions(-) diff --git a/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java index db1e041ed..99f03805e 100644 --- a/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java @@ -1,5 +1,6 @@ package com.csse3200.game.components; +import static org.junit.jupiter.api.Assertions.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -10,68 +11,92 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.junit.Ignore; import org.junit.jupiter.api.BeforeEach; import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.areas.terrain.TerrainFactory; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.ProjectileFactory; +import com.csse3200.game.entities.factories.RenderFactory; import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsComponent; import com.csse3200.game.physics.components.PhysicsMovementComponent; +import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.rendering.Renderer; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ResourceService; import com.csse3200.game.services.ServiceLocator; +@ExtendWith(GameExtension.class) public class RicochetComponentTest { Entity projectile; Entity mob; + private final String[] atlas = { + "images/projectiles/mobProjectile.atlas", + "images/projectiles/basic_projectile.atlas", + "images/projectiles/mobKing_projectile.atlas", + "images/projectiles/engineer_projectile.atlas" + }; + @BeforeEach - void beforeEach() { + public void setUp() { GameTime gameTime = mock(GameTime.class); - when(gameTime.getDeltaTime()).thenReturn(0.03f); + when(gameTime.getDeltaTime()).thenReturn(0.02f); ServiceLocator.registerTimeSource(gameTime); ServiceLocator.registerPhysicsService(new PhysicsService()); - ServiceLocator.registerEntityService(new EntityService()); 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.registerEntityService(new EntityService()); + // For the time being, NPC is treated as an enemy. projectile = createProjectile(PhysicsLayer.NPC); mob = createMobTarget(PhysicsLayer.NPC); ServiceLocator.getEntityService().register(projectile); ServiceLocator.getEntityService().register(mob); - ServiceLocator.registerResourceService(resourceService); - resourceService.loadAll(); } @Test - void shouldHaveRicochetComponent() { + public void shouldHaveRicochetComponent() { assertNotNull(projectile.getComponent(RicochetComponent.class), "Projectile does not contain RicochetComponent"); } @Test - void shouldDisposeAferCollision() { + public void shouldDisposeAferCollision() { + int currentEntities = ServiceLocator.getEntityService().getEntities().size; + projectile.getEvents().trigger("collisionEnd", projectile.getComponent(HitboxComponent.class).getFixture(), mob.getComponent(HitboxComponent.class).getFixture()); assertTrue("projectile entity flag should be true after collision", projectile.getFlagForDelete()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertEquals("Projectile should be deleted after collision upon update", currentEntities - 1, + ServiceLocator.getEntityService().getEntities().size); } - // @Test - @Ignore - void shouldSpawnAnotherProjectile() { + // @Ignore + @Test + public void shouldSpawnAnotherProjectileWithinMapBounds() { + projectile.setPosition(3, 3); int currentEntities = ServiceLocator.getEntityService().getEntities().size; // projectile.setPosition(2, 2); @@ -86,6 +111,55 @@ void shouldSpawnAnotherProjectile() { ServiceLocator.getEntityService().getEntities().size); } + @Test + public void shouldNotSpawnAnotherProjectileOutOfMapBounds() { + projectile.setPosition(-1, -1); + int currentEntities = ServiceLocator.getEntityService().getEntities().size; + + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertNotEquals(currentEntities, + ServiceLocator.getEntityService().getEntities().size, + "Should not have spawned another projectile upon collision"); + } + + @Test + public void testWithinRangeSpawnedProjectile() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + // For the time being, 2f seems to be the justifiable range + // for the new projectile to be spawned. + assertEquals("Projectile should be spawned within the range provided.", 1, + ServiceLocator.getEntityService().getNearbyEntities(mob, 2f).size); + } + + @Test + public void testNotWithinRangeShouldNotSpawnProjectile() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertEquals("Projectile should not be spawned too close to the original (now disposed) projectile and mob", 0, + ServiceLocator.getEntityService().getNearbyEntities(mob, 0.5f).size); + } + Entity createProjectile(short targetLayer) { Entity projectile = new Entity(); From e28b548a03d616a870665e31fbe597b44efba04b Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 11:35:12 +1000 Subject: [PATCH 12/22] Changed stun effect animation to suit the game more. --- .../images/projectiles/oldstun_effect.atlas | 41 ++++++++++++++++++ .../images/projectiles/oldstun_effect.png | Bin 0 -> 1146 bytes .../images/projectiles/stun_effect.atlas | 32 +++++++------- .../assets/images/projectiles/stun_effect.png | Bin 1146 -> 647 bytes .../components/tasks/StunTowerCombatTask.java | 3 +- .../destructors/ProjectileDestructors.java | 1 + 6 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 source/core/assets/images/projectiles/oldstun_effect.atlas create mode 100644 source/core/assets/images/projectiles/oldstun_effect.png diff --git a/source/core/assets/images/projectiles/oldstun_effect.atlas b/source/core/assets/images/projectiles/oldstun_effect.atlas new file mode 100644 index 000000000..a50132d0b --- /dev/null +++ b/source/core/assets/images/projectiles/oldstun_effect.atlas @@ -0,0 +1,41 @@ + +stun_effect.png +size: 256, 32 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +projectile + rotate: false + xy: 86, 3 + size: 41, 27 + orig: 41, 27 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 2, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 129, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 44, 2 + size: 40, 28 + orig: 40, 28 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 86, 3 + size: 41, 27 + orig: 41, 27 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/projectiles/oldstun_effect.png b/source/core/assets/images/projectiles/oldstun_effect.png new file mode 100644 index 0000000000000000000000000000000000000000..238eac60d99c88d68091d07bfcbeeafbfad971f7 GIT binary patch literal 1146 zcmV-=1cm#FP)xDbR0;@*XVE_AP3!FTZ4ViIBqS@;4%CxT6e%I;Iliu+);68G~<8vNc_$!6Il&Ce<$Hk|^)y0>?)z$ZhtKT0E z1|D)cd2xGIuc9&>&=PrJU4DIF%WKr-w~z6-T5$g*%6W8ua}NUUiwkB-{yA!6ZF0kLFKAHAQ(~X^{#JvQXn+MMC>BIQG3d5De|JA7 zO(&6Sb&u@Be4d&6SlzDwKp<9s0C zfvu%yu>&|kLSP5M_8E0oPl2iLoq2@w)QO893m<)?W>(i6S1X%hUQ&au3qPmWb3Bki zH^miZRt&b!c)Oy+V~bfIArIZMWB~H@+@A_G)2;it+^O7~;W3cbnbC~@T9@$@Qj}El&1yDRl zq9;~uuiSph590e%&njXb0JeRqO|bwt0Z=qs#)87vJP4R-KeS?BDD;TmPe^(6ZKm2D z9rjoH5D?e>J+2mBv0vBNp8->aZ%P%v27o;Rf*b>O`g)xN9Bf+-z6g{a2&x5t8;`ba zFhe!;=z!Oa{|snKd2Znq`iy>Xph=0(b0;SFo%^fSVoNBv7CyZI3Ce?M=T3G?!OzFKE)!z#9}ie%Yyl)eOa>1$1|DZD{-F)4_9d&g z1)B6|voFuUsM;QLSo^s_phT^_dV41Q80bF-lfh)k;KJ>AADFvWkl0w*Knw_80l|b=Sa<|BBqR_U60g7m@LtS_E>&NlMGBnbbAIuk#Ay;z zTlYz)w60@U{w~QSnau=25Cox_)x(ZAgv>FrU-lgN*tRWvT^xC1EbMv4p6_2#a$on2 z*K-2n6YoFu{q{<<$p*T6ubU7G~$b&OBE&&%HJkW z0+hdeI;U+xvA932#OUAqf|4l~k7^Dz-}3D&k0dZhy_V17?WiTe#0h}%i_a?+Moih> zI|)#(maWF;^}r{v&f+qQ9p4<{()galI1TmsiA1ExNqou~+1=rX7S_1HQI|;f7 z;{GA|+(uhn6LcDXtAK@f1wZeW5&FGB62X12uxyK%8iN)as(t4y;Au1c+faS0YCk9+ zkACi-B)r(P_>SO#5&-vYi`cQXpkN`$ZM4O^gEqJySNkB^k)M14Ncbet=fN%kBPM`- zD`+QyeHMrj#rrY7J+8$fiD3}QxahGO#qCn_D+95w`qgPzYPvro!y~HytM_jO0XK2MZ(N$QSW~AP9mW2!bF8 hf*=TjAP9nx0>4B(SuQrR2N(bV002ovPDHLkV1mRdBqjg= literal 1146 zcmV-=1cm#FP)xDbR0;@*XVE_AP3!FTZ4ViIBqS@;4%CxT6e%I;Iliu+);68G~<8vNc_$!6Il&Ce<$Hk|^)y0>?)z$ZhtKT0E z1|D)cd2xGIuc9&>&=PrJU4DIF%WKr-w~z6-T5$g*%6W8ua}NUUiwkB-{yA!6ZF0kLFKAHAQ(~X^{#JvQXn+MMC>BIQG3d5De|JA7 zO(&6Sb&u@Be4d&6SlzDwKp<9s0C zfvu%yu>&|kLSP5M_8E0oPl2iLoq2@w)QO893m<)?W>(i6S1X%hUQ&au3qPmWb3Bki zH^miZRt&b!c)Oy+V~bfIArIZMWB~H@+@A_G)2;it+^O7~;W3cbnbC~@T9@$@Qj}El&1yDRl zq9;~uuiSph590e%&njXb0JeRqO|bwt0Z=qs#)87vJP4R-KeS?BDD;TmPe^(6ZKm2D z9rjoH5D?e>J+2mBv0vBNp8->aZ%P%v27o;Rf*b>O`g)xN9Bf+-z6g{a2&x5t8;`ba zFhe!;=z!Oa{|snKd2Znq`iy>Xph=0(b0;SFo%^fSVoNBv7CyZI3Ce?M=T3G?!OzFKE)!z#9}ie%Yyl)eOa>1$1|DZD{-F)4_9d&g z1)B6|voFuUsM;QLSo^s_phT^_dV41Q80bF-lfh)k;KJ>AADFvW Date: Mon, 11 Sep 2023 14:14:05 +1000 Subject: [PATCH 13/22] Added anim JUnit for slow effect --- .../npc/XenoAnimationController.java | 5 ++++ .../player/HumanAnimationController.java | 4 +-- .../destructors/ProjectileDestructors.java | 1 - .../factories/ProjectileFactoryTest.java | 25 ++++++++++++++++++- 4 files changed, 31 insertions(+), 4 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..2baddffa0 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,13 +1,18 @@ package com.csse3200.game.components.npc; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class XenoAnimationController extends Component { + private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; + Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( + COLLISION_SFX, Sound.class); AnimationRenderComponent animator; @Override diff --git a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java index e65fc8763..87a358e81 100644 --- a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java @@ -103,7 +103,7 @@ void animatePrepWalk() { */ void animateSingleFiring() { animator.startAnimation(FIRE_SINGLE_ANIM); - fireSingleSound.play(); +// fireSingleSound.play(); } /** @@ -112,7 +112,7 @@ void animateSingleFiring() { */ void animateFiring() { animator.startAnimation(FIRE_AUTO_ANIM); - fireAutoSound.play(); +// fireAutoSound.play(); } /** diff --git a/source/core/src/main/com/csse3200/game/entities/destructors/ProjectileDestructors.java b/source/core/src/main/com/csse3200/game/entities/destructors/ProjectileDestructors.java index 1df39162d..2fbd01930 100644 --- a/source/core/src/main/com/csse3200/game/entities/destructors/ProjectileDestructors.java +++ b/source/core/src/main/com/csse3200/game/entities/destructors/ProjectileDestructors.java @@ -15,7 +15,6 @@ public class ProjectileDestructors { */ public static Entity destroyProjectile(Entity projectile) { projectile.dispose(); - projectile.getEvents().trigger(""); return projectile; } /** diff --git a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java index c9bdd3d16..b1e4969d1 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java @@ -44,7 +44,8 @@ class ProjectileFactoryTest { "images/projectiles/mobKing_projectile.atlas", "images/projectiles/engineer_projectile.atlas", "images/projectiles/stun_effect.atlas", - "images/projectiles/burn_effect.atlas" + "images/projectiles/burn_effect.atlas", + "images/projectiles/snow_ball.atlas" }; private final String[] animations = { @@ -249,5 +250,27 @@ public void testBurnProjectileAnimationController() { assertNotNull(burnProjectile.getComponent(BurnEffectProjectileAnimationController.class), "Burn Projectile does not have Animation Controller"); } + + @Test + public void testSlowProjectileCreation() { + Entity slowProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f, + 0.1f), new Vector2(2,2), ProjectileEffects.SLOW, false); + assertNotNull(slowProjectile, "slowProjectile is null"); + } + + @Test + public void testSlowProjectileAnimationRenderComponent() { + Entity slowProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, new Vector2(0.1f,01f), + new Vector2(2,2), ProjectileEffects.SLOW, false); + assertNotNull(slowProjectile.getComponent(AnimationRenderComponent.class), + "Slow Projectile does not have AnimationRenderComponent"); + } + @Test + public void testSlowProjectileAnimationController() { + Entity slowProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f) + , new Vector2(2,2), ProjectileEffects.SLOW, false); + assertNotNull(slowProjectile.getComponent(SnowBallProjectileAnimationController.class), + "Slow Projectile does not have Animation Controller"); + } } From dd27f67a0fe33a5286d54cc3b72482599c97ac0c Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 14:44:26 +1000 Subject: [PATCH 14/22] Added animations for SplitFireworksComponent --- .../images/projectiles/firework_anim.atlas | 41 ++++++++ .../images/projectiles/firework_anim.png | Bin 0 -> 439 bytes .../csse3200/game/areas/ForestGameArea.java | 6 +- .../components/SplitFireworksComponent.java | 2 +- .../player/HumanAnimationController.java | 4 +- .../FireworkAnimationController.java | 26 +++++ .../entities/factories/ProjectileFactory.java | 91 +++++++++++------- 7 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 source/core/assets/images/projectiles/firework_anim.atlas create mode 100644 source/core/assets/images/projectiles/firework_anim.png create mode 100644 source/core/src/main/com/csse3200/game/components/projectile/FireworkAnimationController.java diff --git a/source/core/assets/images/projectiles/firework_anim.atlas b/source/core/assets/images/projectiles/firework_anim.atlas new file mode 100644 index 000000000..45f2d54c9 --- /dev/null +++ b/source/core/assets/images/projectiles/firework_anim.atlas @@ -0,0 +1,41 @@ + +firework_anim.png +size: 128, 32 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +projectile + rotate: false + xy: 23, 2 + size: 19, 16 + orig: 19, 16 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 65, 2 + size: 19, 16 + orig: 19, 16 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 44, 2 + size: 19, 16 + orig: 19, 16 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 2, 2 + size: 19, 16 + orig: 19, 16 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 23, 2 + size: 19, 16 + orig: 19, 16 + offset: 0, 0 + index: -1 diff --git a/source/core/assets/images/projectiles/firework_anim.png b/source/core/assets/images/projectiles/firework_anim.png new file mode 100644 index 0000000000000000000000000000000000000000..56a46b556a3db060f87fdb08a448c5b822a4764d GIT binary patch literal 439 zcmV;o0Z9IdP)-Wy>MB7A?|1N0Z3&#Tn&iK+5nwk{76r<=Ad%dpZFC z0Q{lPw>vjlou6+uqn4iU$u%s!xJC~he9sbST}iy$R@H0IBvF}bSjojR(aH>bTB2zQ zw4R@sY+PRNt7{F_LX{tV6LkFE(f>K_c)7MiBTW=|wFPF>4;m8H!;7t=& zjVLt__x(YKZx4(w{L1#oh;+KG2W@kOzk3(Ji>=hf3F2t z*IxO_UC!s0AU@}Ck_Ik~_|10!JN(84h{JMf*JGRXtjX)H { projectile.addComponent(new EffectsComponent(targetLayer, 3, ProjectileEffects.FIREBALL, aoe)); AnimationRenderComponent animator = - new AnimationRenderComponent( - ServiceLocator.getResourceService() - .getAsset(BASE_PROJECTILE_ATLAS, TextureAtlas.class)); + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset(BASE_PROJECTILE_ATLAS, TextureAtlas.class)); animator.addAnimation(START_ANIM, START_SPEED, Animation.PlayMode.NORMAL); animator.addAnimation(FINAL_ANIM, FINAL_SPEED, Animation.PlayMode.NORMAL); - projectile - .addComponent(animator) - .addComponent(new ProjectileAnimationController()); + projectile + .addComponent(animator) + .addComponent(new ProjectileAnimationController()); } case BURN -> { projectile.addComponent(new EffectsComponent(targetLayer, 3, ProjectileEffects.BURN, aoe)); AnimationRenderComponent animator = - new AnimationRenderComponent( - ServiceLocator.getResourceService() - .getAsset("images/projectiles/burn_effect.atlas", TextureAtlas.class)); + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset("images/projectiles/burn_effect.atlas", TextureAtlas.class)); animator.addAnimation(START_ANIM, START_SPEED, Animation.PlayMode.NORMAL); animator.addAnimation(FINAL_ANIM, FINAL_SPEED, Animation.PlayMode.NORMAL); - projectile - .addComponent(animator) - .addComponent(new BurnEffectProjectileAnimationController()); + projectile + .addComponent(animator) + .addComponent(new BurnEffectProjectileAnimationController()); } case SLOW -> { projectile.addComponent(new EffectsComponent(targetLayer, 3, ProjectileEffects.SLOW, aoe)); AnimationRenderComponent animator = - new AnimationRenderComponent( - ServiceLocator.getResourceService() - .getAsset("images/projectiles/snow_ball.atlas", TextureAtlas.class)); + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset("images/projectiles/snow_ball.atlas", TextureAtlas.class)); animator.addAnimation(START_ANIM, START_SPEED, Animation.PlayMode.NORMAL); animator.addAnimation(FINAL_ANIM, FINAL_SPEED, Animation.PlayMode.NORMAL); - projectile - .addComponent(animator) - .addComponent(new SnowBallProjectileAnimationController()); + projectile + .addComponent(animator) + .addComponent(new SnowBallProjectileAnimationController()); // * TEMPORARY // .addComponent(new DeleteOnMapEdgeComponent()); // .addComponent(new SelfDestructOnHitComponent(PhysicsLayer.OBSTACLE)); @@ -110,7 +112,7 @@ public static Entity createEffectProjectile(short targetLayer, Vector2 destinati .addComponent(new StunEffectProjectileAnimationController()); } } - return projectile; + return projectile; } /** @@ -132,8 +134,8 @@ public static Entity createPierceFireBall(short targetLayer, Vector2 destination public static Entity createRicochetFireball(short targetLayer, Vector2 destination, Vector2 speed, int bounceCount) { Entity fireBall = createFireBall(targetLayer, destination, speed); fireBall - .addComponent(new RicochetComponent(targetLayer, bounceCount)); - + .addComponent(new RicochetComponent(targetLayer, bounceCount)); + setColliderSize(fireBall, (float) 0.1, (float) 0.1); return fireBall; @@ -142,17 +144,17 @@ public static Entity createRicochetFireball(short targetLayer, Vector2 destinati public static Entity createSplitFireWorksFireball(short targetLayer, Vector2 destination, Vector2 speed, int amount) { Entity fireBall = createFireBall(targetLayer, destination, speed); fireBall - .addComponent(new SplitFireworksComponent(targetLayer, amount)); - + .addComponent(new SplitFireworksComponent(targetLayer, amount)); + return fireBall; } /** * Creates a fireball Entity. - * + * * @param targetLayer The enemy layer that the projectile collides with. * @param destination The destination the projectile heads towards. - * @param speed The speed of the projectile. + * @param speed The speed of the projectile. * @return Returns a new fireball projectile entity. */ public static Entity createFireBall(short targetLayer, Vector2 destination, Vector2 speed) { @@ -166,14 +168,31 @@ public static Entity createFireBall(short targetLayer, Vector2 destination, Vect animator.addAnimation(FINAL_ANIM, FINAL_SPEED, Animation.PlayMode.NORMAL); projectile - .addComponent(animator) - .addComponent(new ProjectileAnimationController()); - // * TEMPORARY - // .addComponent(new DeleteOnMapEdgeComponent()); - // .addComponent(new SelfDestructOnHitComponent(PhysicsLayer.OBSTACLE)); + .addComponent(animator) + .addComponent(new ProjectileAnimationController()); + // * TEMPORARY + // .addComponent(new DeleteOnMapEdgeComponent()); + // .addComponent(new SelfDestructOnHitComponent(PhysicsLayer.OBSTACLE)); return projectile; } + + public static Entity createFireworks(short targetLayer, Vector2 destination, Vector2 speed) { + Entity projectile = createBaseProjectile(targetLayer, destination, speed); + + AnimationRenderComponent animator = + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset("images/projectiles/firework_anim.atlas", TextureAtlas.class)); + animator.addAnimation(START_ANIM, 0.2f, Animation.PlayMode.LOOP); + projectile + .addComponent(animator) + .addComponent(new FireworkAnimationController()); + + return projectile; + } + + /** * Creates a engineer bullet * From c304c9aece219973cabe709742b2aa89038c9f75 Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 14:49:12 +1000 Subject: [PATCH 15/22] Added anim JUnit tests for fireworks --- .../factories/ProjectileFactoryTest.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java index b1e4969d1..1065562d4 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java @@ -45,7 +45,8 @@ class ProjectileFactoryTest { "images/projectiles/engineer_projectile.atlas", "images/projectiles/stun_effect.atlas", "images/projectiles/burn_effect.atlas", - "images/projectiles/snow_ball.atlas" + "images/projectiles/snow_ball.atlas", + "images/projectiles/firework_anim.atlas" }; private final String[] animations = { @@ -272,5 +273,27 @@ public void testSlowProjectileAnimationController() { assertNotNull(slowProjectile.getComponent(SnowBallProjectileAnimationController.class), "Slow Projectile does not have Animation Controller"); } + + @Test + public void testFireworkProjectileCreation() { + Entity fireworkProjectile = ProjectileFactory.createFireworks( + PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireworkProjectile, "fireworkProjectile is null"); + } + + @Test + public void testFireworkProjectileAnimationRenderComponent() { + Entity fireworkProjectile = ProjectileFactory.createFireworks( + PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireworkProjectile.getComponent(AnimationRenderComponent.class), + "Slow Projectile does not have AnimationRenderComponent"); + } + @Test + public void testFireworkProjectileAnimationController() { + Entity fireworkProjectile = ProjectileFactory.createFireworks( + PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); + assertNotNull(fireworkProjectile.getComponent(FireworkAnimationController.class), + "Slow Projectile does not have Animation Controller"); + } } From 03ef30c6a882f3ede0537086b57f65c8055b14af Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 14:51:54 +1000 Subject: [PATCH 16/22] Fixed typo in firework tests --- .../game/entities/factories/ProjectileFactoryTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java index 1065562d4..9c4129a40 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/ProjectileFactoryTest.java @@ -286,14 +286,14 @@ public void testFireworkProjectileAnimationRenderComponent() { Entity fireworkProjectile = ProjectileFactory.createFireworks( PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); assertNotNull(fireworkProjectile.getComponent(AnimationRenderComponent.class), - "Slow Projectile does not have AnimationRenderComponent"); + "Fire Projectile does not have AnimationRenderComponent"); } @Test public void testFireworkProjectileAnimationController() { Entity fireworkProjectile = ProjectileFactory.createFireworks( PhysicsLayer.TOWER, new Vector2(0.1f, 0.1f), new Vector2(1f, 1f)); assertNotNull(fireworkProjectile.getComponent(FireworkAnimationController.class), - "Slow Projectile does not have Animation Controller"); + "Fire Projectile does not have Animation Controller"); } } From 1abe56bd086b4b3fe499e9fd57c642ce79a8ad0f Mon Sep 17 00:00:00 2001 From: freshc0w <121275444+freshc0w@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:36:51 +1000 Subject: [PATCH 17/22] Finalise SplitFireworksComponent and RicochetComponent tests --- .../components/SplitFireworksComponent.java | 11 +- .../components/RicochetComponentTest.java | 58 ++--- .../SplitFireworksComponentTest.java | 213 ++++++++++++++++++ 3 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 source/core/src/test/com/csse3200/game/components/SplitFireworksComponentTest.java diff --git a/source/core/src/main/com/csse3200/game/components/SplitFireworksComponent.java b/source/core/src/main/com/csse3200/game/components/SplitFireworksComponent.java index a48f6595a..58d808aab 100644 --- a/source/core/src/main/com/csse3200/game/components/SplitFireworksComponent.java +++ b/source/core/src/main/com/csse3200/game/components/SplitFireworksComponent.java @@ -18,16 +18,17 @@ public class SplitFireworksComponent extends Component { private HitboxComponent hitboxComponent; private int amount; private static int TOTAL_RANGE = 450; + private static double SPAWN_OFFSET_X = 1.75; /** - * Initialises a component that splits the projectile into multiple fireballs + * Initialises a component that splits the projectile into multiple fireballs * upon collision on a specified target layer. - * The spawned projectiles will be spawned just before original projectile + * The spawned projectiles will be spawned just before original projectile * and spread out in multiple direction set by a certain range. * Assumes amount of split projectiles is greater or equal than 2. * * @param targetLayer Target layer upon collision. - * @param amount Amount of projectiles that is split after collision event. + * @param amount Amount of projectiles that is split after collision event. */ public SplitFireworksComponent(short targetLayer, int amount) { this.targetLayer = targetLayer; @@ -52,14 +53,14 @@ private void onCollisionEnd(Fixture me, Fixture other) { int newDirection = (i * TOTAL_RANGE) / (amount - 1); // Boundaries - float newXPosition = (float) (projectile.getPosition().x + 1.75); + float newXPosition = (float) (projectile.getPosition().x + SPAWN_OFFSET_X); if (newXPosition >= 18 || newXPosition <= 1) return; // * RIGHT NOW TARGET IS NPC, SUBJECT TO CHANGE // Speed is a bit faster than normal but can change. Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, - new Vector2(100, projectile.getPosition().y + (newDirection - (TOTAL_RANGE/2))), new Vector2(3f, 3f)); + new Vector2(100, projectile.getPosition().y + (newDirection - (TOTAL_RANGE / 2))), new Vector2(3f, 3f)); newProjectile.setPosition(newXPosition, (float) projectile.getPosition().y); diff --git a/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java index 99f03805e..3698767aa 100644 --- a/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/RicochetComponentTest.java @@ -3,26 +3,18 @@ import static org.junit.jupiter.api.Assertions.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.Ignore; import org.junit.jupiter.api.BeforeEach; import com.badlogic.gdx.math.Vector2; -import com.csse3200.game.areas.ForestGameArea; -import com.csse3200.game.areas.terrain.TerrainFactory; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.ProjectileFactory; -import com.csse3200.game.entities.factories.RenderFactory; import com.csse3200.game.extensions.GameExtension; -import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.physics.components.HitboxComponent; @@ -30,7 +22,6 @@ import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.rendering.RenderService; -import com.csse3200.game.rendering.Renderer; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ResourceService; import com.csse3200.game.services.ServiceLocator; @@ -63,12 +54,19 @@ public void setUp() { ServiceLocator.registerEntityService(new EntityService()); // For the time being, NPC is treated as an enemy. - projectile = createProjectile(PhysicsLayer.NPC); + // projectile = createProjectile(PhysicsLayer.NPC); + projectile = ProjectileFactory.createRicochetFireball(PhysicsLayer.NPC, new Vector2(0.1f, 0.1f), + new Vector2(2f, 2f), 0); mob = createMobTarget(PhysicsLayer.NPC); ServiceLocator.getEntityService().register(projectile); ServiceLocator.getEntityService().register(mob); } + @Test + public void shouldNotBeNull() { + assertNotNull(projectile, "Ricochet projectile does not exist"); + } + @Test public void shouldHaveRicochetComponent() { assertNotNull(projectile.getComponent(RicochetComponent.class), @@ -79,9 +77,7 @@ public void shouldHaveRicochetComponent() { public void shouldDisposeAferCollision() { int currentEntities = ServiceLocator.getEntityService().getEntities().size; - projectile.getEvents().trigger("collisionEnd", - projectile.getComponent(HitboxComponent.class).getFixture(), - mob.getComponent(HitboxComponent.class).getFixture()); + triggerCollisionEnd(projectile, mob); assertTrue("projectile entity flag should be true after collision", projectile.getFlagForDelete()); @@ -95,30 +91,25 @@ public void shouldDisposeAferCollision() { // @Ignore @Test - public void shouldSpawnAnotherProjectileWithinMapBounds() { + public void shouldSpawnAnotherProjWithinMapBounds() { projectile.setPosition(3, 3); int currentEntities = ServiceLocator.getEntityService().getEntities().size; - // projectile.setPosition(2, 2); - projectile.getEvents().trigger("collisionEnd", - projectile.getComponent(HitboxComponent.class).getFixture(), - mob.getComponent(HitboxComponent.class).getFixture()); + triggerCollisionEnd(projectile, mob); ServiceLocator.getPhysicsService().getPhysics().update(); ServiceLocator.getEntityService().update(); - assertEquals("Should spawn another ricochet projectile", currentEntities, + assertEquals("Should spawn another ricochet projectile within map bounds", currentEntities, ServiceLocator.getEntityService().getEntities().size); } @Test - public void shouldNotSpawnAnotherProjectileOutOfMapBounds() { + public void shouldNotSpawnAnotherProjOutOfMapBounds() { projectile.setPosition(-1, -1); int currentEntities = ServiceLocator.getEntityService().getEntities().size; - projectile.getEvents().trigger("collisionEnd", - projectile.getComponent(HitboxComponent.class).getFixture(), - mob.getComponent(HitboxComponent.class).getFixture()); + triggerCollisionEnd(projectile, mob); ServiceLocator.getPhysicsService().getPhysics().update(); ServiceLocator.getEntityService().update(); @@ -132,9 +123,8 @@ public void shouldNotSpawnAnotherProjectileOutOfMapBounds() { public void testWithinRangeSpawnedProjectile() { projectile.setPosition(3, 3); mob.setPosition(3, 3); - projectile.getEvents().trigger("collisionEnd", - projectile.getComponent(HitboxComponent.class).getFixture(), - mob.getComponent(HitboxComponent.class).getFixture()); + + triggerCollisionEnd(projectile, mob); ServiceLocator.getPhysicsService().getPhysics().update(); ServiceLocator.getEntityService().update(); @@ -149,9 +139,7 @@ public void testWithinRangeSpawnedProjectile() { public void testNotWithinRangeShouldNotSpawnProjectile() { projectile.setPosition(3, 3); mob.setPosition(3, 3); - projectile.getEvents().trigger("collisionEnd", - projectile.getComponent(HitboxComponent.class).getFixture(), - mob.getComponent(HitboxComponent.class).getFixture()); + triggerCollisionEnd(projectile, mob); ServiceLocator.getPhysicsService().getPhysics().update(); ServiceLocator.getEntityService().update(); @@ -184,4 +172,16 @@ Entity createMobTarget(short layer) { return target; } + + /** + * Assumes both entity has hitbox components. + * + * @param projectile + * @param mob + */ + void triggerCollisionEnd(Entity projectile, Entity mob) { + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + } } diff --git a/source/core/src/test/com/csse3200/game/components/SplitFireworksComponentTest.java b/source/core/src/test/com/csse3200/game/components/SplitFireworksComponentTest.java new file mode 100644 index 000000000..241a98845 --- /dev/null +++ b/source/core/src/test/com/csse3200/game/components/SplitFireworksComponentTest.java @@ -0,0 +1,213 @@ +package com.csse3200.game.components; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.csse3200.game.entities.factories.ProjectileFactory; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.physics.components.PhysicsComponent; +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; + +@ExtendWith(GameExtension.class) +public class SplitFireworksComponentTest { + Entity projectile; + Entity mob; + static double OFFSET_X = 1.75; + + private final String[] atlas = { + "images/projectiles/mobProjectile.atlas", + "images/projectiles/basic_projectile.atlas", + "images/projectiles/mobKing_projectile.atlas", + "images/projectiles/engineer_projectile.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.registerEntityService(new EntityService()); + + // For the time being, NPC is treated as an enemy. + projectile = createSplitFireworkProjectile(PhysicsLayer.NPC, 3); + mob = createMobTarget(PhysicsLayer.NPC); + ServiceLocator.getEntityService().register(projectile); + ServiceLocator.getEntityService().register(mob); + } + + @Test + public void shouldNotBeNull() { + assertNotNull(projectile, "Ricochet projectile does not exist"); + } + + @Test + public void shouldHaveSplitFireworksComponent() { + assertNotNull(projectile.getComponent(SplitFireworksComponent.class), + "Projectile does not contain SplitFireworksComponent"); + } + + @Test + public void shouldDisposeAferCollision() { + triggerCollisionEnd(projectile, mob); + + assertTrue("original projectile entity flag should be true after collision", + projectile.getFlagForDelete()); + } + + @Test + void shouldSpawnCorrectNumberOfProjs() { + projectile.setPosition(3, 3); + + int initialNumEntities = ServiceLocator.getEntityService().getEntities().size; + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + // initialNumEntities + 2 to account for the dispose of the original projectile. + assertEquals("Should spawn correct number of projectiles after collision based on amount given", + initialNumEntities + 2, ServiceLocator.getEntityService().getEntities().size); + } + + @Test + public void shouldSpawnMultProjWithinMapBounds() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + + int initialNumEntities = ServiceLocator.getEntityService().getEntities().size; + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertTrue("SplitFireWorks projectile should spawn multiple projectile out of map bounds", + ServiceLocator.getEntityService().getEntities().size > initialNumEntities); + } + + @Test + public void shouldNotSpawnMultProjOutOfMapBounds() { + projectile.setPosition(22, 22); + mob.setPosition(22, 22); + + int initialNumEntities = ServiceLocator.getEntityService().getEntities().size; + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertFalse(ServiceLocator.getEntityService().getEntities().size > initialNumEntities, + "SplitFireWorks projectile should not spawn multiple projectile out of map bounds"); + } + + @Test + public void testWithinRangeSpawnedProjectiles() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertEquals("Projectiles should be spawned within the range provided.", 3, + ServiceLocator.getEntityService().getNearbyEntities(mob, 2f).size); + } + + @Test + public void testTooCloseRangeSpawnedProjectiles() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + assertNotEquals(3, + ServiceLocator.getEntityService().getNearbyEntities(mob, 0.5f).size, + "Projectiles should not be spawned too close upon impact."); + } + + @Test + public void shouldSpawnAtSpecifiedLocation() { + projectile.setPosition(3, 3); + mob.setPosition(3, 3); + float currPosition = projectile.getPosition().x; + + triggerCollisionEnd(projectile, mob); + + ServiceLocator.getPhysicsService().getPhysics().update(); + ServiceLocator.getEntityService().update(); + + float newXPosition = (float) (currPosition + OFFSET_X); + + Array allEntities = ServiceLocator.getEntityService().getEntities(); + + for (Entity entity : allEntities) { + if (entity == mob) + continue; + + assertEquals("Projectiles were not spawned at the right offset x placement", newXPosition, entity.getPosition().x, + 0.02); + } + } + + Entity createSplitFireworkProjectile(short targetLayer, int amount) { + Entity projectile = ProjectileFactory.createSplitFireWorksFireball(targetLayer, new Vector2(100, 3), + new Vector2(2f, 2f), amount); + + return projectile; + } + + Entity createMobTarget(short layer) { + Entity target = new Entity(); + + target + .addComponent(new CombatStatsComponent(100, 0)) + .addComponent(new PhysicsComponent()) + .addComponent(new HitboxComponent().setLayer(layer)); + + return target; + } + + /** + * Assumes both entity has hitbox components. + * + * @param projectile + * @param mob + */ + void triggerCollisionEnd(Entity projectile, Entity mob) { + projectile.getEvents().trigger("collisionEnd", + projectile.getComponent(HitboxComponent.class).getFixture(), + mob.getComponent(HitboxComponent.class).getFixture()); + } +} From 2379fd7f3b3fac1a2429d65bae88e7fa66fccbe0 Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 15:46:21 +1000 Subject: [PATCH 18/22] Added animation to pierce fireball --- .../images/projectiles/pierce_anim.atlas | 42 ++++++++++++++++++ .../assets/images/projectiles/pierce_anim.png | Bin 0 -> 1630 bytes .../csse3200/game/areas/ForestGameArea.java | 6 ++- .../PierceProjectileAnimationController.java | 25 +++++++++++ .../entities/factories/ProjectileFactory.java | 27 ++++++++++- 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 source/core/assets/images/projectiles/pierce_anim.atlas create mode 100644 source/core/assets/images/projectiles/pierce_anim.png create mode 100644 source/core/src/main/com/csse3200/game/components/projectile/PierceProjectileAnimationController.java diff --git a/source/core/assets/images/projectiles/pierce_anim.atlas b/source/core/assets/images/projectiles/pierce_anim.atlas new file mode 100644 index 000000000..0dea23b97 --- /dev/null +++ b/source/core/assets/images/projectiles/pierce_anim.atlas @@ -0,0 +1,42 @@ + +pierce_anim.png +size: 256, 32 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +projectile + rotate: false + xy: 2, 2 + size: 35, 26 + orig: 35, 26 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 76, 2 + size: 35, 26 + orig: 35, 26 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 39, 2 + size: 35, 26 + orig: 35, 26 + offset: 0, 0 + index: -1 +projectile + rotate: false + xy: 113, 2 + size: 35, 26 + orig: 35, 26 + offset: 0, 0 + index: -1 +default +projectile + rotate: false + xy: 2, 2 + size: 35, 26 + orig: 35, 26 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/projectiles/pierce_anim.png b/source/core/assets/images/projectiles/pierce_anim.png new file mode 100644 index 0000000000000000000000000000000000000000..e9c349e6f6e861baa3296ebc480321d230054587 GIT binary patch literal 1630 zcmV-k2BG*%SJl-&vdrOd zI2;a#!{Kl^9OL4>#S?+&me#V5PpoEN-oKpvu(6c=@^Fz3$IOC>K8VwV6&DEML4Xh< z1Uad=Q0Mv8T`{Suw3L*n(0E__wg-{{babv>vsE2i3xOXMA_v7iK_`eJGVkq$6cOEQ= zzx&f>*8P5SqGn)^QHl;nDQvRj42iD%=7CN@cq)`pp`yR?^x^RTl_ze^{(R=;(}1ejS1V(+)!U$XTQx}JP~`MF6VYn_*?tp?|#>e5wP!hIs#MX zcU93pkk1I}0&%IiF;18t%-J5hoRRqJ^oQesz$S<$7e_#lLa=6l5g6iy zh_@cu6Z0@=S#0~;i=9aHh0)Yd%cP8evy`ePpk-D3rNU3Nt7efZAGnnpK@Af?AAw(= zS_<*$%!F}T@;Aduec?D@U}7jCh7VWbkp@CnQE0;BbNlhV>HF``-yWv!Wk4BXQ#)>}@vc_je`W|h(VS8InO`w7SXkUR`hp>IYeFk9;dYWeGa8v>l z2IBZ)J&e#pP2lP)ogn^eFD;as08bTC;qkvG5Seyk=xD^ zP#>*TzoyUqf+3t=+cN`QC_}xva-P~2{X) zlbR*r6K!x`2A$S8904|I$vV(vv**c41IWJ%vw%15i0V=UQ1P=49r;HAx3%Z>ISczP zebWEEj(tOIRpT!RF(kID=H?KJ_r-=plmqs5Se+KMS|+mhSiP(%qEeBL@~~8D zmXtC9wlV43r5$qsJ;-VTniK_L4o&CQH~zvD^h=u_nRd(xY+^!i zH~N)VHYPB2?rLa7X{&7nwv9n-`ju%Af16&K;+P}gz(a6tdg&!&NUdI1;iO^POK}pQ z5wzj8X^uGrlb6Cnvb5o~*H&C99yF*K+^83)IvkFczzQFn)~nMU4u`|xa5x+ehr{7; cI2_Z*|0?^K>d}?P Date: Mon, 11 Sep 2023 16:00:29 +1000 Subject: [PATCH 19/22] Fixed bug to pass JUnit testing --- .../csse3200/game/entities/factories/ProjectileFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java index 5977b2dba..578b1abf4 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java @@ -169,7 +169,7 @@ public static Entity createFireBall(short targetLayer, Vector2 destination, Vect projectile .addComponent(animator) - .addComponent(new PierceProjectileAnimationController()); + .addComponent(new ProjectileAnimationController()); // * TEMPORARY // .addComponent(new DeleteOnMapEdgeComponent()); // .addComponent(new SelfDestructOnHitComponent(PhysicsLayer.OBSTACLE)); @@ -210,7 +210,7 @@ public static Entity createPierceBallAnim(short targetLayer, Vector2 destination animator.addAnimation(START_ANIM, 0.05f, Animation.PlayMode.LOOP); projectile .addComponent(animator) - .addComponent(new FireworkAnimationController()); + .addComponent(new PierceProjectileAnimationController()); return projectile; } From a355fc0e24daf3b3b9821f3e98127d4f4a5c8701 Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 17:37:59 +1000 Subject: [PATCH 20/22] Changed Burn Effect Animation --- source/core/assets/images/projectiles/burn_effect.atlas | 4 ++-- .../csse3200/game/components/tasks/FireTowerCombatTask.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/core/assets/images/projectiles/burn_effect.atlas b/source/core/assets/images/projectiles/burn_effect.atlas index 2d422b19f..140875f0f 100644 --- a/source/core/assets/images/projectiles/burn_effect.atlas +++ b/source/core/assets/images/projectiles/burn_effect.atlas @@ -32,14 +32,14 @@ projectile orig: 36, 31 offset: 0, 0 index: -1 -projectileFinal +projectile rotate: false xy: 116, 2 size: 36, 31 orig: 36, 31 offset: 0, 0 index: -1 -projectile +projectileFinal rotate: false xy: 191, 2 size: 31, 31 diff --git a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java index 3ac568f1b..c70919487 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java @@ -3,6 +3,7 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.components.ProjectileEffects; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsEngine; @@ -102,8 +103,8 @@ public void updateTowerState() { towerState = STATE.IDLE; } else { owner.getEntity().getEvents().trigger(ATTACK); - Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, - new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); + Entity newProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, + new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), ProjectileEffects.BURN, false); newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), (float) (owner.getEntity().getPosition().y + 0.25)); ServiceLocator.getEntityService().register(newProjectile); From a8f7cecae1684015f47c4857b58b4805ee2c80cc Mon Sep 17 00:00:00 2001 From: freshc0w <121275444+freshc0w@users.noreply.github.com> Date: Mon, 11 Sep 2023 18:51:29 +1000 Subject: [PATCH 21/22] Commented out sound to fix Mob Junit --- .../game/components/npc/XenoAnimationController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 77907c597..b25b91e00 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,10 +14,10 @@ * of the events is triggered. */ public class XenoAnimationController extends Component { - // For on collision sounds later - private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - COLLISION_SFX, Sound.class); + // // For on collision sounds later + // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; + // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( + // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; @Override From a63f74dd1b43c6c68007b9c3cf3da784c9826cca Mon Sep 17 00:00:00 2001 From: cindyle1 Date: Mon, 11 Sep 2023 19:12:10 +1000 Subject: [PATCH 22/22] Readded atlas images --- .../main/com/csse3200/game/areas/ForestGameArea.java | 10 ++++++---- 1 file changed, 6 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 4f08c902a..0c3c3e46a 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -93,8 +93,6 @@ public class ForestGameArea extends GameArea { "images/projectiles/stun_effect.png", "images/projectiles/firework_anim.png", "images/projectiles/pierce_anim.png", - - "images/projectiles/snow_ball.png" }; private static final String[] forestTextureAtlases = { @@ -117,8 +115,12 @@ public class ForestGameArea extends GameArea { "images/projectiles/mobProjectile.atlas", "images/projectiles/engineer_projectile.atlas", "images/projectiles/mobKing_projectile.atlas", - "images/projectiles/snow_ball.atlas" - + "images/projectiles/snow_ball.atlas", + "images/projectiles/pierce_anim.atlas", + "images/projectiles/burn_effect.atlas", + "images/projectiles/firework_anim.atlas", + "images/projectiles/mobProjectile.atlas", + "images/projectiles/stun_effect.atlas" }; private static final String[] forestSounds = { "sounds/Impact4.ogg",