From 2a9f37abf2a33d0940b6a0bc315f223320d66772 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Wed, 16 Aug 2023 18:08:52 +1000 Subject: [PATCH 01/33] updated readme for individual branch (sub-branch of team-2) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dbdb2da3b..3d149b8db 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,7 @@ You are welcome to use the game engine for your own purposes. It is released und - [JavaDoc](https://uqcsse3200.github.io/2023-studio-3/) - [SonarCloud](https://sonarcloud.io/project/overview?id=UQcsse3200_2023-studio-3) + +## Tower-Graphics Branch + +This is a sub-branch of Team-2--Towers and will encompass the work on rendering and animating the towers in the Studio 3 project. From db7e7fec04372acbb086e201a6640df14d1f2659 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Fri, 18 Aug 2023 13:26:22 +1000 Subject: [PATCH 02/33] updated readme for team 2 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dbdb2da3b..0252137eb 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,7 @@ You are welcome to use the game engine for your own purposes. It is released und - [JavaDoc](https://uqcsse3200.github.io/2023-studio-3/) - [SonarCloud](https://sonarcloud.io/project/overview?id=UQcsse3200_2023-studio-3) + +## Team 2 - Tower Branch + +Implements defense towers in the Outworld Outposts game. Any questions or discussion, please contact Team 2 From 79f29c3772f556978dd84e01b97dcfac114209ee Mon Sep 17 00:00:00 2001 From: Mohamad Date: Fri, 18 Aug 2023 19:01:56 +1000 Subject: [PATCH 03/33] Added TowerFactory class --- .../game/entities/factories/TowerFactory.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java new file mode 100644 index 000000000..afb0e2cdc --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -0,0 +1,23 @@ +package com.csse3200.game.entities.factories; + + +import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; +import com.csse3200.game.entities.Entity; +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; + + +public class TowerFactory { + + public static Entity createBaseTower() { + // we're going to add more components later on + Entity tower = new Entity() + .addComponent(new ColliderComponent()) + .addComponent(new HitboxComponent().setLayer(PhysicsLayer.OBSTACLE)) // we might have to change the names of the layers + .addComponent(new PhysicsComponent().setBodyType(BodyType.StaticBody)); + + return tower; + } +} \ No newline at end of file From 5c271585c76a7a916408efa64338996f6c62d090 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Fri, 18 Aug 2023 19:35:09 +1000 Subject: [PATCH 04/33] Implemented CostComponent for entities that necessitate a cost --- .../game/components/CostComponent.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 source/core/src/main/com/csse3200/game/components/CostComponent.java diff --git a/source/core/src/main/com/csse3200/game/components/CostComponent.java b/source/core/src/main/com/csse3200/game/components/CostComponent.java new file mode 100644 index 000000000..0e2d165e2 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/CostComponent.java @@ -0,0 +1,40 @@ +package com.csse3200.game.components; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Component used to store information related to cost. + * Any entities that necessitate a cost should register an instance of this class. + */ +public class CostComponent extends Component { + + private static final Logger logger = LoggerFactory.getLogger(CostComponent.class); + private int cost; + + public CostComponent(int cost) { + setCost(cost); + + } + + /** + * Sets the entity's cost. Cost has a minimum bound of 0. + * @param cost + */ + public void setCost(int cost) { + if(cost >= 0) { + this.cost = cost; + } else { + this.cost = 0; + } + } + + /** + * Returns the entity's cost + * @return entity's cost + */ + public int getCost() { + return this.cost; + } + +} \ No newline at end of file From 91c121c008bda5be370f0e5dceffb9799d15dc1e Mon Sep 17 00:00:00 2001 From: Mohamad Date: Fri, 18 Aug 2023 19:55:48 +1000 Subject: [PATCH 05/33] Added empty files baseTowerConfigs and tower.json --- source/core/assets/configs/tower.json | 0 .../csse3200/game/entities/configs/baseTowerConfigs.java | 8 ++++++++ .../csse3200/game/entities/factories/TowerFactory.java | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 source/core/assets/configs/tower.json create mode 100644 source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java diff --git a/source/core/assets/configs/tower.json b/source/core/assets/configs/tower.json new file mode 100644 index 000000000..e69de29bb diff --git a/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java new file mode 100644 index 000000000..2e4dbf84b --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java @@ -0,0 +1,8 @@ +package com.csse3200.game.entities.configs; + +/** + * Defines all tower configs to be loaded by the Tower Factory. + */ +public class baseTowerConfigs { + +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index afb0e2cdc..fb7065586 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -10,6 +10,10 @@ public class TowerFactory { + /** + private static final baseTowerConfigs configs = + FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); + */ public static Entity createBaseTower() { // we're going to add more components later on From ff7cfc19fe81074a474abc5dddee9c3c4d1c9386 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Fri, 18 Aug 2023 20:05:40 +1000 Subject: [PATCH 06/33] Added comments in TowerFactory --- .../game/entities/factories/TowerFactory.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index fb7065586..7f47b34c5 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -8,13 +8,22 @@ import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsComponent; - +/** + * Factory to create a tower entity. + * + * Predefined tower properties are loaded from a config stored as a json file and should have + * the properties stores in 'baseTowerConfigs'. + */ public class TowerFactory { /** private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); */ + /** + * Creates a generic tower entity to be used as a base entity by more specific tower creation methods. + * @return entity + */ public static Entity createBaseTower() { // we're going to add more components later on Entity tower = new Entity() From b68079678e4262c489823e84cf3133549e29029c Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Sat, 19 Aug 2023 15:38:36 +1000 Subject: [PATCH 07/33] added static sprite and spritesheet for graphics development --- .../images/turret-sprites-deployment.png | Bin 0 -> 98972 bytes source/core/assets/images/turret_deployed.png | Bin 0 -> 3438 bytes .../TowerAnimationRenderComponentTest.java | 138 ++++++++++++++++++ .../TowerTextureRenderComponentTest.java | 33 +++++ 4 files changed, 171 insertions(+) create mode 100644 source/core/assets/images/turret-sprites-deployment.png create mode 100644 source/core/assets/images/turret_deployed.png create mode 100644 source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java create mode 100644 source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java diff --git a/source/core/assets/images/turret-sprites-deployment.png b/source/core/assets/images/turret-sprites-deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..ca80d32cc59eaabc7c4587c492bec99981d9dfcc GIT binary patch literal 98972 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 Q?EnA(07*qoM6N<$f>}|P-~a#s literal 0 HcmV?d00001 diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java new file mode 100644 index 000000000..aeb646b1a --- /dev/null +++ b/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java @@ -0,0 +1,138 @@ +package com.csse3200.game.rendering; + +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; +import com.badlogic.gdx.utils.Array; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(GameExtension.class) +class AnimationRenderComponentTest { + @Test + void shouldAddRemoveAnimation() { + TextureAtlas atlas = createMockAtlas("test_name", 1); + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + + assertTrue(animator.addAnimation("test_name", 0.1f)); + assertTrue(animator.removeAnimation("test_name")); + assertFalse(animator.removeAnimation("test_name")); + } + + @Test + void shouldFailRemoveInvalidAnimation() { + TextureAtlas atlas = mock(TextureAtlas.class); + when(atlas.findRegions("test_name")).thenReturn(null); + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + + assertFalse(animator.addAnimation("test_name", 0.1f)); + assertFalse(animator.removeAnimation("test_name")); + } + + @Test + void shouldFailDuplicateAddAnimation() { + TextureAtlas atlas = createMockAtlas("test_name", 1); + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + + assertTrue(animator.addAnimation("test_name", 0.1f)); + assertFalse(animator.addAnimation("test_name", 0.2f)); + } + + @Test + void shouldHaveAnimation() { + TextureAtlas atlas = createMockAtlas("test_name", 1); + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + + animator.addAnimation("test_name", 0.1f); + assertTrue(animator.hasAnimation("test_name")); + animator.removeAnimation("test_name"); + assertFalse(animator.hasAnimation("test_name")); + } + + @Test + void shouldPlayAnimation() { + int numFrames = 5; + String animName = "test_name"; + float frameTime = 1f; + + // Mock texture atlas + TextureAtlas atlas = createMockAtlas(animName, numFrames); + Array regions = atlas.findRegions(animName); + SpriteBatch batch = mock(SpriteBatch.class); + + // Mock game time + GameTime gameTime = mock(GameTime.class); + ServiceLocator.registerTimeSource(gameTime); + when(gameTime.getDeltaTime()).thenReturn(frameTime); + + // Start animation + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + Entity entity = new Entity(); + animator.setEntity(entity); + animator.addAnimation(animName, frameTime); + animator.startAnimation(animName); + + for (int i = 0; i < 5; i++) { + // Each draw advances 1 frame, check that it matches for each + animator.draw(batch); + verify(batch).draw( + regions.get(i), + entity.getPosition().x, + entity.getPosition().y, + entity.getScale().x, + entity.getScale().y + ); + } + } + + @Test + void shouldFinish() { + TextureAtlas atlas = createMockAtlas("test_name", 1); + SpriteBatch batch = mock(SpriteBatch.class); + + GameTime gameTime = mock(GameTime.class); + ServiceLocator.registerTimeSource(gameTime); + when(gameTime.getDeltaTime()).thenReturn(1f); + + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + Entity entity = new Entity(); + animator.setEntity(entity); + animator.addAnimation("test_name", 1f); + assertFalse(animator.isFinished()); + + animator.startAnimation("test_name"); + assertFalse(animator.isFinished()); + + animator.draw(batch); + assertTrue(animator.isFinished()); + } + + @Test + void shouldStopAnimation() { + TextureAtlas atlas = createMockAtlas("test_name", 1); + AnimationRenderComponent animator = new AnimationRenderComponent(atlas); + animator.addAnimation("test_name", 1f); + assertFalse(animator.stopAnimation()); + + animator.startAnimation("test_name"); + assertTrue(animator.stopAnimation()); + assertNull(animator.getCurrentAnimation()); + } + + static TextureAtlas createMockAtlas(String animationName, int numRegions) { + TextureAtlas atlas = mock(TextureAtlas.class); + Array regions = new Array<>(numRegions); + for (int i = 0; i < numRegions; i++) { + regions.add(mock(AtlasRegion.class)); + } + when(atlas.findRegions(animationName)).thenReturn(regions); + return atlas; + } +} \ No newline at end of file diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java new file mode 100644 index 000000000..11b25d0a7 --- /dev/null +++ b/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java @@ -0,0 +1,33 @@ +package com.csse3200.game.rendering; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.extensions.GameExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(GameExtension.class) +@ExtendWith(MockitoExtension.class) +class TextureRenderComponentTest { + @Mock Texture texture; + @Mock SpriteBatch spriteBatch; + @Mock Entity entity; + + @Test + void shouldDrawTexture() { + when(entity.getPosition()).thenReturn(new Vector2(2f, 2f)); + when(entity.getScale()).thenReturn(new Vector2(1f, 1f)); + TextureRenderComponent component = new TextureRenderComponent(texture); + component.setEntity(entity); + component.render(spriteBatch); + + verify(spriteBatch).draw(texture, 2f, 2f, 1f, 1f); + } +} \ No newline at end of file From 55d0f47c48295a98064014d5d1e666fa2faf1368 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Sat, 19 Aug 2023 15:39:54 +1000 Subject: [PATCH 08/33] changed tree texture into turret texture --- .../src/main/com/csse3200/game/areas/ForestGameArea.java | 3 ++- .../csse3200/game/entities/factories/ObstacleFactory.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 305ee1ed8..ea4a47014 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -37,7 +37,8 @@ public class ForestGameArea extends GameArea { "images/hex_grass_3.png", "images/iso_grass_1.png", "images/iso_grass_2.png", - "images/iso_grass_3.png" + "images/iso_grass_3.png", + "images/turret_deployed.png" }; private static final String[] forestTextureAtlases = { "images/terrain_iso_grass.atlas", "images/ghost.atlas", "images/ghostKing.atlas" diff --git a/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java index ac0704e97..e83999830 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java @@ -22,13 +22,13 @@ public class ObstacleFactory { public static Entity createTree() { Entity tree = new Entity() - .addComponent(new TextureRenderComponent("images/tree.png")) + .addComponent(new TextureRenderComponent("images/turret_deployed.png")) .addComponent(new PhysicsComponent()) .addComponent(new ColliderComponent().setLayer(PhysicsLayer.OBSTACLE)); tree.getComponent(PhysicsComponent.class).setBodyType(BodyType.StaticBody); tree.getComponent(TextureRenderComponent.class).scaleEntity(); - tree.scaleHeight(2.5f); + tree.scaleHeight(1.5f); PhysicsUtils.setScaledCollider(tree, 0.5f, 0.2f); return tree; } @@ -50,4 +50,4 @@ public static Entity createWall(float width, float height) { private ObstacleFactory() { throw new IllegalStateException("Instantiating static util class"); } -} +} \ No newline at end of file From 95c142bf6305a244923b00a80cc09b06a0a32855 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Sat, 19 Aug 2023 15:41:37 +1000 Subject: [PATCH 09/33] added skeleton JUnit files for Tower graphics specific rendering testing --- .../game/rendering/TowerAnimationRenderComponentTest.java | 2 +- .../game/rendering/TowerTextureRenderComponentTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java index aeb646b1a..db1afce3a 100644 --- a/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java +++ b/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java @@ -15,7 +15,7 @@ import static org.mockito.Mockito.*; @ExtendWith(GameExtension.class) -class AnimationRenderComponentTest { +class TowerAnimationRenderComponentTest { @Test void shouldAddRemoveAnimation() { TextureAtlas atlas = createMockAtlas("test_name", 1); diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java index 11b25d0a7..ebb0b9b97 100644 --- a/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java +++ b/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java @@ -1,8 +1,5 @@ package com.csse3200.game.rendering; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; @@ -13,9 +10,12 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + @ExtendWith(GameExtension.class) @ExtendWith(MockitoExtension.class) -class TextureRenderComponentTest { +class TowerTextureRenderComponentTest { @Mock Texture texture; @Mock SpriteBatch spriteBatch; @Mock Entity entity; From d18aca658e58b2741ca691a531a72a9d5427eafb Mon Sep 17 00:00:00 2001 From: Mohamad Date: Sun, 20 Aug 2023 14:39:01 +1000 Subject: [PATCH 10/33] Added JUnit tests for TowerFactoryTest and CostComponentTest --- .../game/entities/factories/TowerFactory.java | 3 + .../game/components/CostComponentTest.java | 48 ++++++++++++++++ .../entities/factories/TowerFactoryTest.java | 55 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 source/core/src/test/com/csse3200/game/components/CostComponentTest.java create mode 100644 source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 7f47b34c5..cf09bf9af 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; import com.csse3200.game.entities.Entity; import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.PhysicsUtils; import com.csse3200.game.physics.components.ColliderComponent; import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsComponent; @@ -31,6 +32,8 @@ public static Entity createBaseTower() { .addComponent(new HitboxComponent().setLayer(PhysicsLayer.OBSTACLE)) // we might have to change the names of the layers .addComponent(new PhysicsComponent().setBodyType(BodyType.StaticBody)); + //PhysicsUtils.setScaledCollider(tower, 0.5f, 0.2f); //values might vary according to entity scale value + return tower; } } \ No newline at end of file diff --git a/source/core/src/test/com/csse3200/game/components/CostComponentTest.java b/source/core/src/test/com/csse3200/game/components/CostComponentTest.java new file mode 100644 index 000000000..d882a0e31 --- /dev/null +++ b/source/core/src/test/com/csse3200/game/components/CostComponentTest.java @@ -0,0 +1,48 @@ +package com.csse3200.game.components; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class CostComponentTest { + + private CostComponent costComponent; + + @BeforeEach + public void setUp() { + costComponent = new CostComponent(0); // initializing with default value + } + + @Test + public void testSetAndGetPositiveCost() { + costComponent.setCost(100); + assertEquals(100, costComponent.getCost(), "The cost should be set to 100"); + } + + @Test + public void testSetAndGetZeroCost() { + costComponent.setCost(0); + assertEquals(0, costComponent.getCost(), "The cost should be set to 0"); + } + + @Test + public void testNegativeCostIsNormalizedToZero() { + costComponent.setCost(-100); + assertEquals(0, costComponent.getCost(), "The cost should be normalized to 0 if set as negative"); + } + + @Test + public void testCostComponentConstructorWithNegativeValue() { + CostComponent tempComponent = new CostComponent(50); + tempComponent.setCost(tempComponent.getCost() - 60); + assertEquals(0, tempComponent.getCost(), "The cost should be 0"); + } + + @Test + public void testCostComponentConstructorWithPositiveValue() { + CostComponent tempComponent = new CostComponent(-50); + tempComponent.setCost(tempComponent.getCost() + 60); + assertEquals(60, tempComponent.getCost(), "The cost should be 60"); + } +} diff --git a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java new file mode 100644 index 000000000..9d21e6fda --- /dev/null +++ b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java @@ -0,0 +1,55 @@ +package com.csse3200.game.entities.factories; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.physics.components.ColliderComponent; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.physics.components.PhysicsComponent; +import com.csse3200.game.services.ServiceLocator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class TowerFactoryTest { + + private Entity baseTower; + + @BeforeEach + public void setUp() { + ServiceLocator.registerPhysicsService(new PhysicsService()); + baseTower = TowerFactory.createBaseTower(); + } + + @Test + public void testCreateBaseTowerNotNull() { + assertNotNull(baseTower, "Base tower should not be null"); + } + + @Test + public void testCreateBaseTowerHasColliderComponent() { + assertNotNull(baseTower.getComponent(ColliderComponent.class), + "Base tower should have ColliderComponent"); + } + + @Test + public void testCreateBaseTowerHasHitboxComponent() { + assertNotNull(baseTower.getComponent(HitboxComponent.class), + "Base tower should have HitboxComponent"); + } + + @Test + public void testCreateBaseTowerHasPhysicsComponent() { + assertNotNull(baseTower.getComponent(PhysicsComponent.class), + "Base tower should have PhysicsComponent"); + } + + @Test + public void testCreateBaseTowerPhysicsComponentStaticBody() { + PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); + assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent should be of type StaticBody"); + } +} From c1e4c0e9e362204b7654260a4d1f039d7332142a Mon Sep 17 00:00:00 2001 From: Mohamad Date: Tue, 22 Aug 2023 18:02:07 +1000 Subject: [PATCH 11/33] Added Configurations for WallTower and WeaponTower entities --- source/core/assets/configs/tower.json | 12 ++++++++++++ .../game/entities/configs/WallTowerConfig.java | 10 ++++++++++ .../game/entities/configs/WeaponTowerConfig.java | 10 ++++++++++ .../game/entities/configs/baseTowerConfigs.java | 3 ++- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java create mode 100644 source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java diff --git a/source/core/assets/configs/tower.json b/source/core/assets/configs/tower.json index e69de29bb..a15ab4d27 100644 --- a/source/core/assets/configs/tower.json +++ b/source/core/assets/configs/tower.json @@ -0,0 +1,12 @@ +{ + "weapon": { + "health": 10, + "baseAttack": 10, + "cost": 10 + }, + "wall": { + "health": 20, + "baseAttack": 0, + "cost": 5 + } +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java new file mode 100644 index 000000000..452eaf7e0 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java @@ -0,0 +1,10 @@ +package com.csse3200.game.entities.configs; + +/** + * Defines a basic set of properties stored in entities config files to be loaded by Entity Factories. + */ +public class WallTowerConfig { + public int health = 1; + public int baseAttack = 0; + public int cost = 1; +} diff --git a/source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java new file mode 100644 index 000000000..7d00ccb65 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java @@ -0,0 +1,10 @@ +package com.csse3200.game.entities.configs; + +/** + * Defines a basic set of properties stored in entities config files to be loaded by Entity Factories. + */ +public class WeaponTowerConfig { + public int health = 1; + public int baseAttack = 0; + public int cost = 1; +} diff --git a/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java index 2e4dbf84b..c641a053c 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java @@ -4,5 +4,6 @@ * Defines all tower configs to be loaded by the Tower Factory. */ public class baseTowerConfigs { - + public WeaponTowerConfig weapon = new WeaponTowerConfig(); + public WallTowerConfig wall = new WallTowerConfig(); } \ No newline at end of file From 12064f0c78c2ffec946d2d74fd8f726586b4e5cd Mon Sep 17 00:00:00 2001 From: Mohamad Date: Tue, 22 Aug 2023 18:04:42 +1000 Subject: [PATCH 12/33] Implemented WeaponTower and WallTower in TowerFactory --- .../game/entities/factories/TowerFactory.java | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index cf09bf9af..3effde0c7 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -2,12 +2,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.entities.Entity; +import com.csse3200.game.entities.configs.WallTowerConfig; import com.csse3200.game.physics.PhysicsLayer; -import com.csse3200.game.physics.PhysicsUtils; 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.entities.configs.WeaponTowerConfig; +import com.csse3200.game.entities.configs.baseTowerConfigs; +import com.csse3200.game.files.FileLoader; /** * Factory to create a tower entity. @@ -16,11 +21,39 @@ * the properties stores in 'baseTowerConfigs'. */ public class TowerFactory { - /** - private static final baseTowerConfigs configs = + + private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); - */ + + + public static Entity createWallTower() { + Entity wall = createBaseTower(); + WallTowerConfig config = configs.wall; + + wall + .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new CostComponent(config.cost)); + + return wall; + + } + + /** + * Creates a weaponry tower that shoots at mobs + * @return entity + */ + public static Entity createWeaponTower() { + Entity weapon = createBaseTower(); + WeaponTowerConfig config = configs.weapon; + + weapon + .addComponent(new CombatStatsComponent(config.health,config.baseAttack)) + .addComponent(new CostComponent(config.cost)); + + return weapon; + + } /** * Creates a generic tower entity to be used as a base entity by more specific tower creation methods. * @return entity From 925e86f9d94fae798b9da78ffc6b92e3be098372 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Tue, 22 Aug 2023 18:05:26 +1000 Subject: [PATCH 13/33] Added new JUnit tests in TowerFactoryTest --- .../entities/factories/TowerFactoryTest.java | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java index 9d21e6fda..bc723cbc3 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java @@ -1,55 +1,146 @@ package com.csse3200.game.entities.factories; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +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.TouchAttackComponent; import com.csse3200.game.entities.Entity; +import com.csse3200.game.extensions.GameExtension; import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.physics.components.ColliderComponent; import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsComponent; +import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +@ExtendWith(GameExtension.class) public class TowerFactoryTest { private Entity baseTower; + private Entity weaponTower; + private Entity wallTower; @BeforeEach public void setUp() { + GameTime gameTime = mock(GameTime.class); + when(gameTime.getDeltaTime()).thenReturn(0.02f); + ServiceLocator.registerTimeSource(gameTime); ServiceLocator.registerPhysicsService(new PhysicsService()); baseTower = TowerFactory.createBaseTower(); + weaponTower = TowerFactory.createWeaponTower(); + wallTower = TowerFactory.createWallTower(); } @Test public void testCreateBaseTowerNotNull() { + assertNotNull(baseTower, "Base tower should not be null"); + assertNotNull(weaponTower, "Weaponry tower should not be null"); + assertNotNull(wallTower, "Wall tower should not be null"); } @Test public void testCreateBaseTowerHasColliderComponent() { assertNotNull(baseTower.getComponent(ColliderComponent.class), "Base tower should have ColliderComponent"); + assertNotNull(weaponTower.getComponent(ColliderComponent.class), + "Weaponry tower should have ColliderComponent"); + assertNotNull(wallTower.getComponent(ColliderComponent.class), + "Wall tower should have ColliderComponent"); } @Test public void testCreateBaseTowerHasHitboxComponent() { assertNotNull(baseTower.getComponent(HitboxComponent.class), "Base tower should have HitboxComponent"); + assertNotNull(weaponTower.getComponent(HitboxComponent.class), + "Weaponry tower should have HitboxComponent"); + assertNotNull(wallTower.getComponent(HitboxComponent.class), + "Wall tower should have HitboxComponent"); } @Test public void testCreateBaseTowerHasPhysicsComponent() { assertNotNull(baseTower.getComponent(PhysicsComponent.class), "Base tower should have PhysicsComponent"); + assertNotNull(weaponTower.getComponent(PhysicsComponent.class), + "Weaponry tower should have PhysicsComponent"); + assertNotNull(wallTower.getComponent(PhysicsComponent.class), + "Wall tower should have PhysicsComponent"); } @Test public void testCreateBaseTowerPhysicsComponentStaticBody() { PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); + PhysicsComponent physicsComponent1 = weaponTower.getComponent(PhysicsComponent.class); + PhysicsComponent physicsComponent2 = wallTower.getComponent(PhysicsComponent.class); + assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, "PhysicsComponent should be of type StaticBody"); + assertTrue(physicsComponent1.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent1 should be of type StaticBody"); + assertTrue(physicsComponent2.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent2 should be of type StaticBody"); + } + + @Test + public void testWeaponTowerCombatStatsComponentAndCostComponent() { + + assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getHealth() == 10, + "Health should be 10"); + assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 10, + "BaseAttack should be 10"); + assertTrue(weaponTower.getComponent(CostComponent.class).getCost() == 10, + "Cost should be 10"); + + } + + @Test + public void testWallTowerCombatStatsComponentAndCostComponent() { + + assertTrue(wallTower.getComponent(CombatStatsComponent.class).getHealth() == 20, + "Health should be 20"); + assertTrue(wallTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 0, + "BaseAttack should be 0"); + assertTrue(wallTower.getComponent(CostComponent.class).getCost() == 5, + "Cost should be 5"); + + } + + @Test + public void testAttackerCollisionWithWall() { + Entity attacker = createAttacker(wallTower.getComponent(HitboxComponent.class).getLayer()); + + wallTower.setPosition(10f,10f); + attacker.setPosition(10f,10f); + wallTower.create(); + + assertEquals(20, wallTower.getComponent(CombatStatsComponent.class).getHealth()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + + assertEquals(10, wallTower.getComponent(CombatStatsComponent.class).getHealth()); + + } + + Entity createAttacker(short targetLayer) { + Entity entity = + new Entity() + .addComponent(new TouchAttackComponent(targetLayer)) + .addComponent(new CombatStatsComponent(0, 10)) + .addComponent(new PhysicsComponent()) + .addComponent(new HitboxComponent()); + entity.create(); + return entity; } } + + From 18f435d1b8d2bf7c83ec8f9c7699c112cfaf86d0 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Tue, 22 Aug 2023 21:28:36 +1000 Subject: [PATCH 14/33] added turret (weapon tower) animation assets --- source/core/assets/images/turret.atlas | 13 ++ source/core/assets/images/turret.png | Bin 0 -> 3185 bytes .../core/assets/images/turret_body_idle.atlas | 13 ++ .../core/assets/images/turret_body_idle.png | Bin 0 -> 1094 bytes .../assets/images/turret_firing_long.atlas | 13 ++ .../core/assets/images/turret_firing_long.png | Bin 0 -> 1376 bytes .../TowerAnimationRenderComponent.java | 189 ++++++++++++++++++ .../TowerTextureRenderComponent.java | 37 ++++ 8 files changed, 265 insertions(+) create mode 100644 source/core/assets/images/turret.atlas create mode 100644 source/core/assets/images/turret.png create mode 100644 source/core/assets/images/turret_body_idle.atlas create mode 100644 source/core/assets/images/turret_body_idle.png create mode 100644 source/core/assets/images/turret_firing_long.atlas create mode 100644 source/core/assets/images/turret_firing_long.png create mode 100644 source/core/src/main/com/csse3200/game/rendering/TowerAnimationRenderComponent.java create mode 100644 source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java diff --git a/source/core/assets/images/turret.atlas b/source/core/assets/images/turret.atlas new file mode 100644 index 000000000..c7cfc2a76 --- /dev/null +++ b/source/core/assets/images/turret.atlas @@ -0,0 +1,13 @@ + +turret.png +size: 512, 64 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +turret-sprites-deployment + rotate: false + xy: 2, 2 + size: 432, 47 + orig: 432, 47 + offset: 0, 0 + index: -1 diff --git a/source/core/assets/images/turret.png b/source/core/assets/images/turret.png new file mode 100644 index 0000000000000000000000000000000000000000..b869a3e44354333e712a8c13d52f47ac2f5078f2 GIT binary patch literal 3185 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 Oz~JfX=d#Wzp$Py?JqwNi literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret_firing_long.atlas b/source/core/assets/images/turret_firing_long.atlas new file mode 100644 index 000000000..02293f34d --- /dev/null +++ b/source/core/assets/images/turret_firing_long.atlas @@ -0,0 +1,13 @@ + +turret_firing_long.png +size: 512, 64 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +turret-sprites-head-shot-idle + rotate: false + xy: 2, 2 + size: 270, 47 + orig: 270, 47 + offset: 0, 0 + index: -1 diff --git a/source/core/assets/images/turret_firing_long.png b/source/core/assets/images/turret_firing_long.png new file mode 100644 index 0000000000000000000000000000000000000000..eb07d8cbbf33836428a90225c050e9429871e1e2 GIT binary patch literal 1376 zcmd5+YgEz)6#wIM>2YK$Os%L*k7b#sm9i#<4o#5|7l!!&40{Oz({d$+c7vL)@$VyJL1Bn5M9ByKo$UM0zV3dw=YF{NcYo)19|f^7k!~(t zE&u?y;iAG10D#?c2!wv-wCvN{I@l_~qdH%{ruN=0gse+|D7mCs5n1^*$%UyHVAKB%FQ%USxRyrpYXTluwF9hJ4 zbM53$u9hc$>?MLY->`6{p-A-j+SZD z5z?!WQ@s3+n%9*8A;;HWD?IlmIK|+v9M?6P#TfJcyhSP6+=70 zw%$>;t~jydBx^SjQ{VCd1qA35<4I^5Xk$N~C{Vk0D=NEMqLfu?LLOX*X+H^15Uc{# z*@Ug${2{rX_GyvmabFX-7+gEoxQ3?L$Lz{x{and4*LQTcV@jLc*Una!MR1JK`nkOh z%koI^&!3JDy^D$u+~3Ve|57*N+Gh&6M!r2b`hF^t_ol!MKll*aTQ3Sy%OTaSq$O>Z;3c|12?7y^jkc+6mt&JZdw1K ziUG(Tbs7HsY3zByIJm-CD3;aeok$oI8_F^`ZB#eG zu9L+mAcNwakaSH9UTL%!LF5z#^TzMWWN_AjM8*CyMrqHvdCF;P6*Q<~kKi^lO=a!-XrCUY93%AE|;u22-l!LpbL8ij(aakLzi9VU-YqC;o z`y$2H&wio63emyimXOOt>uz3aYf(^Oj6mQFuDc`3;b&T(ZxJ8PXM`N4WUQz3o*Ml~ z&zkDFaPZA6>3HjWrWFy&)*-b{DSwK=J8;YcUk=O%D`LK#z}hxJdZkVlnLsO2b?7hp z^VrkxpQK@wbrOrj*pAfA<@xt-G7e0Zl7koS@k~0n&N~;g1RbS6nqdAR^u_XJd*}Zu zsc#!c{-6`%FHz&a?)(sm6kl=O9J($Yr*K>bZ1DN;Uq|h`#p8ckW_yeOZm|!R YfZFC?YWjB|__i!uL`=BoyOi^P11Dygh5!Hn literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/rendering/TowerAnimationRenderComponent.java b/source/core/src/main/com/csse3200/game/rendering/TowerAnimationRenderComponent.java new file mode 100644 index 000000000..e903b185a --- /dev/null +++ b/source/core/src/main/com/csse3200/game/rendering/TowerAnimationRenderComponent.java @@ -0,0 +1,189 @@ +package com.csse3200.game.rendering; + +import com.badlogic.gdx.graphics.g2d.Animation; +import com.badlogic.gdx.graphics.g2d.Animation.PlayMode; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * Subclass of the AnimationRenderComponent, specifically for use by the TowerFactory class + * to build animations for in game defensive towers + * + * using the animation found at https://opengameart.org/content/pixel-turret-animation + * Renders animations from a texture atlas on a tower. + * + *

Example usage: + * + *

+ *   TowerAnimationRenderComponent towerAnimator = new TowerAnimationRenderComponent("turret.atlas");
+ *   entity.addComponent(towerAnimator);
+ *   towerAnimator.addAnimation("attack", 0.1f); // Only need to add animation once per entity
+ *   towerAnimator.startAnimation("attack");
+ * 
+ * + * Texture atlases can be created using:
+ * - libgdx texture packer (included in External Libraries/gdx-tools)
+ * - gdx-texture-packer-gui (recommended) https://github.com/crashinvaders/gdx-texture-packer-gui
+ * - other third-party tools, e.g. https://www.codeandweb.com/texturepacker
+ */ +public class TowerAnimationRenderComponent extends RenderComponent { + private static final Logger logger = LoggerFactory.getLogger(TowerAnimationRenderComponent.class); + private final GameTime timeSource; + private final TextureAtlas atlas; + private final Map> animations; + private Animation currentAnimation; + private String currentAnimationName; + private float animationPlayTime; + // TODO: remove reimplentations of existing functionality and only declare overridden methods + /** + * Create the component for a given texture atlas. + * @param atlas libGDX-supported texture atlas containing desired animations + */ + public TowerAnimationRenderComponent(TextureAtlas atlas) { + this.atlas = atlas; + this.animations = new HashMap<>(4); + timeSource = ServiceLocator.getTimeSource(); + } + + /** + * Register an animation from the texture atlas. Will play once when called with startAnimation() + * @param name Name of the animation. Must match the name of this animation inside the texture + * atlas. + * @param frameDuration How long, in seconds, to show each frame of the animation for when playing + * @return true if added successfully, false otherwise + */ + public boolean addAnimation(String name, float frameDuration) { + return addAnimation(name, frameDuration, PlayMode.NORMAL); + } + + /** + * Register an animation from the texture atlas. + * @param name Name of the animation. Must match the name of this animation inside the texture + * atlas. + * @param frameDuration How long, in seconds, to show each frame of the animation for when playing + * @param playMode How the animation should be played (e.g. looping, backwards) + * @return true if added successfully, false otherwise + */ + public boolean addAnimation(String name, float frameDuration, PlayMode playMode) { + Array regions = atlas.findRegions(name); + if (regions == null || regions.size == 0) { + logger.warn("Animation {} not found in texture atlas", name); + return false; + } else if (animations.containsKey(name)) { + logger.warn( + "Animation {} already added in texture atlas. Animations should only be added once.", + name); + return false; + } + + Animation animation = new Animation<>(frameDuration, regions, playMode); + animations.put(name, animation); + logger.debug("Adding animation {}", name); + return true; + } + + /** Scale the entity to a width of 1 and a height matching the texture's ratio */ + public void scaleEntity() { + TextureRegion defaultTexture = this.atlas.findRegion("default"); + entity.setScale(1f, (float) defaultTexture.getRegionHeight() / defaultTexture.getRegionWidth()); + } + + /** + * Remove an animation from this animator. This is not required before disposing. + * @param name Name of the previously added animation. + * @return true if removed, false if animation was not found. + */ + public boolean removeAnimation(String name) { + logger.debug("Removing animation {}", name); + return animations.remove(name) != null; + } + + /** + * Whether the animator has added the given animation. + * @param name Name of the added animation. + * @return true if added, false otherwise. + */ + public boolean hasAnimation(String name) { + return animations.containsKey(name); + } + + /** + * Start playback of an animation. The animation must have been added using addAnimation(). + * @param name Name of the animation to play. + */ + public void startAnimation(String name) { + Animation animation = animations.getOrDefault(name, null); + if (animation == null) { + logger.error( + "Attempted to play unknown animation {}. Ensure animation is added before playback.", + name); + return; + } + + currentAnimation = animation; + currentAnimationName = name; + animationPlayTime = 0f; + logger.debug("Starting animation {}", name); + } + + /** + * Stop the currently running animation. Does nothing if no animation is playing. + * @return true if animation was stopped, false if no animation is playing. + */ + public boolean stopAnimation() { + if (currentAnimation == null) { + return false; + } + + logger.debug("Stopping animation {}", currentAnimationName); + currentAnimation = null; + currentAnimationName = null; + animationPlayTime = 0f; + return true; + } + + /** + * Get the name of the animation currently being played. + * @return current animation name, or null if not playing. + */ + public String getCurrentAnimation() { + return currentAnimationName; + } + + /** + * Has the playing animation finished? This will always be false for looping animations. + * @return true if animation was playing and has now finished, false otherwise. + */ + public boolean isFinished() { + return currentAnimation != null && currentAnimation.isAnimationFinished(animationPlayTime); + } + + @Override + protected void draw(SpriteBatch batch) { + if (currentAnimation == null) { + return; + } + TextureRegion region = currentAnimation.getKeyFrame(animationPlayTime); + Vector2 pos = entity.getPosition(); + Vector2 scale = entity.getScale(); + batch.draw(region, pos.x, pos.y, scale.x, scale.y); + animationPlayTime += timeSource.getDeltaTime(); + } + + @Override + public void dispose() { + atlas.dispose(); + super.dispose(); + } +} diff --git a/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java b/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java new file mode 100644 index 000000000..e267feae4 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java @@ -0,0 +1,37 @@ +package com.csse3200.game.rendering; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.services.ServiceLocator; + +/** Render a static tower texture. */ +// TODO: remove reimplentations of existing functionality and only declare overridden methods +public class TowerTextureRenderComponent extends RenderComponent { + private final Texture texture; + + /** + * @param type The type of tower to be instantiated. + */ + public TowerTextureRenderComponent(String type) { + this(ServiceLocator.getResourceService().getAsset("images/turret_deployed.png", Texture.class)); + + } +//... + /** @param texture Static tower texture to render. Will be scaled to the entity's scale. */ + public TowerTextureRenderComponent(Texture texture) { + this.texture = texture; + } + + /** Scale the entity to a width of 1 and a height matching the texture's ratio */ + public void scaleEntity() { + entity.setScale(1f, (float) texture.getHeight() / texture.getWidth()); + } + + @Override + protected void draw(SpriteBatch batch) { + Vector2 position = entity.getPosition(); + Vector2 scale = entity.getScale(); + batch.draw(texture, position.x, position.y, scale.x, scale.y); + } +} From 97e4d1252c206828b027d18f1bf566281f58076b Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Tue, 22 Aug 2023 22:32:18 +1000 Subject: [PATCH 15/33] modified animation atlas files to animate --- source/core/assets/images/turret.atlas | 122 +++++++++++++++++- source/core/assets/images/turret.png | Bin 3185 -> 2482 bytes .../core/assets/images/turret_body_idle.atlas | 52 +++++++- .../core/assets/images/turret_body_idle.png | Bin 1094 -> 758 bytes .../assets/images/turret_firing_long.atlas | 6 +- .../core/assets/images/turret_firing_long.png | Bin 1376 -> 868 bytes 6 files changed, 167 insertions(+), 13 deletions(-) diff --git a/source/core/assets/images/turret.atlas b/source/core/assets/images/turret.atlas index c7cfc2a76..2ae57b6e8 100644 --- a/source/core/assets/images/turret.atlas +++ b/source/core/assets/images/turret.atlas @@ -1,13 +1,125 @@ turret.png -size: 512, 64 +size: 256, 64 format: RGBA8888 filter: Nearest, Nearest repeat: none -turret-sprites-deployment +idle + rotate: false + xy: 2, 24 + size: 35, 33 + orig: 40, 37 + offset: 3, 2 + index: -1 +idle + rotate: false + xy: 39, 24 + size: 35, 33 + orig: 40, 37 + offset: 3, 1 + index: -1 +idle + rotate: false + xy: 76, 24 + size: 29, 33 + orig: 40, 37 + offset: 6, 1 + index: -1 +idle + rotate: false + xy: 107, 30 + size: 24, 27 + orig: 40, 37 + offset: 9, 2 + index: -1 +idle + rotate: false + xy: 133, 37 + size: 24, 20 + orig: 40, 37 + offset: 9, 2 + index: -1 +idle + rotate: false + xy: 2, 2 + size: 24, 20 + orig: 40, 37 + offset: 9, 2 + index: -1 +idle + rotate: false + xy: 28, 4 + size: 24, 18 + orig: 40, 37 + offset: 10, 1 + index: -1 +idle + rotate: false + xy: 159, 40 + size: 24, 17 + orig: 40, 37 + offset: 9, 1 + index: -1 +default + rotate: false + xy: 159, 40 + size: 24, 17 + orig: 40, 37 + offset: 9, 1 + index: -1 +angry + rotate: false + xy: 159, 40 + size: 24, 17 + orig: 40, 37 + offset: 9, 1 + index: -1 +angry + rotate: false + xy: 28, 4 + size: 24, 18 + orig: 40, 37 + offset: 10, 1 + index: -1 +angry rotate: false xy: 2, 2 - size: 432, 47 - orig: 432, 47 - offset: 0, 0 + size: 24, 20 + orig: 40, 37 + offset: 9, 2 + index: -1 +angry + rotate: false + xy: 133, 37 + size: 24, 20 + orig: 40, 37 + offset: 9, 2 + index: -1 +angry + rotate: false + xy: 107, 30 + size: 24, 27 + orig: 40, 37 + offset: 9, 2 + index: -1 +angry + rotate: false + xy: 76, 24 + size: 29, 33 + orig: 40, 37 + offset: 6, 1 + index: -1 +angry + rotate: false + xy: 39, 24 + size: 35, 33 + orig: 40, 37 + offset: 3, 1 index: -1 +angry + rotate: false + xy: 2, 24 + size: 35, 33 + orig: 40, 37 + offset: 3, 2 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/turret.png b/source/core/assets/images/turret.png index b869a3e44354333e712a8c13d52f47ac2f5078f2..f85fa0d034a3192d8977d4833d398512219679b1 100644 GIT binary patch literal 2482 zcmV;j2~GBiP)lcWP2oQ$0JqJJaqY|DW{N%=C6wm3O*(dZuUFSq1}w|gKr|TL&j!iW(psIO5>+} zd2EUE=uUvsNx1(9U^w?)e~#k_SNgVTAAnsNObJ$0Lad8XioVtmC=Qir=k1O0RU~` z>i~S60H=jC$|Hx}n}aY0Mg!V z!EV3bck*>Iz7Bwlj2USF0Gc2hrf%SrRyPvRdGFlb$hNjt3fqzZy9Zx=Q#n)vDU`jrmC8fgFkrbN7>UukGolBq+KA|5YFD?C!Kb4qLi35P?85}sElZwi1Nw40+jo`w?jiRj7 zBqO10MIE%7LU@VsF-?M&L>&j zKB+waB%~5kDsceN4f-m_FX8aQoN}K&*YEMu{_?W>?S7>(OnQ%-P)sHJ+IL7C+~~Oj zc=Ot|=UxEV4}ABzT&a15U#{%*+3uH1))mo9=sJFh#k9+dsL(!Xk~l72-p;7eUwiku z+vdtHUAgkylb=R^698>dRBkCsms&V@xLm4RD)GdMY5mNm>i~`(b88?}VvuoA2S8gL z2Q_vj*8z}fDD3jHga+~wIPw9nDsp9CsimWCSYD#nEB+rqr|efuN0(Qr@jKB-pe~L_ zTeBH;0DrzWS}lp=poW)^08A0SQIDQ!U}44qbb?&jR}58)``3%xqao|Ug1sbI7wl(D z-1xW7Z}W2r!i?kR_ctf)dgz%N(kvY+0u*D(+sKxqV!gBb^~|L_ActD^JOgd1F})p}BisYx7Q#j+VXkPT5>uo&DzgpN%!kmlv}p^x=;%t$S057n>u&MyzoU^#Oflj(bjVF5 z>PFs$ufjH_8(%Tz=Ip1{T*2iqm$q83oj%P)O5~MyB2tMdW*k0WOg_UgwJ*buE3c;+ z$4xi-{?8<)8(%<9o?4@guQHXMChL1$%D^iDv-XCmqWEN_5>w1LV)@d3^h| zyx>-&JxULl^f1sj9F$@kR4Hg**`I_|Vu~3@EMHytapFelo7K=he7-1+^5a$`4wcG4 z`|{Wl=h2lSPoI`lVu~3@EMJ}a;rAaBxYYnnkngwi7jK;mEt!Wa1Sz*S6{*A&Gmcok zV)@yla;p$3UB2P1255?W&wgA5Xd<$s>;{ucOfxexyxVFV!fruVzVzQ5`Md4>Rs*z0 z(ZgHPCynxxJn3ywiKDBS^v`z{72j>gF&Gs0%oY1>`^u@5zy5Hd{m_^W9y;QF?wbi8{OiBqIL3T8 z`kjCBI~+_rjD(ga1B%Y;8=s=sQGSkN;b$ZX_CL$*D%SB?>xlt z6ZuvHv;=?Ah3YB=r|FZ_gl(e{N(owvN&ApmUOiD70kC~8%jr^+#=&JdANi#bi2Ph@ z3SV`^@Kds*rfEN%FC-4OrR~!#K&ZZ$v)@QIQqn4~KO?dwWWsyvrZmhAfAhR1fru@hYt+lYI`Cz(AAX)Z-r4=;>yd8VI9stz$G#3g+5~|ZZ)I7ylb|bvuToeN4{U1b z_XpXDQ|qNhNK0n@TQTvDc&`qGP% zq~zzujdQNN?gVrhPE&S42>Qvh)bh&cS8aR}^of#{Lgv%r3c>a)iFNhdRaaIrxjlX6 z4QHdRn8=>xhor9lM3IMolG|1sY)^Lp1pk<)EnmJxNmBB2`{t(UL*}8+Nj^WI8AXNH zqR;q63qAp~&&T?t=@TQ5*^c%heH9Un$+u52jcz~oI;#BLfY#$6yJSBf9y6E#kHB0oQWkdwNI!`UZ4>II}u zd>JI?=hn?Fwo}o^pN{nd8c?b1g5t|wTRUDlZYrak#`15aF?F^Z$tb6(^Uu`TYb2wb zkGe9AWR$b0%il;wIg7gdjkLJ9sLO##;9;#X?2Llt-%5+ge)|U?3OuZ(x800kXXj}D wH0Mo9DW=%|0RR9100000000000D!6a9|JvvBNp5{Pyhe`07*qoM6N<$f=43PBLDyZ literal 3185 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 Xtgipbw%jYjvTpkG=1ns;R z0IU-P)gQ)eurrh zPpXN>=70BhD?Ct{z^#AG#i_M!6(oAvOZ?;^$}MD0Pf_45k?-Aw^!vV130m`1GNb(^ zK01aX6A)-NUq4;LQ^UiifzxqZ7&flwQsToP(UWG<)4~PU@b_{I4(izE!J}{tZR0w8 z4|YHNf$&~6jHe-MO5l03D&e@910 dM@L7){0HMp4FrgpjX?ka002ovPDHLkV1i&=Z=V1F literal 1094 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|`|(ba4!+hRb-=+lZVbNU7@7Yv&0!VRgQ>leC>z$Du}5ea?8mp;DVSp3HC zPN&KIFDEy?HvT_z;_WTI%O6|xU7mS1?VZ$0KDHg(LfM&PZm())T$g+GAj9=-uM!%v zqe~4AY+Y+5@!(dNEKfo1YOKl}f`bp3zE0rUkv0{m+c)-D*?RH59p`qP&e*MAYOr7( zQ;Fg8hZh5X9Llgs+aBAv)!?z3h{46_RuUIN;yyh+n(DXf+lxP*Kaymm)@|21>=OSf z!68`rvttWm?ayDiiDhq_?gy_(yx1{y-<5+6%Y;7u4UoF_-oC#0@T;=j4<+(MUPVsa za0O^ufo$iLL|GrT?mq>S15QtB0jq!Qm6My>`uN_zx{e3?s{XdkXW!7~%E?{3vYByZ zSYz{|hc5T)f5|L)UBk=1`PLRLu!N@2-#U4%)FX-?<)@aoyq`DssH$aIx%%t#^SHv+gDUgK2MkXqjUo|@OZ7Cny zk`vP(Pk3Q!KfUMsgALEFZ$9MoZdK}xw_vM{BzT-SjrblO{ao!R!#DlDFuUuy*Q^Gc zd6lRA4g#93VrFJ0raFyR&2`n`*GXy8>zqLWx@wP0%_miFwxBXwZH*^eRTp3AZUu#B zi1Os-L=EN6!(4^=--*Q&)f3{@ZvsZ5Lg=E~XY1B{Wj}oG z=jC+cDW^WapCu6fi6LNaoc?bGR$$N-#;fu-l!2_0t(4r774cDuPfJ9o=+?BvbzuET z#m4`+h544`MAUfH1RQ=?7Upvz+xt)vNXOj`A2t5Gx4CXH(`e0|0Qvb(UQKJP&Pn15 z19_+-p!^@>2_Y{3x~m&hZr(pL^~m1`aj#Fj);X90)XTuu`#rDqwu*ZDP4(oDoyQ$N zCVu>V!D2;(f6=~vhId>0CYFMNO`u84-^we#`~T}c-^;Hn`kcFuRsX15(=7QRc3Q5- zjr>(TPRFdi07IU`v1T#rU>9{VaheH`~XB6Pd&lA1fKmsm+0 zXl}D!eD2)49mNF|GJPfY)KY)$xNa48HMe^cL;?0ZCVRY41`{oBs@FUktMqF2T2Wy6 Oz~JfX=d#Wzp$Py?JqwNi diff --git a/source/core/assets/images/turret_firing_long.atlas b/source/core/assets/images/turret_firing_long.atlas index 02293f34d..180ee6a12 100644 --- a/source/core/assets/images/turret_firing_long.atlas +++ b/source/core/assets/images/turret_firing_long.atlas @@ -1,13 +1,13 @@ turret_firing_long.png -size: 512, 64 +size: 256, 16 format: RGBA8888 filter: Nearest, Nearest repeat: none turret-sprites-head-shot-idle rotate: false xy: 2, 2 - size: 270, 47 + size: 240, 8 orig: 270, 47 - offset: 0, 0 + offset: 15, 32 index: -1 diff --git a/source/core/assets/images/turret_firing_long.png b/source/core/assets/images/turret_firing_long.png index eb07d8cbbf33836428a90225c050e9429871e1e2..cfdb1c72c3948dd4cbaa2cbea96001cc2fbe07ac 100644 GIT binary patch literal 868 zcmV-q1DpJbP)}N>2Bt`yEECP6~f^#@cTzY z)8TORDBk$6nB7|zmoL@C-8;v{qxrK^6SVR3FaZ4KLrsT*@B4HW0&k#+fX~Q63q767 zLTDx&0NDJGpWGHtU%l?|<>I1P{x3p z1_AR>u#j3V0I$PX6b1+Bs-Q5F%0(o_05dzv!M3WEY8CgZ9ULx!KFPJJOz8P@`$YZp z8EAN)`etcKG=8o4$`A-01hmFD8gc=v%GT|CUA$1oAz;@~TM_~8T#HB*6bHOr-Y94g}s27x~WdLa3 z{%H>YsEPZ083q9B9Y7oQT#29)>fqs{(rw#kwAb)H22qRiys?gbpz8ApJwRL{{g8|1 zh>~e~$`h5^0YMudoPY6LJ_2-We2xLYdA^Pu+MmfI0Kl0m(epoGdq%;6V5t@g@A)Uj zOw-KD+Myx2qz8ygpigqe&eUplqtD*IlLO%U&re#jr`7OOfctzsxHs2%yU*D8D8QWy z!0Rwgg2Gf`z3T9~^_^RVKo1VL7PL$`$ff0plBs7DcHvDkisV73HaESsW~}z(S!wH|YuTn2ReDZT>6I2;a#!{Kl^91e%W5rscvW7xI5N1(d^00002YK$Os%L*k7b#sm9i#<4o#5|7l!!&40{Oz({d$+c7vL)@$VyJL1Bn5M9ByKo$UM0zV3dw=YF{NcYo)19|f^7k!~(t zE&u?y;iAG10D#?c2!wv-wCvN{I@l_~qdH%{ruN=0gse+|D7mCs5n1^*$%UyHVAKB%FQ%USxRyrpYXTluwF9hJ4 zbM53$u9hc$>?MLY->`6{p-A-j+SZD z5z?!WQ@s3+n%9*8A;;HWD?IlmIK|+v9M?6P#TfJcyhSP6+=70 zw%$>;t~jydBx^SjQ{VCd1qA35<4I^5Xk$N~C{Vk0D=NEMqLfu?LLOX*X+H^15Uc{# z*@Ug${2{rX_GyvmabFX-7+gEoxQ3?L$Lz{x{and4*LQTcV@jLc*Una!MR1JK`nkOh z%koI^&!3JDy^D$u+~3Ve|57*N+Gh&6M!r2b`hF^t_ol!MKll*aTQ3Sy%OTaSq$O>Z;3c|12?7y^jkc+6mt&JZdw1K ziUG(Tbs7HsY3zByIJm-CD3;aeok$oI8_F^`ZB#eG zu9L+mAcNwakaSH9UTL%!LF5z#^TzMWWN_AjM8*CyMrqHvdCF;P6*Q<~kKi^lO=a!-XrCUY93%AE|;u22-l!LpbL8ij(aakLzi9VU-YqC;o z`y$2H&wio63emyimXOOt>uz3aYf(^Oj6mQFuDc`3;b&T(ZxJ8PXM`N4WUQz3o*Ml~ z&zkDFaPZA6>3HjWrWFy&)*-b{DSwK=J8;YcUk=O%D`LK#z}hxJdZkVlnLsO2b?7hp z^VrkxpQK@wbrOrj*pAfA<@xt-G7e0Zl7koS@k~0n&N~;g1RbS6nqdAR^u_XJd*}Zu zsc#!c{-6`%FHz&a?)(sm6kl=O9J($Yr*K>bZ1DN;Uq|h`#p8ckW_yeOZm|!R YfZFC?YWjB|__i!uL`=BoyOi^P11Dygh5!Hn From ea0a7a4e61e6d7df1817c9247d38864afea5119d Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Tue, 22 Aug 2023 22:32:49 +1000 Subject: [PATCH 16/33] configured ghosts to appear as towers and animate --- .../main/com/csse3200/game/areas/ForestGameArea.java | 7 ++++++- .../components/npc/GhostAnimationController.java | 4 ++-- .../csse3200/game/entities/factories/NPCFactory.java | 12 ++++++------ .../game/entities/factories/ObstacleFactory.java | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index ea4a47014..2eb35f6a2 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -41,7 +41,12 @@ public class ForestGameArea extends GameArea { "images/turret_deployed.png" }; private static final String[] forestTextureAtlases = { - "images/terrain_iso_grass.atlas", "images/ghost.atlas", "images/ghostKing.atlas" + "images/terrain_iso_grass.atlas", + "images/ghost.atlas", + "images/ghostKing.atlas", + "images/turret.atlas", + "images/turret_body_idle.atlas", + "images/turret_firing_long.atlas" }; private static final String[] forestSounds = {"sounds/Impact4.ogg"}; private static final String backgroundMusic = "sounds/BGM_03_mp3.mp3"; diff --git a/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java index 78c7ce6e4..7a689a893 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java @@ -19,10 +19,10 @@ public void create() { } void animateWander() { - animator.startAnimation("float"); + animator.startAnimation("idle"); } void animateChase() { - animator.startAnimation("angry_float"); + animator.startAnimation("angry"); } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index efd59ca29..e0283f860 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -49,9 +49,9 @@ public static Entity createGhost(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( - ServiceLocator.getResourceService().getAsset("images/ghost.atlas", TextureAtlas.class)); - animator.addAnimation("angry_float", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("float", 0.1f, Animation.PlayMode.LOOP); + ServiceLocator.getResourceService().getAsset("images/turret_body_idle.atlas", TextureAtlas.class)); + animator.addAnimation("angry", 0.1f, Animation.PlayMode.LOOP); + animator.addAnimation("idle", 0.1f, Animation.PlayMode.LOOP); ghost .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) @@ -76,9 +76,9 @@ public static Entity createGhostKing(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() - .getAsset("images/ghostKing.atlas", TextureAtlas.class)); - animator.addAnimation("float", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("angry_float", 0.1f, Animation.PlayMode.LOOP); + .getAsset("images/turret.atlas", TextureAtlas.class)); + animator.addAnimation("idle", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("angry", 0.2f, Animation.PlayMode.NORMAL); ghostKing .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java index e83999830..936fbea6f 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/ObstacleFactory.java @@ -22,7 +22,7 @@ public class ObstacleFactory { public static Entity createTree() { Entity tree = new Entity() - .addComponent(new TextureRenderComponent("images/turret_deployed.png")) + .addComponent(new TextureRenderComponent("images/tree.png")) .addComponent(new PhysicsComponent()) .addComponent(new ColliderComponent().setLayer(PhysicsLayer.OBSTACLE)); From a47867457dffa154aa5b034e5ab780dd67cabf1a Mon Sep 17 00:00:00 2001 From: MajorDzaster Date: Wed, 23 Aug 2023 15:55:41 +1000 Subject: [PATCH 17/33] Test has bug --- .../popupmenu/PopupMenuInputComponent.java | 33 +++++++++++++++ .../PopupMenuInputComponentTest.java | 41 +++++++++++++++++++ source/gradlew | 0 3 files changed, 74 insertions(+) create mode 100644 source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java create mode 100644 source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java mode change 100644 => 100755 source/gradlew diff --git a/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java new file mode 100644 index 000000000..25b931bdf --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java @@ -0,0 +1,33 @@ +package com.csse3200.game.components.popupmenu; + +import com.badlogic.gdx.InputProcessor; +import com.csse3200.game.input.InputComponent; + +/** + * Input handler for the player for keyboard and touch (mouse) input. + * This input handler only uses keyboard input. + */ +public class PopupMenuInputComponent extends InputComponent{ + /** TO DO: + * This component's end goal is to send a deactivation trigger when the + * user clicks on anything other than the menu entity, and reactivate it + * if the user clicks on a tower, with the new tower's stats as per its + * config file. + * Current implementation step: trigger a generic event whenever + * the mouse is clicked, with no checks for the entity clicked on. + */ + public PopupMenuInputComponent() {super(1);} + // Note: will need to change constructor's priority when merging with other + // branches that add other input components. + /** + * + * @return whether the input was processed + * @see InputProcessor#keyDown(int) + */ + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + System.out.println(9); + entity.getEvents().trigger("popupEvent"); + return true; + } +} diff --git a/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java b/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java new file mode 100644 index 000000000..0f9bc21c3 --- /dev/null +++ b/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java @@ -0,0 +1,41 @@ +package com.csse3200.game.components.popupmenu; + +import com.csse3200.game.input.InputService; +import com.csse3200.game.services.ServiceLocator; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.events.EventHandler; +import com.csse3200.game.events.listeners.EventListener0; +import com.csse3200.game.extensions.GameExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(GameExtension.class) +class PopupMenuInputComponentTest { + + @Test + void handlesTouchDownNoEntity(){ + EventHandler handler = new EventHandler(); + EventListener0 listener = mock(EventListener0.class); + handler.addListener("popupEvent", listener); + PopupMenuInputComponent popupMenuInputComponent = spy(PopupMenuInputComponent.class); + assertFalse(popupMenuInputComponent.touchDown(5f, 6f, 7, 8)); + verify(listener, times(0)).handle(); + } + + @Test + void handlesTouchDownEntityIncluded(){ +// EventListener0 listener = mock(EventListener0.class); +// Entity entity = new Entity(); +// InputService inputService = new InputService(); +// ServiceLocator.registerInputService(inputService); + PopupMenuInputComponent popupMenuInputComponent = new PopupMenuInputComponent();//spy(PopupMenuInputComponent.class); +// entity.addComponent(popupMenuInputComponent); +// inputService.register(popupMenuInputComponent); +// entity.getEvents().addListener("popupEvent", listener); +// entity.create(); + assertTrue(popupMenuInputComponent.touchDown(5f, 6f, 7, 8)); +// verify(listener).handle(); + } +} diff --git a/source/gradlew b/source/gradlew old mode 100644 new mode 100755 From a165843a0e8d7cdc12ac997c81ad78bf88b2cd96 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Wed, 23 Aug 2023 18:31:41 +1000 Subject: [PATCH 18/33] Added Tower animation controller class --- .../tower/TowerAnimationController.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java new file mode 100644 index 000000000..2db8dadfc --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java @@ -0,0 +1,28 @@ +package com.csse3200.game.components.tower; + +import com.csse3200.game.components.Component; +import com.csse3200.game.rendering.AnimationRenderComponent; + +/** + * 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 TowerAnimationController extends Component { + AnimationRenderComponent animator; + + @Override + public void create() { + super.create(); + animator = this.entity.getComponent(AnimationRenderComponent.class); + entity.getEvents().addListener("wanderStart", this::animateWander); + entity.getEvents().addListener("chaseStart", this::animateChase); + } + + void animateWander() { + animator.startAnimation("idle"); + } + + void animateChase() { + animator.startAnimation("angry"); + } +} \ No newline at end of file From 96e2f0e3e83f82065f9cbf4bdba39b8c16348f19 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 10:10:16 +1000 Subject: [PATCH 19/33] modified atlas file to include all animations --- .../images/turret-sprites-deployment.png | Bin 98972 -> 0 bytes source/core/assets/images/turret.atlas | 160 +++++++++++++++ .../assets/images/turret_firing_long.atlas | 13 -- .../core/assets/images/turret_firing_long.png | Bin 868 -> 0 bytes .../TowerAnimationRenderComponent.java | 189 ------------------ .../TowerTextureRenderComponent.java | 37 ---- .../TowerAnimationRenderComponentTest.java | 138 ------------- .../TowerTextureRenderComponentTest.java | 33 --- 8 files changed, 160 insertions(+), 410 deletions(-) delete mode 100644 source/core/assets/images/turret-sprites-deployment.png create mode 100644 source/core/assets/images/turret.atlas delete mode 100644 source/core/assets/images/turret_firing_long.atlas delete mode 100644 source/core/assets/images/turret_firing_long.png delete mode 100644 source/core/src/main/com/csse3200/game/rendering/TowerAnimationRenderComponent.java delete mode 100644 source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java delete mode 100644 source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java delete mode 100644 source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java diff --git a/source/core/assets/images/turret-sprites-deployment.png b/source/core/assets/images/turret-sprites-deployment.png deleted file mode 100644 index ca80d32cc59eaabc7c4587c492bec99981d9dfcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98972 zcmeHQ2UrtX*Pe(gioI9-06P*ws3uaRsGuSWxL{iiAwX6j2vJa17wm0SL`6YZ%PLlE zD=t>7hy{B^#qO$~`mgBXu0sB~LvEN1$q*%h3E!RPftlOS`<^rB+&e7`h7BFq*r&>`mMn>1+x=EU z^!>vASfCZwDrE2}9(J3JS$PG7cw)N`U^)5C8t%pFH^Quj&!5u^t2+%Ff3{1PIBfPB ztkr<`0giw5&TRI=9A|3HUdQaNy#5KJ>$4{s1_W4k?wRk^ws$LgK^;L#Kg$zS*0i@y zuxr2Z<3jxZ@(m~$vF0_WA$WaK|xPSpIzD>)eplSNoQOswczaQ z5Z||6d_?JnZg1;`{m^jTq~b*(dz<##kF9%oH=rmAaMOSNvg|u|o;`hfd(bJj(SmaU z(@R57jLQiq3IAt?A)`s8p^&H zUo$)96_g!l-s;Kl7893vq%1D7-ek7GZF#TL-LA@l9~WADHgGPq!*>7Z%$kt!4kBc$v{UOQm>pklm#D~p#bSYN$&ZT7Fx^7r}h}ZIo81{olS4;nM`&@Ey zwzEOP2~I{w|g;|;%zx1a6S_0$QsW^P8o@tvZ__u4Vjt>@f}yN%7q zbFTL@w#^wHHa97%iRFnAe>8E5YWlCBe){pAhZ7pqbv;|ZrNH#=d{)rHz%EPbw_P*m zlj(8Kx-AxUHOZUbYPi|pL_1He??Qi*5uV2HoucdT=8YL}FtP7h%zEaRxrYaGS0wBm z?sUD;e)sGx4jpC>*wFBDu#}s!w9UHI%hA7ga9V7?{>A0(VNLHYb#~9S%K5XMq0Omq zE6Xz{-S+gcXpkg4zsGDxqwQxp?EZd-!J!2og_rik)@_l{Kc|6x-B>phL1$Obz#)M{ zZ+mVr>D1M>`P~K%4Gd-vKheW1Y0Kc>yB}=+Wn*4%l4o)%qhwpiMd(`?#&_frmC zTP$$5?vcH$j@O>w{I9mSI^b%gZJ^9q; zX~(Cg??)S@1@)Ww+b6%rJ$=vpIH>)zX3uP&)f26@b{(-X#rOV}_5RK6mX31UxjxHx z*YJ5;TG~!Z;a!~7#%u7Vof}qO>k!s9tXRD3PwBzt_g8ivntVCn>iL%g|4jbV;6rSq z#&cWG%AFtDvwdni!*-$VW83XoJ!EtHYm3_F`dc}0U$1_#rs*2Vh(Pl!^PgHLo-%Xn=!IvLA{YDhn)0r|84lXJ>#AnK4a2Q*nVG}h3SOG+viS7ushX#&&4}G zO*TKYy2SX)h(){nzUijVd zyPsi{(Z<_}|1r~Y+k{OW*B|nTJr{6Y$x2#{JzDT{5 zT6kdmsJKxUSzEIH5P9u=I%@OCw^@fH=ZxZw+!Q!s)YyFkcBbv@cJt8ALmAC8vWF%O z-JX6k^yKcpvhuRF9%#S&+3k7-nOPB8(*>bHZ9@;7&OG@x=}6M_gVTR0aWZT??@p8L z#-og9#QYxJivKA_*`?byPqJE`?{!L?=9hYHU})RW?3h_a z^A{}`JoCI|va@As$20fO9(g)Q`f=jeM^mqUOiSIDdg9HNf?aRz--_SPyZ7q_+h2R7 zkF<%oeDbXO!{N`axHSBArPYMO9W#8~eG)?Vzv#jdauNe}-r9X&Q|z{4!MnE3e>+G2 z`o#H(qr(I12P4N_aL74u_P}|clalmta|+#m?jj48O_g22GUB_jLJbxqxF(FQ^ZC=% zpG=P}ap4z;{@#1%jqBod*{-c!m(JWd^V#v8reSCQyKJXv@r%{@iTUCtbB4|M^X6qk z!E?c)lQSCim@{uqz+9IlQS$>kT;V3$#a_AR9#iP?ug5Bn2dSZ4AKotZAUkvCZI(Ye z-gP)=d(h>KWyr`2Hv-cFy}}1~;#rz!+DC>TE&TGPXx`(r#|@uMYrC3rc5Kv?_4y}0 z%*kl8)v|>Je^tLB^N03X@qez(%(t{z-0gkK*ltUVrkpT75o*S{Vt-}+ZTB(eork{n zH20pm{J)8Z?WS}+ZL`VZS@!H6TbCUk(s;=IRDOD!l*uL$)=vB*+*!*LmrZorX6l`k z75XaldC27RJ4AE#mY$AWbb!-&rD5KLeam)yH#S^u`tU#;)c)mHv!3+Gmdnh>OCRhhvVmF9^cQJ@Vem$qi1ubzrJ_t%~+p6&d9?3 zf`8|xb#!jMU}0vfg0{)6f4<%GUfi>e^Cahvt+}`2_pRGcWd~mhxf=5F`2%+P=q9VS zB|lGY65069-QOD*e*gQMkAL?s;3Qw{S#W4pmV5TbV~&3u7G>n+U+nAR|C|2@|9}1M z-(J1HUvTSFebDEE^Oc*g9!&i* zu;4#U*V;OcoHD4$KTmx3<;-hIq3(UKNhyRKO?$FN&fjmcVc_I-FevO@VF2C z-niazzd!GW%jnX3x8L3S`Ny2tbwyY14J@uVXV#_C#E(mxx_`HH&C>I88_#{6-p858 zd+ZWj^72cD`=#JZ-P7BaZYVvU*|rU5#-|&vZ{=TEePw;}`{bl!5kGAzd6o0J{jP#D zC(d*}nipro{o%v+pWhshy%%fzZew9npQk^W{M=I(_RpS=ewQ;oC$&#XlGQa>UGzn0 z!!E!uzJu65P#WkxgfEmtSPFtAK_bhzh$ws_ieZi}aZv){1d-GvNE9lLbTWH)=$M&_ zIM~T7z|PysJIY-YCia{fE%KW>)L%Gtf{+(%=HhJR7{|vuh!9ByCUFtrkum%@Co`g7 zK7I_cIc6qA73l;gGgmO6Nuc*I6L(3p$i&XljxDsZ=9)P0EV*`e4i459Ce~J5TaFc% z!?j^^d3;-2zLk}Ud^2-4!jBxIgG2bf9s}gV;VCDxFsU?(&*8+z##+YOSW2QpIb0r( z$FZ{JSX;C48tj-Uky1e%J2IwAStqa`4^fOTS{x-6OCn7`zk(piB&m~`85l^h$#F$Q zDF%v+k#mQ$$cYm~ak!RN95s!+z3H1pM5t^TBkeyKmqd34Vfw98tI^0&fz73(r+4LKIwqD4HvYp(s|1UMdbLSB_F! zP@=Y(C{C=V87L`hMwmjGh8%JGnD8q1gy%Wr?)^Tjs%OU zUXC1UqjHUx_b2iYNJY+g+dgcr72BHU&$Z>-*zmcwY%6=*E=iq~)ui;{jaz@PKq}Cr z7p1z?ek8%-kSQAVQeIQJ4{vY2S7eM-5GfRSc{tTyh)3BpNr0G42UFk4#z&&I~u zp6y^|$7S1c?XB1XI|myanl(4bKG=?D9mIuLRCH5eC{J+=ZckH4c7|IU;d}f<6P0se zLAaRkAyIR%F_I8ztRPzC8j4$pX6I&Ezse1%12}SkzYZ7cKov29 z$yHN?X6IEcQAD{V3&RAFp`u`C4m4tzp_%T=G^%`d!85kv+2|N7x(1mXGOJ?uXnZ;gV=?NwCP-#*w2cTV*T!`rELw%Wuvxz60G%y!yM_b9wgm zY->y0rIdF=sz>SvggQR%ad7Jw5NA5xra~UIejxB1;gg8^4%Sxq#^Hkh@}}fsYSWSQ zP07X7rsXY1M2e-(*7DIP*`!t=9`gxO{qU)y$Qg%5&7#&GCXN$@2YQI{co75qo~;c& z4AF>MqO#>kQcDMNLsEgfVVOOVW_X0FD9gp?kNDJ;qnNu^@FEI#tIdOQMB40?(ia+p zLI`~l(M8V>r4-RcA%s4O=%VL`Qi|xJ5JI0sbkXxeDMfTq2%%3Ry6E|#lp?w)gwQ7u zUG)4=N)cTYLgZ==q_PBDyGq&?gaH^!!jt5nU8Q z=#z*pdVVOSh%O2t^hrb)JwKFEL>Gk+`Xr)@o*zmnqKiTZeG<_{&kv;((M2JIK8fg} z=Z8{?=%NrppG0)g^Ft{`bWsSQPtww5RQ@)oC=!1KG!}o?^FY6#PxyPHCPGhNZw#B- z4a4GRVc0)1eE$-|CRt(FtMT|NrmHcmtz`MQ(*rP;(`+vfSN}K`Cc`VSWZ*yA5Cez- z!~kLdF`#D*)X_6}k+_Hf!~kLdF@P8#7(f9G83JMeF@P9A4Co~TD1hmu+K|wQ0mJ}e z05O097_tGx0Ac_!fEdtA22cRgOSK`P5d(+;!~kLd1u$d-hyla^VgNCqmkiX^OR162 zhylbvtz&@2Vv*nJsWq?oAY8gLRkQ-r9k-}w!~kMI0|tPDhfY2w$`!UC@?e>YJ*>yr zJ(L*;h;XrVqNiFj%h3rts8hrMVnC-1s0dt2*CBSB$3q0O2a(Nu`IBVY? z4Az5A5d<%MBQ7C=AO?aKDVVWN9y?0(QQiM=TwqAWWzDMKQXzYd`D!NPLQf&8uoRSq z7+^93FaXG9tTD${MUIF71o{9$s$2ISMDPMZ3~Vrvf#d7u_b?007R$}6uv&vbOwkvp zU&9*_#c&y9Rm4@pFe(hsNL>1A{1wME-n{ns3d`1seR$#Tl z!dGE35WuKg!QDGVmMpLt#@h0K;21hlMOD(u3*-^~)zk_M2mrBxV|=5SUD5 zE5m~rOCH1&5P(B>a&=Rr@dJ$l0l9&$j^)9oGF;$(9X03?c|b0_F(ID3FI|cHRsAvz z7ZZ&5s|ZAu5d;5A43Hf=ya!Yn{_1%8t1=lhDYxL*5!J3=IZp&x%4&+Zw}n?=ffX3B zWxOlftND)yvl?H4QAGp#Q;SQFe~XbRxKIG2S{zCv1{lHsa1yogX+2f+;#fg8;q0B< z+!a;k&G-qE2QU^^c>p8Y)#N2ah2Zi7I$U@az4gCL!G$g%QY{Xp5d+L&fVe*d#nI%c zHt?VWT&cmQ_3)?kR9-@a{W56Jg0jLOmUa9D#scqlf%{+#yriZfcPeq=@2nBmPGKKR zx>N{ds$^f|xb$`gPzkZ97%`yt3_yo12SNlPbx-SoC*FXQx47Arcr={^UhRD$ra4R! zUZs^7cu5(&pp0*2%QQW^^oDS$nm>^&vtu}T)GQf~KCe^&4mkS*Gj;ha{i~>? zwg)%a!B!hSq6&!sABkn+$6;~#6z3AqCHe7e_|OCSei2x;k!_dU9%8Mjy*jxNE@ocN zXR5vwCxkW(nG8~&9X;TJj0L2>VMY&{soJ#4xvBxwAz&ev#NYGE#3DgJNlk0#W0Gz#i zQ@WWBE?L#Y2K7Y_UNGoFoT}u4b<_lA1-9CRi%9`Y+xn_0Jwe;jl^r5nkl~8^D!s@I z6sBTnSaB3ej{F5nBA47Aymfz4#c%vjnpa!0vJ(ufBFP)sAp)mJa`f=CIH0=1F_PO> z=P`MrK^M57OyoKMGYAS0E38wKd*GCTEs|v*VfgRYdDEeWXKO7CYZ0vPGK1n z93hYe;er}bKam18kiN=!(!~*z?XXG#3^yDco3b+`JAHLz!a7X7bfXJ}fj*gXq5-|( zUjnbNynx@)Qx^o(>9eNu<-As~MJU&|1ZLQ_Cik@k7sW@wt3F?)FZe}z7CxzhR|Cis zDWE6vIKalMTX)~0FInayLQIzLB(=Dz8wYi~Z^9-21pzvJQOEg~bd>@a91sR1kfzRb zVIA_GTu0SPMNSyGNwpq-i^B9_r2^#LC6OQ62OU3MFDu^m=sv_EimglE@*4e#-NVA1{Z6~L!ue9N7x5-567bBS7-XGaN#R2 zuvLbuI^|b4)>q-uP+#iC(lozH0Su4GU>qD*MaKaOfKq^yht3ZKugX>`pdFJos$qc@ zioQEUz^^)7pbW>?n7k4LdHNEp)!_m<%R7GwbFec8a1{8VZ4#Lb{zr$4tSeZLNw{$C zm3|h6Of!@h=E3tz)j0<0Xo3rj2m902UVaH4j02n?3;ZZ2dDAwo%Elv)t;=I=R)8feO%psL~bw zia=fRD*~$O)KnfFu3i@9t7j;mz654ETu@hJ=fWghbgLp=;G!E3>b)v^%Kc-N!BPjf z$m7Ux87c(Ls$kNztqyQ$I<(4qRSsZa^#xBH0|ORjARorDuQ67NKTw#PSD={ff_gOf zREU|3N-1j~lZ=ZzJX9bIV&vH`sHehlFbWqgqC#JExIh_jjB2(o@_h11rKW22WNWG~ z=qL5MeKHg@gxBjm|Gk?GW~hk5!{~$y9w+Ie8>a15;exV*;8m}lA&&2%O0lUgGpnprjhSR8 zQW-8F7Mz$=qln)$6v9<@KT}`yMOLyt+aU;6AP~X5u5iKr;hsE>HjhD&Qq!Me_Mt6( z(Tyd)HKj%rH{hujc`#}(taB0OPNz9+99qZ#fly{Vt8KA`3+@M6(0a2pI>-g7QAAB z_ph^8R)DR+aj5cvakY($ZY*v3%8Iz6oR*gT&_o$bCWF&T6az5Hk&LQckS>)OV0q{6 zt17|<5B0&VuB;DjYDVQ?8e~GR2&z_wOI>#`GQ&O)E_F;*Js;^yJ%>!OLtIA{q8L0k zU?fwIqGAaZ7ha=UqZn}Nsx}bCz@{y~p=u2I(vNr-K~?#;|ky9@j zDf}PRo-}1iMY{@P!11+dqxy=gN&!q$rJ#C<0mJ}e05O0V&^7~gwA~@<4>5okKnx%T z5Chf0019B$!7>^HF@P9A3?K%y&HxHvTBj6sh!{W&AO;Wv)xiJ?VAa7g8Urza7(fgl z2DHuq3Se5N6m^IgKnx%T5Chf0019B$!7>^HF@P9A3?K%y&H(<7flOxIYf?t=}N>2Bt`yEECP6~f^#@cTzY z)8TORDBk$6nB7|zmoL@C-8;v{qxrK^6SVR3FaZ4KLrsT*@B4HW0&k#+fX~Q63q767 zLTDx&0NDJGpWGHtU%l?|<>I1P{x3p z1_AR>u#j3V0I$PX6b1+Bs-Q5F%0(o_05dzv!M3WEY8CgZ9ULx!KFPJJOz8P@`$YZp z8EAN)`etcKG=8o4$`A-01hmFD8gc=v%GT|CUA$1oAz;@~TM_~8T#HB*6bHOr-Y94g}s27x~WdLa3 z{%H>YsEPZ083q9B9Y7oQT#29)>fqs{(rw#kwAb)H22qRiys?gbpz8ApJwRL{{g8|1 zh>~e~$`h5^0YMudoPY6LJ_2-We2xLYdA^Pu+MmfI0Kl0m(epoGdq%;6V5t@g@A)Uj zOw-KD+Myx2qz8ygpigqe&eUplqtD*IlLO%U&re#jr`7OOfctzsxHs2%yU*D8D8QWy z!0Rwgg2Gf`z3T9~^_^RVKo1VL7PL$`$ff0plBs7DcHvDkisV73HaESsW~}z(S!wH|YuTn2ReDZT>6I2;a#!{Kl^91e%W5rscvW7xI5N1(d^0000Example usage: - * - *
- *   TowerAnimationRenderComponent towerAnimator = new TowerAnimationRenderComponent("turret.atlas");
- *   entity.addComponent(towerAnimator);
- *   towerAnimator.addAnimation("attack", 0.1f); // Only need to add animation once per entity
- *   towerAnimator.startAnimation("attack");
- * 
- * - * Texture atlases can be created using:
- * - libgdx texture packer (included in External Libraries/gdx-tools)
- * - gdx-texture-packer-gui (recommended) https://github.com/crashinvaders/gdx-texture-packer-gui
- * - other third-party tools, e.g. https://www.codeandweb.com/texturepacker
- */ -public class TowerAnimationRenderComponent extends RenderComponent { - private static final Logger logger = LoggerFactory.getLogger(TowerAnimationRenderComponent.class); - private final GameTime timeSource; - private final TextureAtlas atlas; - private final Map> animations; - private Animation currentAnimation; - private String currentAnimationName; - private float animationPlayTime; - // TODO: remove reimplentations of existing functionality and only declare overridden methods - /** - * Create the component for a given texture atlas. - * @param atlas libGDX-supported texture atlas containing desired animations - */ - public TowerAnimationRenderComponent(TextureAtlas atlas) { - this.atlas = atlas; - this.animations = new HashMap<>(4); - timeSource = ServiceLocator.getTimeSource(); - } - - /** - * Register an animation from the texture atlas. Will play once when called with startAnimation() - * @param name Name of the animation. Must match the name of this animation inside the texture - * atlas. - * @param frameDuration How long, in seconds, to show each frame of the animation for when playing - * @return true if added successfully, false otherwise - */ - public boolean addAnimation(String name, float frameDuration) { - return addAnimation(name, frameDuration, PlayMode.NORMAL); - } - - /** - * Register an animation from the texture atlas. - * @param name Name of the animation. Must match the name of this animation inside the texture - * atlas. - * @param frameDuration How long, in seconds, to show each frame of the animation for when playing - * @param playMode How the animation should be played (e.g. looping, backwards) - * @return true if added successfully, false otherwise - */ - public boolean addAnimation(String name, float frameDuration, PlayMode playMode) { - Array regions = atlas.findRegions(name); - if (regions == null || regions.size == 0) { - logger.warn("Animation {} not found in texture atlas", name); - return false; - } else if (animations.containsKey(name)) { - logger.warn( - "Animation {} already added in texture atlas. Animations should only be added once.", - name); - return false; - } - - Animation animation = new Animation<>(frameDuration, regions, playMode); - animations.put(name, animation); - logger.debug("Adding animation {}", name); - return true; - } - - /** Scale the entity to a width of 1 and a height matching the texture's ratio */ - public void scaleEntity() { - TextureRegion defaultTexture = this.atlas.findRegion("default"); - entity.setScale(1f, (float) defaultTexture.getRegionHeight() / defaultTexture.getRegionWidth()); - } - - /** - * Remove an animation from this animator. This is not required before disposing. - * @param name Name of the previously added animation. - * @return true if removed, false if animation was not found. - */ - public boolean removeAnimation(String name) { - logger.debug("Removing animation {}", name); - return animations.remove(name) != null; - } - - /** - * Whether the animator has added the given animation. - * @param name Name of the added animation. - * @return true if added, false otherwise. - */ - public boolean hasAnimation(String name) { - return animations.containsKey(name); - } - - /** - * Start playback of an animation. The animation must have been added using addAnimation(). - * @param name Name of the animation to play. - */ - public void startAnimation(String name) { - Animation animation = animations.getOrDefault(name, null); - if (animation == null) { - logger.error( - "Attempted to play unknown animation {}. Ensure animation is added before playback.", - name); - return; - } - - currentAnimation = animation; - currentAnimationName = name; - animationPlayTime = 0f; - logger.debug("Starting animation {}", name); - } - - /** - * Stop the currently running animation. Does nothing if no animation is playing. - * @return true if animation was stopped, false if no animation is playing. - */ - public boolean stopAnimation() { - if (currentAnimation == null) { - return false; - } - - logger.debug("Stopping animation {}", currentAnimationName); - currentAnimation = null; - currentAnimationName = null; - animationPlayTime = 0f; - return true; - } - - /** - * Get the name of the animation currently being played. - * @return current animation name, or null if not playing. - */ - public String getCurrentAnimation() { - return currentAnimationName; - } - - /** - * Has the playing animation finished? This will always be false for looping animations. - * @return true if animation was playing and has now finished, false otherwise. - */ - public boolean isFinished() { - return currentAnimation != null && currentAnimation.isAnimationFinished(animationPlayTime); - } - - @Override - protected void draw(SpriteBatch batch) { - if (currentAnimation == null) { - return; - } - TextureRegion region = currentAnimation.getKeyFrame(animationPlayTime); - Vector2 pos = entity.getPosition(); - Vector2 scale = entity.getScale(); - batch.draw(region, pos.x, pos.y, scale.x, scale.y); - animationPlayTime += timeSource.getDeltaTime(); - } - - @Override - public void dispose() { - atlas.dispose(); - super.dispose(); - } -} diff --git a/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java b/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java deleted file mode 100644 index e267feae4..000000000 --- a/source/core/src/main/com/csse3200/game/rendering/TowerTextureRenderComponent.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.csse3200.game.rendering; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.math.Vector2; -import com.csse3200.game.services.ServiceLocator; - -/** Render a static tower texture. */ -// TODO: remove reimplentations of existing functionality and only declare overridden methods -public class TowerTextureRenderComponent extends RenderComponent { - private final Texture texture; - - /** - * @param type The type of tower to be instantiated. - */ - public TowerTextureRenderComponent(String type) { - this(ServiceLocator.getResourceService().getAsset("images/turret_deployed.png", Texture.class)); - - } -//... - /** @param texture Static tower texture to render. Will be scaled to the entity's scale. */ - public TowerTextureRenderComponent(Texture texture) { - this.texture = texture; - } - - /** Scale the entity to a width of 1 and a height matching the texture's ratio */ - public void scaleEntity() { - entity.setScale(1f, (float) texture.getHeight() / texture.getWidth()); - } - - @Override - protected void draw(SpriteBatch batch) { - Vector2 position = entity.getPosition(); - Vector2 scale = entity.getScale(); - batch.draw(texture, position.x, position.y, scale.x, scale.y); - } -} diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java deleted file mode 100644 index db1afce3a..000000000 --- a/source/core/src/test/com/csse3200/game/rendering/TowerAnimationRenderComponentTest.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.csse3200.game.rendering; - -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; -import com.badlogic.gdx.utils.Array; -import com.csse3200.game.entities.Entity; -import com.csse3200.game.extensions.GameExtension; -import com.csse3200.game.services.GameTime; -import com.csse3200.game.services.ServiceLocator; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@ExtendWith(GameExtension.class) -class TowerAnimationRenderComponentTest { - @Test - void shouldAddRemoveAnimation() { - TextureAtlas atlas = createMockAtlas("test_name", 1); - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - - assertTrue(animator.addAnimation("test_name", 0.1f)); - assertTrue(animator.removeAnimation("test_name")); - assertFalse(animator.removeAnimation("test_name")); - } - - @Test - void shouldFailRemoveInvalidAnimation() { - TextureAtlas atlas = mock(TextureAtlas.class); - when(atlas.findRegions("test_name")).thenReturn(null); - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - - assertFalse(animator.addAnimation("test_name", 0.1f)); - assertFalse(animator.removeAnimation("test_name")); - } - - @Test - void shouldFailDuplicateAddAnimation() { - TextureAtlas atlas = createMockAtlas("test_name", 1); - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - - assertTrue(animator.addAnimation("test_name", 0.1f)); - assertFalse(animator.addAnimation("test_name", 0.2f)); - } - - @Test - void shouldHaveAnimation() { - TextureAtlas atlas = createMockAtlas("test_name", 1); - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - - animator.addAnimation("test_name", 0.1f); - assertTrue(animator.hasAnimation("test_name")); - animator.removeAnimation("test_name"); - assertFalse(animator.hasAnimation("test_name")); - } - - @Test - void shouldPlayAnimation() { - int numFrames = 5; - String animName = "test_name"; - float frameTime = 1f; - - // Mock texture atlas - TextureAtlas atlas = createMockAtlas(animName, numFrames); - Array regions = atlas.findRegions(animName); - SpriteBatch batch = mock(SpriteBatch.class); - - // Mock game time - GameTime gameTime = mock(GameTime.class); - ServiceLocator.registerTimeSource(gameTime); - when(gameTime.getDeltaTime()).thenReturn(frameTime); - - // Start animation - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - Entity entity = new Entity(); - animator.setEntity(entity); - animator.addAnimation(animName, frameTime); - animator.startAnimation(animName); - - for (int i = 0; i < 5; i++) { - // Each draw advances 1 frame, check that it matches for each - animator.draw(batch); - verify(batch).draw( - regions.get(i), - entity.getPosition().x, - entity.getPosition().y, - entity.getScale().x, - entity.getScale().y - ); - } - } - - @Test - void shouldFinish() { - TextureAtlas atlas = createMockAtlas("test_name", 1); - SpriteBatch batch = mock(SpriteBatch.class); - - GameTime gameTime = mock(GameTime.class); - ServiceLocator.registerTimeSource(gameTime); - when(gameTime.getDeltaTime()).thenReturn(1f); - - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - Entity entity = new Entity(); - animator.setEntity(entity); - animator.addAnimation("test_name", 1f); - assertFalse(animator.isFinished()); - - animator.startAnimation("test_name"); - assertFalse(animator.isFinished()); - - animator.draw(batch); - assertTrue(animator.isFinished()); - } - - @Test - void shouldStopAnimation() { - TextureAtlas atlas = createMockAtlas("test_name", 1); - AnimationRenderComponent animator = new AnimationRenderComponent(atlas); - animator.addAnimation("test_name", 1f); - assertFalse(animator.stopAnimation()); - - animator.startAnimation("test_name"); - assertTrue(animator.stopAnimation()); - assertNull(animator.getCurrentAnimation()); - } - - static TextureAtlas createMockAtlas(String animationName, int numRegions) { - TextureAtlas atlas = mock(TextureAtlas.class); - Array regions = new Array<>(numRegions); - for (int i = 0; i < numRegions; i++) { - regions.add(mock(AtlasRegion.class)); - } - when(atlas.findRegions(animationName)).thenReturn(regions); - return atlas; - } -} \ No newline at end of file diff --git a/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java b/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java deleted file mode 100644 index ebb0b9b97..000000000 --- a/source/core/src/test/com/csse3200/game/rendering/TowerTextureRenderComponentTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.csse3200.game.rendering; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.math.Vector2; -import com.csse3200.game.entities.Entity; -import com.csse3200.game.extensions.GameExtension; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(GameExtension.class) -@ExtendWith(MockitoExtension.class) -class TowerTextureRenderComponentTest { - @Mock Texture texture; - @Mock SpriteBatch spriteBatch; - @Mock Entity entity; - - @Test - void shouldDrawTexture() { - when(entity.getPosition()).thenReturn(new Vector2(2f, 2f)); - when(entity.getScale()).thenReturn(new Vector2(1f, 1f)); - TextureRenderComponent component = new TextureRenderComponent(texture); - component.setEntity(entity); - component.render(spriteBatch); - - verify(spriteBatch).draw(texture, 2f, 2f, 1f, 1f); - } -} \ No newline at end of file From e3a9202ffdb67ccb02aaf837b3be4d22e78d01ad Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 10:27:45 +1000 Subject: [PATCH 20/33] asset update --- source/core/assets/images/turret_deploy.atlas | 98 +++++------------- source/core/assets/images/turret_deploy.png | Bin 2878 -> 5102 bytes 2 files changed, 28 insertions(+), 70 deletions(-) diff --git a/source/core/assets/images/turret_deploy.atlas b/source/core/assets/images/turret_deploy.atlas index 83abe2827..2176c56f6 100644 --- a/source/core/assets/images/turret_deploy.atlas +++ b/source/core/assets/images/turret_deploy.atlas @@ -1,125 +1,83 @@ turret_deploy.png -size: 512, 128 +size: 256, 256 format: RGBA8888 filter: Nearest, Nearest repeat: xy -angry +1 rotate: false - xy: 80, 20 + xy: 20, 134 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -angry - rotate: false - xy: 380, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -angry - rotate: false - xy: 200, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -angry +2 rotate: false xy: 20, 20 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -angry - rotate: false - xy: 320, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -angry - rotate: false - xy: 140, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -angry +3 rotate: false - xy: 440, 20 + xy: 20, 77 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -angry +4 rotate: false - xy: 260, 20 + xy: 20, 191 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -default +5 rotate: false - xy: 260, 20 + xy: 140, 191 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -idle +6 rotate: false - xy: 80, 20 + xy: 80, 191 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -idle +7 rotate: false - xy: 380, 20 + xy: 80, 77 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -idle +8 rotate: false - xy: 200, 20 + xy: 80, 134 size: 40, 37 orig: 40, 37 offset: 0, 0 index: -1 -idle +fire1 rotate: false - xy: 20, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -idle - rotate: false - xy: 320, 20 - size: 40, 37 - orig: 40, 37 + xy: 140, 138 + size: 35, 33 + orig: 35, 33 offset: 0, 0 index: -1 -idle +fire2 rotate: false - xy: 140, 20 - size: 40, 37 - orig: 40, 37 + xy: 80, 24 + size: 35, 33 + orig: 35, 33 offset: 0, 0 index: -1 -idle +fire3 rotate: false - xy: 440, 20 - size: 40, 37 - orig: 40, 37 + xy: 200, 195 + size: 35, 33 + orig: 35, 33 offset: 0, 0 index: -1 -idle - rotate: false - xy: 260, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 \ No newline at end of file diff --git a/source/core/assets/images/turret_deploy.png b/source/core/assets/images/turret_deploy.png index d4f41aef496ced6d3e1777e3280c539ee1b9ec3e..58ba60e8e29e287ab673e5a7cb5d161862530eff 100644 GIT binary patch literal 5102 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 Mb#uda`mRs@3$F|$(f|Me literal 2878 zcmcgu>pv3=8(!}t<$Nkc89kw%DU|a>N5F zA!(Mw45NvdnHlErj2&Lj@Av!x&!_kLaR06k*L`32@BVP#ck1O!7v!WhqyYecoRg!y zI{@&X9STU;E4dSqUIQ`!fXr?udppk<2xrnY^WcR8fT>jYOeVQ!90Hcolke7~JDDW` z`1W=dYVz7sPZX8avd?urK6B*1iU-e}Ettx*cl`O~P`om#{oSKaRn4-clq96Yepsl8bJ;mjO4P8Ft3jjz#L z3-az>Lc7h?V-6ja6_orXsLz}`thZMI@^Pptzk81Yusibo1)7brwON8l7QenIYFz%# zImm581bMzowe#jGp!lI`;;l^-Cb;kR;T>73NVZ~gem=b!vv(-)u$yEjQ9&zy^m%lw z-jR+#^gN~JEMI1bvZ`3A$SrHEW)8e@jl!tJ+UWp_PVO_eIB2K86SAFX^@sv)kY%`|=|bdy{3uMN zj`Um_?;sofWv)~$Vc@)MV?(r%k!rUkAty-29Wq|k;~>DF3GWRSD3V}?gS^xfPj)! z5PPf-Z|Sm8?ko-yB^EQ$90fbyC$ zTW~-?b`b*5v?7T%c4}WwTm{%ob~kYJ8Hfs>((I|(#5Re9W9cl)C2xzWA7tGUO_!`u zb+;y|0TETSKRpl7SSw{#Wh0Yr8SK0~f)Q2P^2Cp}SabaYA3F@~iPDPG=55Eq`2+qy0t*4 z@|BVztDeGR*lT8#SZ_YyIYPa3rH{!2$A61X}uO*YE)=rc-~Ks@qV1&NXJ;=85*kWD=h|?3oR~{p(z)~ zdaOXgJf@GVGWA%&@#9w+MurA$ce$yXfrEQek!914>Izkd*TI9o*;F`cU40`)A1*T@dBc>;z>DFkAid~0~HCxfWnLgKPMe1ck-vtZMG3@~`-N$ToJ@mBq z0~YBMRA@ObC;Dd=Scxva&L8plLGG<~0q8v`*9h2rUuMxoqR#5p(^#Bfn(3OvdMJ8s zXa+Pd_l<-Vk7o2a9MuOkn}KYvr(Id;sB3O}ut55h?nEh9!J5X>BdzErXYBh%EaP@Z z3dTlZ<-Db(l?<);{f44>4~_bFB%MxP(T3ctUyCQj>p6Bg3g7xzCtWb5l%rs5)Ha{Q z!R7v#0+tRjOH%rNIh_HwdCYV~jv?V?wlos=?jvLjRrpad=+&}kLAx7BUNM)j2%P{J z|1yDTIRnmGvM)1>ByN_GA|MbN#(I6N-nI2Ehb^as5{8Z0-6})QXulK(UmJZeDjL3q zZ1UWm{W-Mwi5*Xr&RL>}1qhXZmSG&N-48tXa+6sTm-3kZ;yc^>d33o&7+E|(_hfdo zG_4D{#f6nO^tDpT!-d^Ea(jUSV1?T!t9(xCi~-06e${fnB~96tm?EijfkUTT$D#lDOjy2C(m`xlp&9lSP%cQ#P1eDC3vShaJo zbd($YL!ny9tXI_TH`Gvq$)HXCaAZ zb!m1}M2eyE-~})k>?%uz9o@Azxw7vnwzum($X5Fo_-bB1yu3jv1A+*sp1?po3VTLO zN1FHHP#XjNZm8At>TepixgBaM3Agf(2h-QY=-gMi{=KIG*WpbjO}5WiL?m;|PIvpk z!H4v{gjNJmyr5Yxtmp{~B}=bM@l>hJ!?-XT_}gR64Xx@P8t7lMC>hEOkw}ttj0d&Q zd{jA}C5}HX6bQ`A;B;=UO@}j^_~i?&J`x|oC@Oo8-180!Q%&shkrkMq5J7m;rCG)<`O-t zGaKW<5Q=B_8moa6@zFi0t?>#BhxOg$GXy~MVSvu`Nfz%b>24ieXLT>?I;@ZfeMet_ z447Pl(B3U#9*Vgex&19$b1<2gVxY5p5rVBigfMrr*GoV+ zdn77~(&G@&s$sD3{W)a2>}X}~^#&oYVcs+|t@F`Usl=!czl*=V!cSM8I&kDHKLFe~ zA)sm8puriIi;d71KtWl{t_a6XjEpdH=TuZYR>|q Date: Thu, 24 Aug 2023 10:29:07 +1000 Subject: [PATCH 21/33] modified TowerFactory with AiTaskComponent and AnimationRenderComponent additions --- .../game/entities/factories/NPCFactory.java | 6 ++-- .../game/entities/factories/TowerFactory.java | 32 +++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 29daa24f2..10ab700b1 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -76,9 +76,9 @@ public static Entity createGhostKing(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() - .getAsset("images/turret_deploy.atlas", TextureAtlas.class)); - animator.addAnimation("idle", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("angry", 0.2f, Animation.PlayMode.REVERSED); + .getAsset("images/turret.atlas", TextureAtlas.class)); + animator.addAnimation("stow", 0.2f, Animation.PlayMode.NORMAL); + animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); ghostKing .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 3effde0c7..4556012eb 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -1,9 +1,15 @@ package com.csse3200.game.entities.factories; +import com.badlogic.gdx.graphics.g2d.Animation; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; +import com.csse3200.game.ai.tasks.AITaskComponent; +import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.CostComponent; +import com.csse3200.game.components.tasks.TowerCombatTask; +import com.csse3200.game.components.tasks.TowerIdleTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.configs.WallTowerConfig; import com.csse3200.game.physics.PhysicsLayer; @@ -13,6 +19,9 @@ import com.csse3200.game.entities.configs.WeaponTowerConfig; import com.csse3200.game.entities.configs.baseTowerConfigs; import com.csse3200.game.files.FileLoader; +import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.rendering.TextureRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * Factory to create a tower entity. @@ -21,7 +30,8 @@ * the properties stores in 'baseTowerConfigs'. */ public class TowerFactory { - + private static final int WEAPON_SCAN_INTERVAL = 1; + private static final int COMBAT_TASK_PRIORITY = 2; private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); @@ -40,15 +50,31 @@ public static Entity createWallTower() { } /** - * Creates a weaponry tower that shoots at mobs + * Creates a weaponry tower that shoots at mobs - This will most likely need to be extended + * once other types of weapon towers are developed * @return entity */ public static Entity createWeaponTower() { Entity weapon = createBaseTower(); WeaponTowerConfig config = configs.weapon; + // TODO: uncomment once tasks are finalised - will break build if included before +// AITaskComponent aiTaskComponent = new AITaskComponent() +// .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)) +// .addTask(new TowerCombatTask()); + + // TODO: uncomment once animations are finalised - will break build if included before +// AnimationRenderComponent animator = +// new AnimationRenderComponent( +// ServiceLocator.getResourceService() +// .getAsset("images/turret.atlas", TextureAtlas.class)); +// animator.addAnimation("idle", 0.5f, Animation.PlayMode.LOOP); +// animator.addAnimation("stow", 0.3f, Animation.PlayMode.NORMAL); +// animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); +// animator.addAnimation("firing", 0.2f, Animation.PlayMode.LOOP); + weapon - .addComponent(new CombatStatsComponent(config.health,config.baseAttack)) + .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(new CostComponent(config.cost)); return weapon; From fa94aafdb80ddb4f2f7626ce3aa2460941709b23 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 10:31:33 +1000 Subject: [PATCH 22/33] created TowerAnimationController class --- .../tower/TowerAnimationController.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java index 2db8dadfc..7e24bfaf0 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java @@ -4,7 +4,7 @@ import com.csse3200.game.rendering.AnimationRenderComponent; /** - * This class listens to events relevant to a ghost entity's state and plays the animation when one + * This class listens to events relevant to a weapon tower state and plays the animation when one * of the events is triggered. */ public class TowerAnimationController extends Component { @@ -14,15 +14,26 @@ public class TowerAnimationController extends Component { public void create() { super.create(); animator = this.entity.getComponent(AnimationRenderComponent.class); - entity.getEvents().addListener("wanderStart", this::animateWander); - entity.getEvents().addListener("chaseStart", this::animateChase); + entity.getEvents().addListener("idleStart", this::animateIdle); + entity.getEvents().addListener("deployStart", this::animateDeploy); + entity.getEvents().addListener("stowStart", this::animateStow); + entity.getEvents().addListener("firingStart", this::animateFiring); + } - void animateWander() { + void animateIdle() { animator.startAnimation("idle"); } - void animateChase() { - animator.startAnimation("angry"); + void animateStow() { + animator.startAnimation("stow"); + } + + void animateDeploy() { + animator.startAnimation("deploy"); + } + + void animateFiring() { + animator.startAnimation("firing"); } } \ No newline at end of file From 5f1e1a7769d64f39514cc6d30cf25d6f6a8af045 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 11:34:59 +1000 Subject: [PATCH 23/33] modified ForestGameArea for testing, added TowerCombatTask and TowerIdleTask --- source/core/assets/images/turret.png | Bin 0 -> 5490 bytes .../csse3200/game/areas/ForestGameArea.java | 21 +++- .../components/tasks/TowerCombatTask.java | 101 ++++++++++++++++++ .../game/components/tasks/TowerIdleTask.java | 94 ++++++++++++++++ 4 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 source/core/assets/images/turret.png create mode 100644 source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java create mode 100644 source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java diff --git a/source/core/assets/images/turret.png b/source/core/assets/images/turret.png new file mode 100644 index 0000000000000000000000000000000000000000..025f187079cc9837e23231c4a124f900c5a1adfb GIT binary patch literal 5490 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 maxRange || !isTargetVisible()) { + return -1; // Too far, stop chasing + } + return priority; + } + + private int getInactivePriority() { + float dst = getDistanceToTarget(); + if (dst < maxRange && isTargetVisible()) { + return priority; + } + return -1; + } + + private boolean isTargetVisible() { + + // If there is an obstacle in the path to the player, not visible. + if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.OBSTACLE, hit)) { + debugRenderer.drawLine(towerPosition, hit.point); + return true; + } + debugRenderer.drawLine(towerPosition, maxRangePosition); + return false; + } +} diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java new file mode 100644 index 000000000..63e4a07f6 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java @@ -0,0 +1,94 @@ +package com.csse3200.game.components.tasks; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.ai.tasks.Task; +import com.csse3200.game.physics.PhysicsEngine; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.raycast.RaycastHit; +import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; + +/** + * Task for the Tower Idle State - specifically for the + * Weapon Tower Entity that can move between combat and + * idle states. Scans for enemy mobs but does nothing else. + */ +public class TowerIdleTask extends DefaultTask implements PriorityTask { + + private static final float SCAN_RANGE = 500; + private static final int ACTIVE_PRIORITY = 1; + private static final int INACTIVE_PRIORITY = -1; + private final GameTime timeSource; + private final float interval; + private long endTime; + private final PhysicsEngine physics; + private final DebugRenderer debugRenderer; + private final RaycastHit hit = new RaycastHit(); + + /** + * @param interval time between scanning for mobs, in seconds. + */ + public TowerIdleTask(float interval) { + timeSource = ServiceLocator.getTimeSource(); + physics = ServiceLocator.getPhysicsService().getPhysics(); + this.interval = interval; + debugRenderer = ServiceLocator.getRenderService().getDebug(); + } + + /** + * Start waiting from now until interval has passed. + */ + @Override + public void start() { + super.start(); + endTime = timeSource.getTime() + (int)(this.interval * 1000); + } + + @Override + public void update() { + if (timeSource.getTime() >= endTime) { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger("mobsVisible"); + } + status = Status.FINISHED; + } + } + + /** + * Scan for any mob entities in the lane. Triggers the 'mobsVisible' event + **/ + private boolean isTargetVisible() { + Vector2 from = owner.getEntity().getCenterPosition(); + Vector2 to = new Vector2(from.x + SCAN_RANGE, from.y); + + // If there is an obstacle in the path to the end of the tower scan range + // must be mobs present. + if (physics.raycast(from, to, PhysicsLayer.OBSTACLE, hit)) { + debugRenderer.drawLine(from, hit.point); + return true; + } + debugRenderer.drawLine(from, to); + return false; + } + + @Override + public int getPriority() { + if (status == Status.ACTIVE) { + return getActivePriority(); + } + + return getInactivePriority(); + } + + public int getActivePriority() { + return this.ACTIVE_PRIORITY; + } + + public int getInactivePriority() { + return this.INACTIVE_PRIORITY; + } + +} \ No newline at end of file From c1fff298bae74106b6ccc3f81d000f1450446ba1 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 18:44:08 +1000 Subject: [PATCH 24/33] Built tower idle and combat tasks --- .../components/tasks/TowerCombatTask.java | 38 ++++++++++--------- .../game/components/tasks/TowerIdleTask.java | 13 +++++-- 2 files changed, 30 insertions(+), 21 deletions(-) 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 006b6dacc..ac7d5e17c 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 @@ -9,16 +9,19 @@ import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TowerCombatTask extends DefaultTask implements PriorityTask { + private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); private final int priority; private final float maxRange; - private final Vector2 towerPosition = owner.getEntity().getCenterPosition(); + private Vector2 towerPosition = new Vector2(10,10); private final Vector2 maxRangePosition = new Vector2(); private final PhysicsEngine physics; private final DebugRenderer debugRenderer; private final RaycastHit hit = new RaycastHit(); -// private DeployTask deployTask; + /** * @param priority Task priority when chasing (0 when not chasing). @@ -27,41 +30,42 @@ public class TowerCombatTask extends DefaultTask implements PriorityTask { public TowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; +// this.towerPosition = this.owner.getEntity().getCenterPosition(); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); physics = ServiceLocator.getPhysicsService().getPhysics(); debugRenderer = ServiceLocator.getRenderService().getDebug(); + logger.debug("TowerCombatTask started"); } @Override public void start() { super.start(); - -// deployTask.create(owner); -// deployTask.start(); - - this.owner.getEntity().getEvents().trigger("towerDeployStart"); + this.towerPosition = owner.getEntity().getCenterPosition(); + owner.getEntity().getEvents().trigger("firingStart"); } @Override public void update() { -// deployTask.update(); -// if (deployTaskTask.getStatus() != Status.ACTIVE) { -// deployTask.start(); -// } + if (status == Status.ACTIVE) { + owner.getEntity().getEvents().trigger("firingStart"); + logger.debug("firing start event should have been triggered"); + } else { + owner.getEntity().getEvents().trigger("stowStart"); + logger.debug("stow start event should have been triggered"); + } } @Override public void stop() { super.stop(); -// deployTask.stop(); + owner.getEntity().getEvents().trigger("stowStart"); } @Override public int getPriority() { - if (status == Status.ACTIVE) { + if (isTargetVisible()) { return getActivePriority(); } - return getInactivePriority(); } @@ -75,7 +79,7 @@ private float getDistanceToTarget() { private int getActivePriority() { float dst = getDistanceToTarget(); if (dst > maxRange || !isTargetVisible()) { - return -1; // Too far, stop chasing + return -1; // Too far, stop firing } return priority; } @@ -90,8 +94,8 @@ private int getInactivePriority() { private boolean isTargetVisible() { - // If there is an obstacle in the path to the player, not visible. - if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.OBSTACLE, hit)) { + // If there is an obstacle in the path to the max range point, mobs visible. + if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.NPC, hit)) { debugRenderer.drawLine(towerPosition, hit.point); return true; } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java index 63e4a07f6..96414c5d7 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java @@ -1,6 +1,7 @@ package com.csse3200.game.components.tasks; import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.ai.tasks.Task; @@ -10,6 +11,8 @@ import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Task for the Tower Idle State - specifically for the @@ -17,9 +20,9 @@ * idle states. Scans for enemy mobs but does nothing else. */ public class TowerIdleTask extends DefaultTask implements PriorityTask { - + private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); private static final float SCAN_RANGE = 500; - private static final int ACTIVE_PRIORITY = 1; + private static final int ACTIVE_PRIORITY = 0; private static final int INACTIVE_PRIORITY = -1; private final GameTime timeSource; private final float interval; @@ -36,6 +39,7 @@ public TowerIdleTask(float interval) { physics = ServiceLocator.getPhysicsService().getPhysics(); this.interval = interval; debugRenderer = ServiceLocator.getRenderService().getDebug(); + logger.debug("Weapon Tower idleTask started"); } /** @@ -51,7 +55,8 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { if (isTargetVisible()) { - owner.getEntity().getEvents().trigger("mobsVisible"); + owner.getEntity().getEvents().trigger("deployStart"); + logger.debug("Idle Task update function: Detected a target!"); } status = Status.FINISHED; } @@ -66,7 +71,7 @@ private boolean isTargetVisible() { // If there is an obstacle in the path to the end of the tower scan range // must be mobs present. - if (physics.raycast(from, to, PhysicsLayer.OBSTACLE, hit)) { + if (physics.raycast(from, to, PhysicsLayer.NPC, hit)) { debugRenderer.drawLine(from, hit.point); return true; } From 23cebb2707152bd528137083329a3e880a7d727c Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 18:45:42 +1000 Subject: [PATCH 25/33] updated the TowerFactory to add animator and aiTask components --- .../game/entities/factories/TowerFactory.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 4556012eb..7647f5a46 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -30,8 +30,10 @@ * the properties stores in 'baseTowerConfigs'. */ public class TowerFactory { + private static final int WEAPON_SCAN_INTERVAL = 1; private static final int COMBAT_TASK_PRIORITY = 2; + public static final int WEAPON_TOWER_MAX_RANGE = 500; private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); @@ -58,25 +60,26 @@ public static Entity createWeaponTower() { Entity weapon = createBaseTower(); WeaponTowerConfig config = configs.weapon; - // TODO: uncomment once tasks are finalised - will break build if included before -// AITaskComponent aiTaskComponent = new AITaskComponent() -// .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)) -// .addTask(new TowerCombatTask()); - - // TODO: uncomment once animations are finalised - will break build if included before -// AnimationRenderComponent animator = -// new AnimationRenderComponent( -// ServiceLocator.getResourceService() -// .getAsset("images/turret.atlas", TextureAtlas.class)); -// animator.addAnimation("idle", 0.5f, Animation.PlayMode.LOOP); -// animator.addAnimation("stow", 0.3f, Animation.PlayMode.NORMAL); -// animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); -// animator.addAnimation("firing", 0.2f, Animation.PlayMode.LOOP); +//// TODO: uncomment once tasks are finalised - will break build if included before + AITaskComponent aiTaskComponent = new AITaskComponent() + .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)) + .addTask(new TowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); +// +// // TODO: uncomment once animations are finalised - will break build if included before + AnimationRenderComponent animator = + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset("images/turret.atlas", TextureAtlas.class)); + animator.addAnimation("idle", 0.5f, Animation.PlayMode.LOOP); + animator.addAnimation("stow", 0.3f, Animation.PlayMode.NORMAL); + animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); + animator.addAnimation("firing", 0.2f, Animation.PlayMode.LOOP); weapon .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) - .addComponent(new CostComponent(config.cost)); - + .addComponent(new CostComponent(config.cost)) + .addComponent(aiTaskComponent) + .addComponent(animator); return weapon; } From 97cea2d8e4302fa9a2d1e86103b490b3e65a939d Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 18:46:15 +1000 Subject: [PATCH 26/33] fixed some naming --- source/core/assets/images/turret.atlas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/core/assets/images/turret.atlas b/source/core/assets/images/turret.atlas index 2a9c54abe..e09479efe 100644 --- a/source/core/assets/images/turret.atlas +++ b/source/core/assets/images/turret.atlas @@ -67,21 +67,21 @@ default orig: 40, 37 offset: 0, 0 index: -1 -fire +firing rotate: false xy: 200, 195 size: 35, 33 orig: 35, 33 offset: 0, 0 index: -1 -fire +firing rotate: false xy: 140, 81 size: 35, 33 orig: 35, 33 offset: 0, 0 index: -1 -fire +firing rotate: false xy: 80, 24 size: 35, 33 From b9cec11a1255c2d7cc6f7d281877d626939e5e4b Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 21:32:20 +1000 Subject: [PATCH 27/33] restored ghost functionality to focus on dedicated turret classes --- .../components/npc/GhostAnimationController.java | 4 ++-- .../csse3200/game/entities/factories/NPCFactory.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java index 7a689a893..78c7ce6e4 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/GhostAnimationController.java @@ -19,10 +19,10 @@ public void create() { } void animateWander() { - animator.startAnimation("idle"); + animator.startAnimation("float"); } void animateChase() { - animator.startAnimation("angry"); + animator.startAnimation("angry_float"); } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index 10ab700b1..c546343c0 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -49,9 +49,9 @@ public static Entity createGhost(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( - ServiceLocator.getResourceService().getAsset("images/turret_body_idle.atlas", TextureAtlas.class)); - animator.addAnimation("idle", 0.1f, Animation.PlayMode.LOOP); - animator.addAnimation("angry", 0.1f, Animation.PlayMode.LOOP); + ServiceLocator.getResourceService().getAsset("images/ghost.atlas", TextureAtlas.class)); + animator.addAnimation("angry_float", 0.1f, Animation.PlayMode.LOOP); + animator.addAnimation("float", 0.1f, Animation.PlayMode.LOOP); ghost .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) @@ -76,9 +76,9 @@ public static Entity createGhostKing(Entity target) { AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() - .getAsset("images/turret.atlas", TextureAtlas.class)); - animator.addAnimation("stow", 0.2f, Animation.PlayMode.NORMAL); - animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); + .getAsset("images/ghostKing.atlas", TextureAtlas.class)); + animator.addAnimation("float", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("angry_float", 0.2f, Animation.PlayMode.LOOP); ghostKing .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) From f1ca47d7d83579c184feb5a1829b13202588bca3 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 23:10:45 +1000 Subject: [PATCH 28/33] duplicated assets for troubleshooting --- source/core/assets/images/turret01.atlas | 160 ++++++++++++++++++ source/core/assets/images/turret01.png | Bin 0 -> 5490 bytes .../core/assets/images/turret_body_idle.atlas | 55 ------ .../core/assets/images/turret_body_idle.png | Bin 758 -> 0 bytes source/core/assets/images/turret_deploy.atlas | 83 --------- source/core/assets/images/turret_deploy.png | Bin 5102 -> 0 bytes 6 files changed, 160 insertions(+), 138 deletions(-) create mode 100644 source/core/assets/images/turret01.atlas create mode 100644 source/core/assets/images/turret01.png delete mode 100644 source/core/assets/images/turret_body_idle.atlas delete mode 100644 source/core/assets/images/turret_body_idle.png delete mode 100644 source/core/assets/images/turret_deploy.atlas delete mode 100644 source/core/assets/images/turret_deploy.png diff --git a/source/core/assets/images/turret01.atlas b/source/core/assets/images/turret01.atlas new file mode 100644 index 000000000..75082330c --- /dev/null +++ b/source/core/assets/images/turret01.atlas @@ -0,0 +1,160 @@ + +turret01.png +size: 256, 256 +format: RGBA8888 +filter: Nearest, Nearest +repeat: xy +deploy + rotate: false + xy: 20, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 140, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 20 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 200, 195 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 140, 81 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 80, 24 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +idle + rotate: false + xy: 140, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +idle + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 140, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 20 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/images/turret01.png b/source/core/assets/images/turret01.png new file mode 100644 index 0000000000000000000000000000000000000000..025f187079cc9837e23231c4a124f900c5a1adfb GIT binary patch literal 5490 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 diff --git a/source/core/assets/images/turret_deploy.atlas b/source/core/assets/images/turret_deploy.atlas deleted file mode 100644 index 2176c56f6..000000000 --- a/source/core/assets/images/turret_deploy.atlas +++ /dev/null @@ -1,83 +0,0 @@ - -turret_deploy.png -size: 256, 256 -format: RGBA8888 -filter: Nearest, Nearest -repeat: xy -1 - rotate: false - xy: 20, 134 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -2 - rotate: false - xy: 20, 20 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -3 - rotate: false - xy: 20, 77 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -4 - rotate: false - xy: 20, 191 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -5 - rotate: false - xy: 140, 191 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -6 - rotate: false - xy: 80, 191 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -7 - rotate: false - xy: 80, 77 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -8 - rotate: false - xy: 80, 134 - size: 40, 37 - orig: 40, 37 - offset: 0, 0 - index: -1 -fire1 - rotate: false - xy: 140, 138 - size: 35, 33 - orig: 35, 33 - offset: 0, 0 - index: -1 -fire2 - rotate: false - xy: 80, 24 - size: 35, 33 - orig: 35, 33 - offset: 0, 0 - index: -1 -fire3 - rotate: false - xy: 200, 195 - size: 35, 33 - orig: 35, 33 - offset: 0, 0 - index: -1 diff --git a/source/core/assets/images/turret_deploy.png b/source/core/assets/images/turret_deploy.png deleted file mode 100644 index 58ba60e8e29e287ab673e5a7cb5d161862530eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5102 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 Mb#uda`mRs@3$F|$(f|Me From 2cef54292a512673ccc185b14fb3e036062a8ad4 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Thu, 24 Aug 2023 23:11:44 +1000 Subject: [PATCH 29/33] More adjustments to animation and tower ai for troubleshooting. --- .../csse3200/game/areas/ForestGameArea.java | 17 +- .../components/tasks/TowerCombatTask.java | 10 +- .../game/components/tasks/TowerIdleTask.java | 25 +- .../tower/TowerAnimationController.java | 2 +- .../game/entities/factories/TowerFactory.java | 29 +- .../entities/factories/TowerFactoryTest.java | 309 +++++++++--------- 6 files changed, 210 insertions(+), 182 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 52c5ba4ec..5e4db0d27 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -41,6 +41,8 @@ public class ForestGameArea extends GameArea { "images/iso_grass_1.png", "images/iso_grass_2.png", "images/iso_grass_3.png", + "images/turret.png", + "images/turret01.png", "images/turret_deployed.png" }; private static final String[] forestTextureAtlases = { @@ -48,8 +50,7 @@ public class ForestGameArea extends GameArea { "images/ghost.atlas", "images/ghostKing.atlas", "images/turret.atlas", - "images/turret_deploy.atlas", - "images/turret_body_idle.atlas" + "images/turret01.atlas" }; private static final String[] forestSounds = {"sounds/Impact4.ogg"}; private static final String backgroundMusic = "sounds/BGM_03_mp3.mp3"; @@ -84,7 +85,7 @@ public void create() { spawnWeaponTower(); -// playMusic(); +// playMusic(); // This music is gonna give me nightmares } private void displayUI() { @@ -164,11 +165,11 @@ private void spawnWeaponTower() { GridPoint2 minPos = new GridPoint2(0, 0); GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); -// for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { - Entity weaponTower = TowerFactory.createWeaponTower(); - spawnEntityAt(weaponTower, randomPos, true, true); -// } + for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { + GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); + Entity weaponTower = TowerFactory.createWeaponTower(); + spawnEntityAt(weaponTower, randomPos, true, true); + } } private void playMusic() { 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 ac7d5e17c..e80771d13 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 @@ -30,7 +30,6 @@ public class TowerCombatTask extends DefaultTask implements PriorityTask { public TowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; -// this.towerPosition = this.owner.getEntity().getCenterPosition(); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); physics = ServiceLocator.getPhysicsService().getPhysics(); debugRenderer = ServiceLocator.getRenderService().getDebug(); @@ -41,7 +40,7 @@ public TowerCombatTask(int priority, float maxRange) { public void start() { super.start(); this.towerPosition = owner.getEntity().getCenterPosition(); - owner.getEntity().getEvents().trigger("firingStart"); + owner.getEntity().getEvents().trigger("deployStart"); } @Override @@ -66,11 +65,13 @@ public int getPriority() { if (isTargetVisible()) { return getActivePriority(); } + status = Status.FINISHED; return getInactivePriority(); } private float getDistanceToTarget() { - if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.OBSTACLE, hit)) { + // TODO change layer to detect + if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.PLAYER, hit)) { return towerPosition.dst(hit.point.x, hit.point.y); }; return -1; @@ -95,7 +96,8 @@ private int getInactivePriority() { private boolean isTargetVisible() { // If there is an obstacle in the path to the max range point, mobs visible. - if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.NPC, hit)) { + // TODO change layer to detect + if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.PLAYER, hit)) { debugRenderer.drawLine(towerPosition, hit.point); return true; } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java index 96414c5d7..99a3a472a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java @@ -21,9 +21,9 @@ */ public class TowerIdleTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private static final float SCAN_RANGE = 500; - private static final int ACTIVE_PRIORITY = 0; - private static final int INACTIVE_PRIORITY = -1; + private static final float SCAN_RANGE = 50; + private static final int ACTIVE_PRIORITY = 1; + private static final int INACTIVE_PRIORITY = 0; private final GameTime timeSource; private final float interval; private long endTime; @@ -48,6 +48,7 @@ public TowerIdleTask(float interval) { @Override public void start() { super.start(); + owner.getEntity().getEvents().trigger("idleStart"); endTime = timeSource.getTime() + (int)(this.interval * 1000); } @@ -55,10 +56,12 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { if (isTargetVisible()) { - owner.getEntity().getEvents().trigger("deployStart"); +// owner.getEntity().getEvents().trigger("deployStart"); + TowerCombatTask combatTask = new TowerCombatTask(ACTIVE_PRIORITY + 2, SCAN_RANGE - 10); + combatTask.create(owner); logger.debug("Idle Task update function: Detected a target!"); } - status = Status.FINISHED; +// status = Status.INACTIVE; } } @@ -71,7 +74,8 @@ private boolean isTargetVisible() { // If there is an obstacle in the path to the end of the tower scan range // must be mobs present. - if (physics.raycast(from, to, PhysicsLayer.NPC, hit)) { + // TODO change layer to detect + if (physics.raycast(from, to, PhysicsLayer.PLAYER, hit)) { debugRenderer.drawLine(from, hit.point); return true; } @@ -81,11 +85,10 @@ private boolean isTargetVisible() { @Override public int getPriority() { - if (status == Status.ACTIVE) { - return getActivePriority(); - } - - return getInactivePriority(); +// if (status == Status.ACTIVE) { +// return getActivePriority(); +// } + return getActivePriority(); } public int getActivePriority() { diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java index 7e24bfaf0..07f9dcee2 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java @@ -15,8 +15,8 @@ public void create() { super.create(); animator = this.entity.getComponent(AnimationRenderComponent.class); entity.getEvents().addListener("idleStart", this::animateIdle); - entity.getEvents().addListener("deployStart", this::animateDeploy); entity.getEvents().addListener("stowStart", this::animateStow); + entity.getEvents().addListener("deployStart", this::animateDeploy); entity.getEvents().addListener("firingStart", this::animateFiring); } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 7647f5a46..1dbd4a01b 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -1,6 +1,7 @@ package com.csse3200.game.entities.factories; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; @@ -10,6 +11,7 @@ import com.csse3200.game.components.CostComponent; import com.csse3200.game.components.tasks.TowerCombatTask; import com.csse3200.game.components.tasks.TowerIdleTask; +import com.csse3200.game.components.tower.TowerAnimationController; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.configs.WallTowerConfig; import com.csse3200.game.physics.PhysicsLayer; @@ -33,7 +35,7 @@ public class TowerFactory { private static final int WEAPON_SCAN_INTERVAL = 1; private static final int COMBAT_TASK_PRIORITY = 2; - public static final int WEAPON_TOWER_MAX_RANGE = 500; + public static final int WEAPON_TOWER_MAX_RANGE = 40; private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); @@ -48,7 +50,6 @@ public static Entity createWallTower() { .addComponent(new CostComponent(config.cost)); return wall; - } /** @@ -60,26 +61,30 @@ public static Entity createWeaponTower() { Entity weapon = createBaseTower(); WeaponTowerConfig config = configs.weapon; -//// TODO: uncomment once tasks are finalised - will break build if included before +// TODO: uncomment once tasks are finalised - will break build if included before AITaskComponent aiTaskComponent = new AITaskComponent() - .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)) - .addTask(new TowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); -// -// // TODO: uncomment once animations are finalised - will break build if included before + .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)); +// .addTask(new TowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); + + // TODO: uncomment once animations are finalised - will break build if included before AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() - .getAsset("images/turret.atlas", TextureAtlas.class)); - animator.addAnimation("idle", 0.5f, Animation.PlayMode.LOOP); - animator.addAnimation("stow", 0.3f, Animation.PlayMode.NORMAL); + .getAsset("images/turret01.atlas", TextureAtlas.class)); + animator.addAnimation("idle", 0.3f, Animation.PlayMode.LOOP); + animator.addAnimation("stow", 0.2f, Animation.PlayMode.NORMAL); animator.addAnimation("deploy", 0.2f, Animation.PlayMode.REVERSED); - animator.addAnimation("firing", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("firing", 0.1f, Animation.PlayMode.LOOP); weapon .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(new CostComponent(config.cost)) .addComponent(aiTaskComponent) - .addComponent(animator); + .addComponent(animator) + .addComponent(new TowerAnimationController()); + +// weapon.getComponent(AnimationRenderComponent.class).scaleEntity(); + return weapon; } diff --git a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java index bc723cbc3..752dbaee1 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java @@ -1,146 +1,163 @@ -package com.csse3200.game.entities.factories; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -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.TouchAttackComponent; -import com.csse3200.game.entities.Entity; -import com.csse3200.game.extensions.GameExtension; -import com.csse3200.game.physics.PhysicsService; -import com.csse3200.game.physics.components.ColliderComponent; -import com.csse3200.game.physics.components.HitboxComponent; -import com.csse3200.game.physics.components.PhysicsComponent; -import com.csse3200.game.services.GameTime; -import com.csse3200.game.services.ServiceLocator; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@ExtendWith(GameExtension.class) -public class TowerFactoryTest { - - private Entity baseTower; - private Entity weaponTower; - private Entity wallTower; - - @BeforeEach - public void setUp() { - GameTime gameTime = mock(GameTime.class); - when(gameTime.getDeltaTime()).thenReturn(0.02f); - ServiceLocator.registerTimeSource(gameTime); - ServiceLocator.registerPhysicsService(new PhysicsService()); - baseTower = TowerFactory.createBaseTower(); - weaponTower = TowerFactory.createWeaponTower(); - wallTower = TowerFactory.createWallTower(); - } - - @Test - public void testCreateBaseTowerNotNull() { - - assertNotNull(baseTower, "Base tower should not be null"); - assertNotNull(weaponTower, "Weaponry tower should not be null"); - assertNotNull(wallTower, "Wall tower should not be null"); - } - - @Test - public void testCreateBaseTowerHasColliderComponent() { - assertNotNull(baseTower.getComponent(ColliderComponent.class), - "Base tower should have ColliderComponent"); - assertNotNull(weaponTower.getComponent(ColliderComponent.class), - "Weaponry tower should have ColliderComponent"); - assertNotNull(wallTower.getComponent(ColliderComponent.class), - "Wall tower should have ColliderComponent"); - } - - @Test - public void testCreateBaseTowerHasHitboxComponent() { - assertNotNull(baseTower.getComponent(HitboxComponent.class), - "Base tower should have HitboxComponent"); - assertNotNull(weaponTower.getComponent(HitboxComponent.class), - "Weaponry tower should have HitboxComponent"); - assertNotNull(wallTower.getComponent(HitboxComponent.class), - "Wall tower should have HitboxComponent"); - } - - @Test - public void testCreateBaseTowerHasPhysicsComponent() { - assertNotNull(baseTower.getComponent(PhysicsComponent.class), - "Base tower should have PhysicsComponent"); - assertNotNull(weaponTower.getComponent(PhysicsComponent.class), - "Weaponry tower should have PhysicsComponent"); - assertNotNull(wallTower.getComponent(PhysicsComponent.class), - "Wall tower should have PhysicsComponent"); - } - - @Test - public void testCreateBaseTowerPhysicsComponentStaticBody() { - PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); - PhysicsComponent physicsComponent1 = weaponTower.getComponent(PhysicsComponent.class); - PhysicsComponent physicsComponent2 = wallTower.getComponent(PhysicsComponent.class); - - assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, - "PhysicsComponent should be of type StaticBody"); - assertTrue(physicsComponent1.getBody().getType() == BodyType.StaticBody, - "PhysicsComponent1 should be of type StaticBody"); - assertTrue(physicsComponent2.getBody().getType() == BodyType.StaticBody, - "PhysicsComponent2 should be of type StaticBody"); - } - - @Test - public void testWeaponTowerCombatStatsComponentAndCostComponent() { - - assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getHealth() == 10, - "Health should be 10"); - assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 10, - "BaseAttack should be 10"); - assertTrue(weaponTower.getComponent(CostComponent.class).getCost() == 10, - "Cost should be 10"); - - } - - @Test - public void testWallTowerCombatStatsComponentAndCostComponent() { - - assertTrue(wallTower.getComponent(CombatStatsComponent.class).getHealth() == 20, - "Health should be 20"); - assertTrue(wallTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 0, - "BaseAttack should be 0"); - assertTrue(wallTower.getComponent(CostComponent.class).getCost() == 5, - "Cost should be 5"); - - } - - @Test - public void testAttackerCollisionWithWall() { - Entity attacker = createAttacker(wallTower.getComponent(HitboxComponent.class).getLayer()); - - wallTower.setPosition(10f,10f); - attacker.setPosition(10f,10f); - wallTower.create(); - - assertEquals(20, wallTower.getComponent(CombatStatsComponent.class).getHealth()); - - ServiceLocator.getPhysicsService().getPhysics().update(); - - assertEquals(10, wallTower.getComponent(CombatStatsComponent.class).getHealth()); - - } - - Entity createAttacker(short targetLayer) { - Entity entity = - new Entity() - .addComponent(new TouchAttackComponent(targetLayer)) - .addComponent(new CombatStatsComponent(0, 10)) - .addComponent(new PhysicsComponent()) - .addComponent(new HitboxComponent()); - entity.create(); - return entity; - } -} - - +//package com.csse3200.game.entities.factories; +// +//import static org.junit.jupiter.api.Assertions.*; +//import static org.mockito.Mockito.mock; +//import static org.mockito.Mockito.when; +// +//import com.badlogic.gdx.assets.AssetManager; +//import com.badlogic.gdx.graphics.g2d.TextureAtlas; +//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.TouchAttackComponent; +//import com.csse3200.game.entities.Entity; +//import com.csse3200.game.extensions.GameExtension; +//import com.csse3200.game.physics.PhysicsService; +//import com.csse3200.game.physics.components.ColliderComponent; +//import com.csse3200.game.physics.components.HitboxComponent; +//import com.csse3200.game.physics.components.PhysicsComponent; +//import com.csse3200.game.rendering.DebugRenderer; +//import com.csse3200.game.rendering.RenderService; +//import com.csse3200.game.services.GameTime; +//import com.csse3200.game.services.ResourceService; +//import com.csse3200.game.services.ServiceLocator; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Test; +//import org.junit.jupiter.api.extension.ExtendWith; +//import org.mockito.Mock; +// +//import java.security.Provider; +// +//@ExtendWith(GameExtension.class) +//public class TowerFactoryTest { +// +// private Entity baseTower; +// private Entity weaponTower; +// private Entity wallTower; +// private String[] texture = {"images/turret_deployed.png", "images/turret01.png"}; +// private String[] atlas = {"images/turret01.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.loadTextures(texture); +// resourceService.loadTextureAtlases(atlas); +// ServiceLocator.getResourceService() +// .getAsset("images/turret01.atlas", TextureAtlas.class); +// baseTower = TowerFactory.createBaseTower(); +// weaponTower = TowerFactory.createWeaponTower(); +// wallTower = TowerFactory.createWallTower(); +// } +// +// @Test +// public void testCreateBaseTowerNotNull() { +// +// assertNotNull(baseTower, "Base tower should not be null"); +// assertNotNull(weaponTower, "Weaponry tower should not be null"); +// assertNotNull(wallTower, "Wall tower should not be null"); +// } +// +// @Test +// public void testCreateBaseTowerHasColliderComponent() { +// assertNotNull(baseTower.getComponent(ColliderComponent.class), +// "Base tower should have ColliderComponent"); +// assertNotNull(weaponTower.getComponent(ColliderComponent.class), +// "Weaponry tower should have ColliderComponent"); +// assertNotNull(wallTower.getComponent(ColliderComponent.class), +// "Wall tower should have ColliderComponent"); +// } +// +// @Test +// public void testCreateBaseTowerHasHitboxComponent() { +// assertNotNull(baseTower.getComponent(HitboxComponent.class), +// "Base tower should have HitboxComponent"); +// assertNotNull(weaponTower.getComponent(HitboxComponent.class), +// "Weaponry tower should have HitboxComponent"); +// assertNotNull(wallTower.getComponent(HitboxComponent.class), +// "Wall tower should have HitboxComponent"); +// } +// +// @Test +// public void testCreateBaseTowerHasPhysicsComponent() { +// assertNotNull(baseTower.getComponent(PhysicsComponent.class), +// "Base tower should have PhysicsComponent"); +// assertNotNull(weaponTower.getComponent(PhysicsComponent.class), +// "Weaponry tower should have PhysicsComponent"); +// assertNotNull(wallTower.getComponent(PhysicsComponent.class), +// "Wall tower should have PhysicsComponent"); +// } +// +// @Test +// public void testCreateBaseTowerPhysicsComponentStaticBody() { +// PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); +// PhysicsComponent physicsComponent1 = weaponTower.getComponent(PhysicsComponent.class); +// PhysicsComponent physicsComponent2 = wallTower.getComponent(PhysicsComponent.class); +// +// assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, +// "PhysicsComponent should be of type StaticBody"); +// assertTrue(physicsComponent1.getBody().getType() == BodyType.StaticBody, +// "PhysicsComponent1 should be of type StaticBody"); +// assertTrue(physicsComponent2.getBody().getType() == BodyType.StaticBody, +// "PhysicsComponent2 should be of type StaticBody"); +// } +// +// @Test +// public void testWeaponTowerCombatStatsComponentAndCostComponent() { +// +// assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getHealth() == 10, +// "Health should be 10"); +// assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 10, +// "BaseAttack should be 10"); +// assertTrue(weaponTower.getComponent(CostComponent.class).getCost() == 10, +// "Cost should be 10"); +// +// } +// +// @Test +// public void testWallTowerCombatStatsComponentAndCostComponent() { +// +// assertTrue(wallTower.getComponent(CombatStatsComponent.class).getHealth() == 20, +// "Health should be 20"); +// assertTrue(wallTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 0, +// "BaseAttack should be 0"); +// assertTrue(wallTower.getComponent(CostComponent.class).getCost() == 5, +// "Cost should be 5"); +// +// } +// +// @Test +// public void testAttackerCollisionWithWall() { +// Entity attacker = createAttacker(wallTower.getComponent(HitboxComponent.class).getLayer()); +// +// wallTower.setPosition(10f,10f); +// attacker.setPosition(10f,10f); +// wallTower.create(); +// +// assertEquals(20, wallTower.getComponent(CombatStatsComponent.class).getHealth()); +// +// ServiceLocator.getPhysicsService().getPhysics().update(); +// +// assertEquals(10, wallTower.getComponent(CombatStatsComponent.class).getHealth()); +// +// } +// +// Entity createAttacker(short targetLayer) { +// Entity entity = +// new Entity() +// .addComponent(new TouchAttackComponent(targetLayer)) +// .addComponent(new CombatStatsComponent(0, 10)) +// .addComponent(new PhysicsComponent()) +// .addComponent(new HitboxComponent()); +// entity.create(); +// return entity; +// } +//} +// +// From 4fe7ac67a9bce104a1023a4034efe351fc04a9ea Mon Sep 17 00:00:00 2001 From: MajorDzaster Date: Fri, 25 Aug 2023 09:42:46 +1000 Subject: [PATCH 30/33] Fixed bug in PopupMenuComponent that caused its override method to be ignored in lieu of the original. --- .../popupmenu/PopupMenuInputComponent.java | 14 ++++++++- .../PopupMenuInputComponentTest.java | 30 +++++++------------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java index 25b931bdf..29bba5619 100644 --- a/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java +++ b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java @@ -20,9 +20,9 @@ public class PopupMenuInputComponent extends InputComponent{ // Note: will need to change constructor's priority when merging with other // branches that add other input components. /** + * Triggers "popupEvent" when the mouse is clicked. * * @return whether the input was processed - * @see InputProcessor#keyDown(int) */ @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { @@ -30,4 +30,16 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { entity.getEvents().trigger("popupEvent"); return true; } + + /** + * Triggers "popupEvent" when the mouse is clicked. + * + * @return whether the input was processed + */ + @Override + public boolean touchDown(float screenX, float screenY, int pointer, int button) { + System.out.println(9); + entity.getEvents().trigger("popupEvent"); + return true; + } } diff --git a/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java b/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java index 0f9bc21c3..9acd1bf7f 100644 --- a/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/popupmenu/PopupMenuInputComponentTest.java @@ -14,28 +14,18 @@ @ExtendWith(GameExtension.class) class PopupMenuInputComponentTest { - @Test - void handlesTouchDownNoEntity(){ - EventHandler handler = new EventHandler(); - EventListener0 listener = mock(EventListener0.class); - handler.addListener("popupEvent", listener); - PopupMenuInputComponent popupMenuInputComponent = spy(PopupMenuInputComponent.class); - assertFalse(popupMenuInputComponent.touchDown(5f, 6f, 7, 8)); - verify(listener, times(0)).handle(); - } - @Test void handlesTouchDownEntityIncluded(){ -// EventListener0 listener = mock(EventListener0.class); -// Entity entity = new Entity(); -// InputService inputService = new InputService(); -// ServiceLocator.registerInputService(inputService); + EventListener0 listener = mock(EventListener0.class); + Entity entity = new Entity(); + InputService inputService = new InputService(); + ServiceLocator.registerInputService(inputService); PopupMenuInputComponent popupMenuInputComponent = new PopupMenuInputComponent();//spy(PopupMenuInputComponent.class); -// entity.addComponent(popupMenuInputComponent); -// inputService.register(popupMenuInputComponent); -// entity.getEvents().addListener("popupEvent", listener); -// entity.create(); - assertTrue(popupMenuInputComponent.touchDown(5f, 6f, 7, 8)); -// verify(listener).handle(); + entity.addComponent(popupMenuInputComponent); + inputService.register(popupMenuInputComponent); + entity.getEvents().addListener("popupEvent", listener); + entity.create(); + assertTrue(popupMenuInputComponent.touchDown(5, 6, 7, 8)); + verify(listener).handle(); } } From f1d773a38b8efb1acd1037eeb78fa0a26fdba0fa Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Fri, 25 Aug 2023 12:04:14 +1000 Subject: [PATCH 31/33] fixed animation and event triggering in TowerCombatTask, removed TowerIdleTask from TowerFactory --- .../components/tasks/TowerCombatTask.java | 130 ++++++++++++++---- .../game/entities/factories/TowerFactory.java | 7 +- 2 files changed, 108 insertions(+), 29 deletions(-) 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 e80771d13..c2660f9e7 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 @@ -7,101 +7,181 @@ import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.raycast.RaycastHit; +import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * The TowerCombatTask runs the AI for the WeaponTower class. The tower will scan for targets in a straight line + * from its center point until a point at (x + maxRange, y), where x,y are the cooridinates of the tower's center + * position. This component should be added to an AiTaskComponent attached to the tower instance. + */ public class TowerCombatTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private final int priority; - private final float maxRange; + private final int priority; // The active priority this task will have + private final float maxRange; // the maximum detection range of the tower private Vector2 towerPosition = new Vector2(10,10); private final Vector2 maxRangePosition = new Vector2(); private final PhysicsEngine physics; + private final int SCAN_INTERVAL = 1; + private final GameTime timeSource; + private long endTime; private final DebugRenderer debugRenderer; private final RaycastHit hit = new RaycastHit(); + private final short TARGET = PhysicsLayer.NPC; // The type of targets that the tower will detect + + private enum STATE { + IDLE, DEPLOY, FIRING, STOW + } + private STATE towerState = STATE.IDLE; /** - * @param priority Task priority when chasing (0 when not chasing). - * @param maxRange Maximum effective range of the weapon tower. + * @param priority Task priority when targets are detected (0 when nothing detected). Must be a positive integer. + * @param maxRange Maximum effective range of the weapon tower. This determines the detection distance of targets */ public TowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); physics = ServiceLocator.getPhysicsService().getPhysics(); + timeSource = ServiceLocator.getTimeSource(); debugRenderer = ServiceLocator.getRenderService().getDebug(); logger.debug("TowerCombatTask started"); } + /** + * Starts the Task running, triggers the initial "idleStart" event. + */ @Override public void start() { super.start(); + // Set the tower's coordinates this.towerPosition = owner.getEntity().getCenterPosition(); - owner.getEntity().getEvents().trigger("deployStart"); + + // Default to idle mode + owner.getEntity().getEvents().trigger("idleStart"); + + endTime = timeSource.getTime() + (int)(SCAN_INTERVAL * 500); } + /** + * The update method is what is run every time the TaskRunner in the AiTaskComponent calls update(). + * triggers events depending on the presence or otherwise of targets in the detection range + */ @Override public void update() { - if (status == Status.ACTIVE) { - owner.getEntity().getEvents().trigger("firingStart"); - logger.debug("firing start event should have been triggered"); - } else { - owner.getEntity().getEvents().trigger("stowStart"); - logger.debug("stow start event should have been triggered"); + if (timeSource.getTime() >= endTime) { + updateTowerState(); + endTime = timeSource.getTime() + (int)(SCAN_INTERVAL * 1000); } } + public void updateTowerState() { + // configure tower state depending on target visibility + switch (towerState) { + case IDLE -> { + // targets detected in idle mode - start deployment + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger("deployStart"); + towerState = STATE.DEPLOY; + } + break; + } + case DEPLOY -> { + // currently deploying, +// if (owner.getEntity().getComponent(AnimationRenderComponent.class) + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger("firingStart"); + towerState = STATE.FIRING; + } + break; + } + case FIRING -> { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger("firingStart"); + } else { + towerState = STATE.STOW; + } + break; + } + case STOW -> { + if (isTargetVisible()) { + towerState = STATE.DEPLOY; + } else { + owner.getEntity().getEvents().trigger("idleStart"); + } + break; + } + } + } + /** + * For stopping the running task + */ @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger("stowStart"); } + /** + * Returns the current priority of the task. + * @return active priority value if targets detected, inactive priority otherwise + */ @Override public int getPriority() { if (isTargetVisible()) { return getActivePriority(); } - status = Status.FINISHED; return getInactivePriority(); } + /** + * Finds the distance to the nearest target, if any in range. + * @return (float) distance to nearest target, otherwise 0 if nothing in range. + */ private float getDistanceToTarget() { - // TODO change layer to detect - if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.PLAYER, hit)) { + if (physics.raycast(towerPosition, maxRangePosition, TARGET, hit)) { return towerPosition.dst(hit.point.x, hit.point.y); }; - return -1; + return 0; } + /** + * Fetches the active priority of the Task if a target is visible. + * @return (int) active priority if a target is visible, -1 otherwise + */ private int getActivePriority() { - float dst = getDistanceToTarget(); - if (dst > maxRange || !isTargetVisible()) { - return -1; // Too far, stop firing + if (!isTargetVisible()) { + return 0; // Too far, stop firing } return priority; } + /** + * Fetches the inactive priority of the Task if a target is not visible. + * @return (int) -1 if a target is not visible, active priority otherwise + */ private int getInactivePriority() { - float dst = getDistanceToTarget(); - if (dst < maxRange && isTargetVisible()) { + if (isTargetVisible()) { return priority; } - return -1; + return 0; } + /** + * Uses a raycast to determine whether there are any targets in detection range + * @return true if a target is visible, false otherwise + */ private boolean isTargetVisible() { // If there is an obstacle in the path to the max range point, mobs visible. - // TODO change layer to detect - if (physics.raycast(towerPosition, maxRangePosition, PhysicsLayer.PLAYER, hit)) { - debugRenderer.drawLine(towerPosition, hit.point); + if (physics.raycast(towerPosition, maxRangePosition, TARGET, hit)) { return true; } - debugRenderer.drawLine(towerPosition, maxRangePosition); return false; } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 1dbd4a01b..8b7c0985e 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -61,12 +61,11 @@ public static Entity createWeaponTower() { Entity weapon = createBaseTower(); WeaponTowerConfig config = configs.weapon; -// TODO: uncomment once tasks are finalised - will break build if included before + // AiTaskComponent will run the tower task which carries out detection of targets and trigger events AITaskComponent aiTaskComponent = new AITaskComponent() - .addTask(new TowerIdleTask(WEAPON_SCAN_INTERVAL)); -// .addTask(new TowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); + .addTask(new TowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); - // TODO: uncomment once animations are finalised - will break build if included before + // Contains all the animations that the tower will have AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() From b44a7833f6fab5724a75f71c3adc250fb23a177c Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Fri, 25 Aug 2023 12:19:04 +1000 Subject: [PATCH 32/33] fixed TowerFactory JUnit test 'asset not loaded' error --- source/core/assets/test/files/turret01.atlas | 160 +++++++++ source/core/assets/test/files/turret01.png | Bin 0 -> 5490 bytes .../assets/test/files/turret_deployed.png | Bin 0 -> 3438 bytes .../game/components/tasks/TowerIdleTask.java | 11 +- .../entities/factories/TowerFactoryTest.java | 327 +++++++++--------- 5 files changed, 330 insertions(+), 168 deletions(-) create mode 100644 source/core/assets/test/files/turret01.atlas create mode 100644 source/core/assets/test/files/turret01.png create mode 100644 source/core/assets/test/files/turret_deployed.png diff --git a/source/core/assets/test/files/turret01.atlas b/source/core/assets/test/files/turret01.atlas new file mode 100644 index 000000000..75082330c --- /dev/null +++ b/source/core/assets/test/files/turret01.atlas @@ -0,0 +1,160 @@ + +turret01.png +size: 256, 256 +format: RGBA8888 +filter: Nearest, Nearest +repeat: xy +deploy + rotate: false + xy: 20, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 140, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 20 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 80, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 200, 195 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 140, 81 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +firing + rotate: false + xy: 80, 24 + size: 35, 33 + orig: 35, 33 + offset: 0, 0 + index: -1 +idle + rotate: false + xy: 140, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +idle + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +deploy + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +default + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 140, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 20 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 77 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 80, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 191 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 +stow + rotate: false + xy: 20, 134 + size: 40, 37 + orig: 40, 37 + offset: 0, 0 + index: -1 \ No newline at end of file diff --git a/source/core/assets/test/files/turret01.png b/source/core/assets/test/files/turret01.png new file mode 100644 index 0000000000000000000000000000000000000000..025f187079cc9837e23231c4a124f900c5a1adfb GIT binary patch literal 5490 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 Q?EnA(07*qoM6N<$f>}|P-~a#s literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java index 99a3a472a..636f079e3 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java @@ -21,7 +21,7 @@ */ public class TowerIdleTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); - private static final float SCAN_RANGE = 50; + private static final float SCAN_RANGE = 100; private static final int ACTIVE_PRIORITY = 1; private static final int INACTIVE_PRIORITY = 0; private final GameTime timeSource; @@ -31,6 +31,8 @@ public class TowerIdleTask extends DefaultTask implements PriorityTask { private final DebugRenderer debugRenderer; private final RaycastHit hit = new RaycastHit(); + private final short TARGET = PhysicsLayer.NPC; + /** * @param interval time between scanning for mobs, in seconds. */ @@ -61,7 +63,6 @@ public void update() { combatTask.create(owner); logger.debug("Idle Task update function: Detected a target!"); } -// status = Status.INACTIVE; } } @@ -75,11 +76,11 @@ private boolean isTargetVisible() { // If there is an obstacle in the path to the end of the tower scan range // must be mobs present. // TODO change layer to detect - if (physics.raycast(from, to, PhysicsLayer.PLAYER, hit)) { - debugRenderer.drawLine(from, hit.point); + if (physics.raycast(from, to, TARGET, hit)) { +// debugRenderer.drawLine(from, hit.point); return true; } - debugRenderer.drawLine(from, to); +// debugRenderer.drawLine(from, to); return false; } diff --git a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java index 752dbaee1..eaec8f784 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java @@ -1,163 +1,164 @@ -//package com.csse3200.game.entities.factories; -// -//import static org.junit.jupiter.api.Assertions.*; -//import static org.mockito.Mockito.mock; -//import static org.mockito.Mockito.when; -// -//import com.badlogic.gdx.assets.AssetManager; -//import com.badlogic.gdx.graphics.g2d.TextureAtlas; -//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.TouchAttackComponent; -//import com.csse3200.game.entities.Entity; -//import com.csse3200.game.extensions.GameExtension; -//import com.csse3200.game.physics.PhysicsService; -//import com.csse3200.game.physics.components.ColliderComponent; -//import com.csse3200.game.physics.components.HitboxComponent; -//import com.csse3200.game.physics.components.PhysicsComponent; -//import com.csse3200.game.rendering.DebugRenderer; -//import com.csse3200.game.rendering.RenderService; -//import com.csse3200.game.services.GameTime; -//import com.csse3200.game.services.ResourceService; -//import com.csse3200.game.services.ServiceLocator; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.Mock; -// -//import java.security.Provider; -// -//@ExtendWith(GameExtension.class) -//public class TowerFactoryTest { -// -// private Entity baseTower; -// private Entity weaponTower; -// private Entity wallTower; -// private String[] texture = {"images/turret_deployed.png", "images/turret01.png"}; -// private String[] atlas = {"images/turret01.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.loadTextures(texture); -// resourceService.loadTextureAtlases(atlas); -// ServiceLocator.getResourceService() -// .getAsset("images/turret01.atlas", TextureAtlas.class); -// baseTower = TowerFactory.createBaseTower(); -// weaponTower = TowerFactory.createWeaponTower(); -// wallTower = TowerFactory.createWallTower(); -// } -// -// @Test -// public void testCreateBaseTowerNotNull() { -// -// assertNotNull(baseTower, "Base tower should not be null"); -// assertNotNull(weaponTower, "Weaponry tower should not be null"); -// assertNotNull(wallTower, "Wall tower should not be null"); -// } -// -// @Test -// public void testCreateBaseTowerHasColliderComponent() { -// assertNotNull(baseTower.getComponent(ColliderComponent.class), -// "Base tower should have ColliderComponent"); -// assertNotNull(weaponTower.getComponent(ColliderComponent.class), -// "Weaponry tower should have ColliderComponent"); -// assertNotNull(wallTower.getComponent(ColliderComponent.class), -// "Wall tower should have ColliderComponent"); -// } -// -// @Test -// public void testCreateBaseTowerHasHitboxComponent() { -// assertNotNull(baseTower.getComponent(HitboxComponent.class), -// "Base tower should have HitboxComponent"); -// assertNotNull(weaponTower.getComponent(HitboxComponent.class), -// "Weaponry tower should have HitboxComponent"); -// assertNotNull(wallTower.getComponent(HitboxComponent.class), -// "Wall tower should have HitboxComponent"); -// } -// -// @Test -// public void testCreateBaseTowerHasPhysicsComponent() { -// assertNotNull(baseTower.getComponent(PhysicsComponent.class), -// "Base tower should have PhysicsComponent"); -// assertNotNull(weaponTower.getComponent(PhysicsComponent.class), -// "Weaponry tower should have PhysicsComponent"); -// assertNotNull(wallTower.getComponent(PhysicsComponent.class), -// "Wall tower should have PhysicsComponent"); -// } -// -// @Test -// public void testCreateBaseTowerPhysicsComponentStaticBody() { -// PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); -// PhysicsComponent physicsComponent1 = weaponTower.getComponent(PhysicsComponent.class); -// PhysicsComponent physicsComponent2 = wallTower.getComponent(PhysicsComponent.class); -// -// assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, -// "PhysicsComponent should be of type StaticBody"); -// assertTrue(physicsComponent1.getBody().getType() == BodyType.StaticBody, -// "PhysicsComponent1 should be of type StaticBody"); -// assertTrue(physicsComponent2.getBody().getType() == BodyType.StaticBody, -// "PhysicsComponent2 should be of type StaticBody"); -// } -// -// @Test -// public void testWeaponTowerCombatStatsComponentAndCostComponent() { -// -// assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getHealth() == 10, -// "Health should be 10"); -// assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 10, -// "BaseAttack should be 10"); -// assertTrue(weaponTower.getComponent(CostComponent.class).getCost() == 10, -// "Cost should be 10"); -// -// } -// -// @Test -// public void testWallTowerCombatStatsComponentAndCostComponent() { -// -// assertTrue(wallTower.getComponent(CombatStatsComponent.class).getHealth() == 20, -// "Health should be 20"); -// assertTrue(wallTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 0, -// "BaseAttack should be 0"); -// assertTrue(wallTower.getComponent(CostComponent.class).getCost() == 5, -// "Cost should be 5"); -// -// } -// -// @Test -// public void testAttackerCollisionWithWall() { -// Entity attacker = createAttacker(wallTower.getComponent(HitboxComponent.class).getLayer()); -// -// wallTower.setPosition(10f,10f); -// attacker.setPosition(10f,10f); -// wallTower.create(); -// -// assertEquals(20, wallTower.getComponent(CombatStatsComponent.class).getHealth()); -// -// ServiceLocator.getPhysicsService().getPhysics().update(); -// -// assertEquals(10, wallTower.getComponent(CombatStatsComponent.class).getHealth()); -// -// } -// -// Entity createAttacker(short targetLayer) { -// Entity entity = -// new Entity() -// .addComponent(new TouchAttackComponent(targetLayer)) -// .addComponent(new CombatStatsComponent(0, 10)) -// .addComponent(new PhysicsComponent()) -// .addComponent(new HitboxComponent()); -// entity.create(); -// return entity; -// } -//} -// -// +package com.csse3200.game.entities.factories; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.badlogic.gdx.assets.AssetManager; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +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.TouchAttackComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.physics.components.ColliderComponent; +import com.csse3200.game.physics.components.HitboxComponent; +import com.csse3200.game.physics.components.PhysicsComponent; +import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ResourceService; +import com.csse3200.game.services.ServiceLocator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; + +import java.security.Provider; + +@ExtendWith(GameExtension.class) +public class TowerFactoryTest { + + private Entity baseTower; + private Entity weaponTower; + private Entity wallTower; + private String[] texture = {"images/turret_deployed.png", "images/turret01.png"}; + private String[] atlas = {"images/turret01.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.loadTextures(texture); + resourceService.loadTextureAtlases(atlas); + resourceService.loadAll(); + ServiceLocator.getResourceService() + .getAsset("images/turret01.atlas", TextureAtlas.class); + baseTower = TowerFactory.createBaseTower(); + weaponTower = TowerFactory.createWeaponTower(); + wallTower = TowerFactory.createWallTower(); + } + + @Test + public void testCreateBaseTowerNotNull() { + + assertNotNull(baseTower, "Base tower should not be null"); + assertNotNull(weaponTower, "Weaponry tower should not be null"); + assertNotNull(wallTower, "Wall tower should not be null"); + } + + @Test + public void testCreateBaseTowerHasColliderComponent() { + assertNotNull(baseTower.getComponent(ColliderComponent.class), + "Base tower should have ColliderComponent"); + assertNotNull(weaponTower.getComponent(ColliderComponent.class), + "Weaponry tower should have ColliderComponent"); + assertNotNull(wallTower.getComponent(ColliderComponent.class), + "Wall tower should have ColliderComponent"); + } + + @Test + public void testCreateBaseTowerHasHitboxComponent() { + assertNotNull(baseTower.getComponent(HitboxComponent.class), + "Base tower should have HitboxComponent"); + assertNotNull(weaponTower.getComponent(HitboxComponent.class), + "Weaponry tower should have HitboxComponent"); + assertNotNull(wallTower.getComponent(HitboxComponent.class), + "Wall tower should have HitboxComponent"); + } + + @Test + public void testCreateBaseTowerHasPhysicsComponent() { + assertNotNull(baseTower.getComponent(PhysicsComponent.class), + "Base tower should have PhysicsComponent"); + assertNotNull(weaponTower.getComponent(PhysicsComponent.class), + "Weaponry tower should have PhysicsComponent"); + assertNotNull(wallTower.getComponent(PhysicsComponent.class), + "Wall tower should have PhysicsComponent"); + } + + @Test + public void testCreateBaseTowerPhysicsComponentStaticBody() { + PhysicsComponent physicsComponent = baseTower.getComponent(PhysicsComponent.class); + PhysicsComponent physicsComponent1 = weaponTower.getComponent(PhysicsComponent.class); + PhysicsComponent physicsComponent2 = wallTower.getComponent(PhysicsComponent.class); + + assertTrue(physicsComponent.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent should be of type StaticBody"); + assertTrue(physicsComponent1.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent1 should be of type StaticBody"); + assertTrue(physicsComponent2.getBody().getType() == BodyType.StaticBody, + "PhysicsComponent2 should be of type StaticBody"); + } + + @Test + public void testWeaponTowerCombatStatsComponentAndCostComponent() { + + assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getHealth() == 10, + "Health should be 10"); + assertTrue(weaponTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 10, + "BaseAttack should be 10"); + assertTrue(weaponTower.getComponent(CostComponent.class).getCost() == 10, + "Cost should be 10"); + + } + + @Test + public void testWallTowerCombatStatsComponentAndCostComponent() { + + assertTrue(wallTower.getComponent(CombatStatsComponent.class).getHealth() == 20, + "Health should be 20"); + assertTrue(wallTower.getComponent(CombatStatsComponent.class).getBaseAttack() == 0, + "BaseAttack should be 0"); + assertTrue(wallTower.getComponent(CostComponent.class).getCost() == 5, + "Cost should be 5"); + + } + + @Test + public void testAttackerCollisionWithWall() { + Entity attacker = createAttacker(wallTower.getComponent(HitboxComponent.class).getLayer()); + + wallTower.setPosition(10f,10f); + attacker.setPosition(10f,10f); + wallTower.create(); + + assertEquals(20, wallTower.getComponent(CombatStatsComponent.class).getHealth()); + + ServiceLocator.getPhysicsService().getPhysics().update(); + + assertEquals(10, wallTower.getComponent(CombatStatsComponent.class).getHealth()); + + } + + Entity createAttacker(short targetLayer) { + Entity entity = + new Entity() + .addComponent(new TouchAttackComponent(targetLayer)) + .addComponent(new CombatStatsComponent(0, 10)) + .addComponent(new PhysicsComponent()) + .addComponent(new HitboxComponent()); + entity.create(); + return entity; + } +} + + From b2e61b868ab1677c176e6ac2e1a96b61057a2a85 Mon Sep 17 00:00:00 2001 From: Ahmad Abu-Aysha Date: Fri, 25 Aug 2023 13:33:18 +1000 Subject: [PATCH 33/33] updated comments --- .../csse3200/game/components/tasks/TowerIdleTask.java | 9 ++++++++- .../game/components/tower/TowerAnimationController.java | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java index 636f079e3..0120b1610 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerIdleTask.java @@ -18,6 +18,10 @@ * Task for the Tower Idle State - specifically for the * Weapon Tower Entity that can move between combat and * idle states. Scans for enemy mobs but does nothing else. + * + * ====================== CURRENTLY NOT IN USE ================================== + * This task may be modified for use in future features but is not required + * for current functionality */ public class TowerIdleTask extends DefaultTask implements PriorityTask { private static final Logger logger = LoggerFactory.getLogger(MovementTask.class); @@ -34,6 +38,8 @@ public class TowerIdleTask extends DefaultTask implements PriorityTask { private final short TARGET = PhysicsLayer.NPC; /** + * Instantiates a TowerIdleTask which scans for mobs at a certain + * time interval. * @param interval time between scanning for mobs, in seconds. */ public TowerIdleTask(float interval) { @@ -45,11 +51,12 @@ public TowerIdleTask(float interval) { } /** - * Start waiting from now until interval has passed. + * Start the Idle task - waiting from current game time until interval has passed. */ @Override public void start() { super.start(); + // Trigger the idle event owner.getEntity().getEvents().trigger("idleStart"); endTime = timeSource.getTime() + (int)(this.interval * 1000); } diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java index 07f9dcee2..cddb893be 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerAnimationController.java @@ -4,8 +4,8 @@ import com.csse3200.game.rendering.AnimationRenderComponent; /** - * This class listens to events relevant to a weapon tower state and plays the animation when one - * of the events is triggered. + * Listens for events relevant to a weapon tower state. + * Each event will trigger a certain animation */ public class TowerAnimationController extends Component { AnimationRenderComponent animator;