From 653114f0fffe1bc6d1f8ff7a1bf1f552bf21d406 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 13:12:46 +1000 Subject: [PATCH 01/49] Fixed posix bug where the WallTower.png had inconsitent naming --- .../images/towers/{wallTower.png => WallTower.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename source/core/assets/images/towers/{wallTower.png => WallTower.png} (100%) diff --git a/source/core/assets/images/towers/wallTower.png b/source/core/assets/images/towers/WallTower.png similarity index 100% rename from source/core/assets/images/towers/wallTower.png rename to source/core/assets/images/towers/WallTower.png From a1c6d78c6cb07e2236219a7d6f5c8a795744733a Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 13:21:48 +1000 Subject: [PATCH 02/49] Cleared forest game area so that we have an empty map to work on --- .../csse3200/game/areas/ForestGameArea.java | 24 +++++++++---------- .../game/entities/factories/TowerFactory.java | 2 +- 2 files changed, 13 insertions(+), 13 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 3ed44061f..52ccc241e 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -89,7 +89,7 @@ public class ForestGameArea extends GameArea { "images/mobs/Hurt.png", "images/mobs/Idle.png", "images/mobs/rangeBossRight.png", - "images/towers/wallTower.png", + "images/towers/WallTower.png", "images/background/building2.png", "images/iso_grass_3.png", "images/terrain_use.png", @@ -256,17 +256,17 @@ public void create() { // Set up infrastructure for end game tracking player = spawnPlayer(); player.getEvents().addListener("spawnWave", this::spawnWave); - playMusic(); - spawnXenoGrunts(); - startWaveTimer(); - spawnScrap(); - spawnDeflectXenoGrunt(15, 5); - spawnSplittingXenoGrunt(15, 4); - spawnScrap(); - spawnTNTTower(); - spawnWeaponTower(); - spawnGapScanners(); - spawnDroidTower(); +// playMusic(); +// spawnXenoGrunts(); +// startWaveTimer(); +// spawnScrap(); +// spawnDeflectXenoGrunt(15, 5); +// spawnSplittingXenoGrunt(15, 4); +// spawnScrap(); +// spawnTNTTower(); +// spawnWeaponTower(); +// spawnGapScanners(); +// spawnDroidTower(); } 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 1341746fd..0e750647f 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 @@ -38,7 +38,7 @@ public class TowerFactory { private static final int TNT_TOWER_MAX_RANGE = 6; private static final int TNT_TOWER_RANGE = 6; private static final int TNT_KNOCK_BACK_FORCE = 10; - private static final String WALL_IMAGE = "images/towers/wallTower.png"; + private static final String WALL_IMAGE = "images/towers/WallTower.png"; private static final String RESOURCE_TOWER = "images/towers/mine_tower.png"; private static final String TURRET_ATLAS = "images/towers/turret01.atlas"; private static final String FIRE_TOWER_ATLAS = "images/towers/fire_tower_atlas.atlas"; From 4c7fd6ea8ae76af388edc69232d68889e1e40fdf Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 16:23:19 +1000 Subject: [PATCH 03/49] Added new atlas file for when an engineer is selected. Added the structure for an EngineerInputComponent to deal with mouse clicks --- .../images/engineers/engineer_outline.atlas | 391 ++++++++++++++++++ .../images/engineers/engineer_outline.png | Bin 0 -> 38831 bytes .../game/input/EngineerInputComponent.java | 2 + 3 files changed, 393 insertions(+) create mode 100644 source/core/assets/images/engineers/engineer_outline.atlas create mode 100644 source/core/assets/images/engineers/engineer_outline.png create mode 100644 source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java diff --git a/source/core/assets/images/engineers/engineer_outline.atlas b/source/core/assets/images/engineers/engineer_outline.atlas new file mode 100644 index 000000000..90e825708 --- /dev/null +++ b/source/core/assets/images/engineers/engineer_outline.atlas @@ -0,0 +1,391 @@ + +engineer_outline.png +size: 2048, 128 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +death + rotate: false + xy: 503, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 6 +death + rotate: false + xy: 902, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +death + rotate: false + xy: 1358, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 5 +death + rotate: false + xy: 1814, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +death + rotate: false + xy: 454, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +death + rotate: false + xy: 796, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +firing_auto + rotate: false + xy: 25, 80 + size: 52, 31 + orig: 52, 31 + offset: 0, 0 + index: 2 +firing_auto + rotate: false + xy: 25, 44 + size: 52, 31 + orig: 52, 31 + offset: 0, 0 + index: 4 +firing_auto + rotate: false + xy: 102, 80 + size: 52, 31 + orig: 52, 31 + offset: 0, 0 + index: 1 +firing_auto + rotate: false + xy: 25, 8 + size: 52, 31 + orig: 52, 31 + offset: 0, 0 + index: 3 +firing_single + rotate: false + xy: 102, 42 + size: 52, 33 + orig: 45, 33 + offset: 0, 0 + index: 2 +firing_single + rotate: false + xy: 179, 78 + size: 52, 33 + orig: 45, 33 + offset: 0, 0 + index: 4 +firing_single + rotate: false + xy: 249, 78 + size: 52, 33 + orig: 45, 33 + offset: 0, 0 + index: 1 +firing_single + rotate: false + xy: 319, 78 + size: 52, 33 + orig: 45, 33 + offset: 0, 0 + index: 3 +firing_single + rotate: false + xy: 343, 40 + size: 52, 33 + orig: 29, 33 + offset: 0, 0 + index: 5 +hit + rotate: false + xy: 560, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +hit + rotate: false + xy: 1415, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +hit + rotate: false + xy: 511, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +idle_left + rotate: false + xy: 674, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +idle_left + rotate: false + xy: 1130, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +idle_left + rotate: false + xy: 1529, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +idle_left + rotate: false + xy: 102, 5 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +idle_right + rotate: false + xy: 1016, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +idle_right + rotate: false + xy: 1586, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +default + rotate: false + xy: 1928, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +idle_right + rotate: false + xy: 1928, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +idle_right + rotate: false + xy: 568, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +prep + rotate: false + xy: 343, 40 + size: 52, 33 + orig: 29, 33 + offset: 0, 0 + index: 4 +prep + rotate: false + xy: 853, 41 + size: 52, 33 + orig: 29, 33 + offset: 0, 0 + index: 1 +prep + rotate: false + xy: 907, 41 + size: 52, 33 + orig: 29, 33 + offset: 0, 0 + index: 3 +prep + rotate: false + xy: 961, 41 + size: 52, 33 + orig: 29, 33 + offset: 0, 0 + index: 2 +walk_left + rotate: false + xy: 446, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 6 +walk_left + rotate: false + xy: 845, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +walk_left + rotate: false + xy: 959, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 8 +walk_left + rotate: false + xy: 1301, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 5 +walk_left + rotate: false + xy: 1700, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +walk_left + rotate: false + xy: 1871, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 7 +walk_left + rotate: false + xy: 397, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +walk_left + rotate: false + xy: 739, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +walk_prep + rotate: false + xy: 389, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 8 +walk_prep + rotate: false + xy: 731, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 5 +walk_prep + rotate: false + xy: 1073, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +walk_prep + rotate: false + xy: 1244, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 7 +walk_prep + rotate: false + xy: 1643, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +walk_prep + rotate: false + xy: 1985, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +walk_prep + rotate: false + xy: 229, 41 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 6 +walk_prep + rotate: false + xy: 625, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +walk_right + rotate: false + xy: 617, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 2 +walk_right + rotate: false + xy: 788, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 7 +walk_right + rotate: false + xy: 1187, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 4 +walk_right + rotate: false + xy: 1472, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 1 +walk_right + rotate: false + xy: 1757, 79 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 6 +walk_right + rotate: false + xy: 172, 41 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 3 +walk_right + rotate: false + xy: 286, 41 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 8 +walk_right + rotate: false + xy: 682, 42 + size: 52, 32 + orig: 32, 32 + offset: 0, 0 + index: 5 diff --git a/source/core/assets/images/engineers/engineer_outline.png b/source/core/assets/images/engineers/engineer_outline.png new file mode 100644 index 0000000000000000000000000000000000000000..620f4cd24283358215583548bc045b00f4eba98d GIT binary patch literal 38831 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�j8Lyj#l>w%7I5TIU8X}dzRGGyW+dhLuEJdSn) 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 literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java new file mode 100644 index 000000000..fd90cf504 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -0,0 +1,2 @@ +package com.csse3200.game.input;public class EngineerInputComponent { +} From bc00c552b8006f099687a58863aaeb73ac0c3481 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 16:27:27 +1000 Subject: [PATCH 04/49] Made changes to engineer factory to clean up code for engineer select --- .../entities/factories/EngineerFactory.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java index 7bdd6396a..f0d8c4c3d 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java @@ -50,19 +50,8 @@ public static Entity createEngineer() { Entity engineer = createBaseHumanNPC(); BaseEntityConfig config = configs.engineer; - AnimationRenderComponent animator = new AnimationRenderComponent( - new TextureAtlas("images/engineers/engineer.atlas")); - animator.addAnimation("walk_left", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("walk_right", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("walk_prep", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("idle_right", 0.2f, Animation.PlayMode.LOOP); - animator.addAnimation("firing_auto", 0.05f, Animation.PlayMode.NORMAL); - animator.addAnimation("firing_single", 0.05f, Animation.PlayMode.NORMAL); - animator.addAnimation("prep", 0.05f, Animation.PlayMode.NORMAL); - animator.addAnimation("hit", 0.01f, Animation.PlayMode.NORMAL); - animator.addAnimation("death", 0.1f, Animation.PlayMode.NORMAL); - AITaskComponent aiComponent = new AITaskComponent(); + AnimationRenderComponent animator = createAnimationRenderComponent(); engineer .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) @@ -76,6 +65,21 @@ public static Entity createEngineer() { return engineer; } + private static AnimationRenderComponent createAnimationRenderComponent() { + AnimationRenderComponent animator = new AnimationRenderComponent( + new TextureAtlas("images/engineers/engineer.atlas")); + animator.addAnimation("walk_left", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("walk_right", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("walk_prep", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("idle_right", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("firing_auto", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("firing_single", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("prep", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("hit", 0.01f, Animation.PlayMode.NORMAL); + animator.addAnimation("death", 0.1f, Animation.PlayMode.NORMAL); + return animator; + } + /** * Creates a generic human npc to be used as a base entity by more specific NPC creation methods. * From b671be5b7dd8ec3f457e0dd7801683ab9099d845 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 16:56:39 +1000 Subject: [PATCH 05/49] Added remove component method to entity which takes a Component.class as input --- .../src/main/com/csse3200/game/entities/Entity.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/core/src/main/com/csse3200/game/entities/Entity.java b/source/core/src/main/com/csse3200/game/entities/Entity.java index 46d4ffda6..4373da4a9 100644 --- a/source/core/src/main/com/csse3200/game/entities/Entity.java +++ b/source/core/src/main/com/csse3200/game/entities/Entity.java @@ -206,6 +206,16 @@ public Entity addComponent(Component component) { return this; } + public void removeComponent(Class componentClass) { + ComponentType componentType = ComponentType.getFrom(componentClass); + int id = componentType.getId(); + + if (components.containsKey(id)) { + Component removedComponent = components.remove(id); + removedComponent.dispose(); + } + } + /** Dispose of the entity. This will dispose of all components on this entity. */ public void dispose() { for (Component component : createdComponents) { From 1bce796a7decac096fed45e285e89c7ae9e64752 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Thu, 28 Sep 2023 23:18:31 +1000 Subject: [PATCH 06/49] Added some touch functionality, current bug if you click on the engineer it disapears but still apears on the screen --- .../csse3200/game/areas/ForestGameArea.java | 4 ++ .../entities/factories/EngineerFactory.java | 8 +-- .../game/input/EngineerInputComponent.java | 49 ++++++++++++++++++- .../csse3200/game/screens/MainGameScreen.java | 17 ++++--- 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 52ccc241e..86fb45744 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -256,6 +256,10 @@ public void create() { // Set up infrastructure for end game tracking player = spawnPlayer(); player.getEvents().addListener("spawnWave", this::spawnWave); + + Entity engineer = EngineerFactory.createEngineer(); + spawnEntityAt(engineer, new GridPoint2(2, 4), true, true); + // playMusic(); // spawnXenoGrunts(); // startWaveTimer(); diff --git a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java index f0d8c4c3d..d18021210 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java @@ -51,7 +51,7 @@ public static Entity createEngineer() { BaseEntityConfig config = configs.engineer; AITaskComponent aiComponent = new AITaskComponent(); - AnimationRenderComponent animator = createAnimationRenderComponent(); + AnimationRenderComponent animator = createAnimationRenderComponent(false); engineer .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) @@ -65,9 +65,11 @@ public static Entity createEngineer() { return engineer; } - private static AnimationRenderComponent createAnimationRenderComponent() { + public static AnimationRenderComponent createAnimationRenderComponent(boolean isClicked) { + String atlasPath = isClicked ? "images/engineers/engineer_outline.atlas" + : "images/engineers/engineer.atlas"; AnimationRenderComponent animator = new AnimationRenderComponent( - new TextureAtlas("images/engineers/engineer.atlas")); + new TextureAtlas(atlasPath)); animator.addAnimation("walk_left", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("walk_right", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("walk_prep", 0.2f, Animation.PlayMode.LOOP); diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index fd90cf504..263d6f284 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -1,2 +1,49 @@ -package com.csse3200.game.input;public class EngineerInputComponent { +package com.csse3200.game.input; +import com.badlogic.gdx.Game; +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; +import com.csse3200.game.components.player.HumanAnimationController; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.csse3200.game.entities.factories.EngineerFactory; +import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EngineerInputComponent extends InputComponent { + + private static final Logger logger = LoggerFactory.getLogger(EngineerInputComponent.class); + private Game game; + private Camera camera; + private EntityService entityService; + + public EngineerInputComponent(Game game, Camera camera) { + this.game = game; + this.camera = camera; + this.entityService = ServiceLocator.getEntityService(); + } + + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + Vector3 worldCoordinates = new Vector3((float) screenX , (float) screenY, 0); + camera.unproject(worldCoordinates); + Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); + Entity engineer = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); + logger.info("Clicked entity: " + engineer); + + // Case when engineer is not clicked + if (engineer == null || engineer.getComponent(HumanAnimationController.class) == null) { + return false; + } + // Case when engineer is clicked + engineer.removeComponent(AnimationRenderComponent.class); + logger.info("Engineer has animation render component " + engineer.getComponent(AnimationRenderComponent.class)); + AnimationRenderComponent animator = EngineerFactory.createAnimationRenderComponent(true); + engineer.addComponent(animator); + logger.info("Engineer has animation render component " + engineer.getComponent(AnimationRenderComponent.class)); + + return true; + } + } diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index 4cadb1db3..13ad9eb18 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -1,6 +1,7 @@ package com.csse3200.game.screens; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; @@ -19,10 +20,7 @@ import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.RenderFactory; -import com.csse3200.game.input.DropInputComponent; -import com.csse3200.game.input.InputComponent; -import com.csse3200.game.input.InputDecorator; -import com.csse3200.game.input.InputService; +import com.csse3200.game.input.*; import com.csse3200.game.physics.PhysicsEngine; import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.rendering.RenderService; @@ -94,11 +92,16 @@ public MainGameScreen(GdxGame game) { renderer = RenderFactory.createRenderer(); renderer.getCamera().getEntity().setPosition(CAMERA_POSITION); renderer.getDebug().renderPhysicsWorld(physicsEngine.getWorld()); - InputComponent inputHandler = new DropInputComponent(renderer.getCamera().getCamera()); - ServiceLocator.getInputService().register(inputHandler); - ServiceLocator.getCurrencyService().getDisplay().setCamera(renderer.getCamera().getCamera()); + /* Input components */ + InputComponent dropInputHandler = new DropInputComponent(renderer.getCamera().getCamera()); + ServiceLocator.getInputService().register(dropInputHandler); + + InputComponent engineerInputHandler = new EngineerInputComponent(game, renderer.getCamera().getCamera()); + ServiceLocator.getInputService().register(engineerInputHandler); + + ServiceLocator.getCurrencyService().getDisplay().setCamera(renderer.getCamera().getCamera()); loadAssets(); createUI(); From 0c97c8478252edb15a4fb53e2ece222a925bca2a Mon Sep 17 00:00:00 2001 From: Nawal Date: Fri, 29 Sep 2023 22:18:44 +1000 Subject: [PATCH 07/49] Added outlined animations to Engineers, so when they are clicked an outline shows up. Also added a new constructor to AnimationRenderComponent that can take two atlas files. --- .../images/engineers/engineer_outline.atlas | 110 +++++++++--------- .../entities/factories/EngineerFactory.java | 20 +++- .../game/input/EngineerInputComponent.java | 17 ++- .../rendering/AnimationRenderComponent.java | 44 +++++-- .../entities/factories/TowerFactoryTest.java | 2 +- 5 files changed, 117 insertions(+), 76 deletions(-) diff --git a/source/core/assets/images/engineers/engineer_outline.atlas b/source/core/assets/images/engineers/engineer_outline.atlas index 90e825708..7ccef54b0 100644 --- a/source/core/assets/images/engineers/engineer_outline.atlas +++ b/source/core/assets/images/engineers/engineer_outline.atlas @@ -4,385 +4,385 @@ size: 2048, 128 format: RGBA8888 filter: Nearest, Nearest repeat: none -death +death_outline rotate: false xy: 503, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 6 -death +death_outline rotate: false xy: 902, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -death +death_outline rotate: false xy: 1358, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 5 -death +death_outline rotate: false xy: 1814, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -death +death_outline rotate: false xy: 454, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -death +death_outline rotate: false xy: 796, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -firing_auto +firing_auto_outline rotate: false xy: 25, 80 size: 52, 31 orig: 52, 31 offset: 0, 0 index: 2 -firing_auto +firing_auto_outline rotate: false xy: 25, 44 size: 52, 31 orig: 52, 31 offset: 0, 0 index: 4 -firing_auto +firing_auto_outline rotate: false xy: 102, 80 size: 52, 31 orig: 52, 31 offset: 0, 0 index: 1 -firing_auto +firing_auto_outline rotate: false xy: 25, 8 size: 52, 31 orig: 52, 31 offset: 0, 0 index: 3 -firing_single +firing_single_outline rotate: false xy: 102, 42 size: 52, 33 orig: 45, 33 offset: 0, 0 index: 2 -firing_single +firing_single_outline rotate: false xy: 179, 78 size: 52, 33 orig: 45, 33 offset: 0, 0 index: 4 -firing_single +firing_single_outline rotate: false xy: 249, 78 size: 52, 33 orig: 45, 33 offset: 0, 0 index: 1 -firing_single +firing_single_outline rotate: false xy: 319, 78 size: 52, 33 orig: 45, 33 offset: 0, 0 index: 3 -firing_single +firing_single_outline rotate: false xy: 343, 40 size: 52, 33 orig: 29, 33 offset: 0, 0 index: 5 -hit +hit_outline rotate: false xy: 560, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -hit +hit_outline rotate: false xy: 1415, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -hit +hit_outline rotate: false xy: 511, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -idle_left +idle_left_outline rotate: false xy: 674, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -idle_left +idle_left_outline rotate: false xy: 1130, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -idle_left +idle_left_outline rotate: false xy: 1529, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -idle_left +idle_left_outline rotate: false xy: 102, 5 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -idle_right +idle_right_outline rotate: false xy: 1016, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -idle_right +idle_right_outline rotate: false xy: 1586, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -default +default_outline rotate: false xy: 1928, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -idle_right +idle_right_outline rotate: false xy: 1928, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -idle_right +idle_right_outline rotate: false xy: 568, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -prep +prep_outline rotate: false xy: 343, 40 size: 52, 33 orig: 29, 33 offset: 0, 0 index: 4 -prep +prep_outline rotate: false xy: 853, 41 size: 52, 33 orig: 29, 33 offset: 0, 0 index: 1 -prep +prep_outline rotate: false xy: 907, 41 size: 52, 33 orig: 29, 33 offset: 0, 0 index: 3 -prep +prep_outline rotate: false xy: 961, 41 size: 52, 33 orig: 29, 33 offset: 0, 0 index: 2 -walk_left +walk_left_outline rotate: false xy: 446, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 6 -walk_left +walk_left_outline rotate: false xy: 845, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -walk_left +walk_left_outline rotate: false xy: 959, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 8 -walk_left +walk_left_outline rotate: false xy: 1301, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 5 -walk_left +walk_left_outline rotate: false xy: 1700, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -walk_left +walk_left_outline rotate: false xy: 1871, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 7 -walk_left +walk_left_outline rotate: false xy: 397, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -walk_left +walk_left_outline rotate: false xy: 739, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -walk_prep +walk_prep_outline rotate: false xy: 389, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 8 -walk_prep +walk_prep_outline rotate: false xy: 731, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 5 -walk_prep +walk_prep_outline rotate: false xy: 1073, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -walk_prep +walk_prep_outline rotate: false xy: 1244, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 7 -walk_prep +walk_prep_outline rotate: false xy: 1643, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -walk_prep +walk_prep_outline rotate: false xy: 1985, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -walk_prep +walk_prep_outline rotate: false xy: 229, 41 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 6 -walk_prep +walk_prep_outline rotate: false xy: 625, 42 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -walk_right +walk_right_outline rotate: false xy: 617, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 2 -walk_right +walk_right_outline rotate: false xy: 788, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 7 -walk_right +walk_right_outline rotate: false xy: 1187, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 4 -walk_right +walk_right_outline rotate: false xy: 1472, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 1 -walk_right +walk_right_outline rotate: false xy: 1757, 79 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 6 -walk_right +walk_right_outline rotate: false xy: 172, 41 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 3 -walk_right +walk_right_outline rotate: false xy: 286, 41 size: 52, 32 orig: 32, 32 offset: 0, 0 index: 8 -walk_right +walk_right_outline rotate: false xy: 682, 42 size: 52, 32 diff --git a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java index d18021210..836b6b359 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java @@ -51,7 +51,7 @@ public static Entity createEngineer() { BaseEntityConfig config = configs.engineer; AITaskComponent aiComponent = new AITaskComponent(); - AnimationRenderComponent animator = createAnimationRenderComponent(false); + AnimationRenderComponent animator = createAnimationRenderComponent(); engineer .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) @@ -65,11 +65,11 @@ public static Entity createEngineer() { return engineer; } - public static AnimationRenderComponent createAnimationRenderComponent(boolean isClicked) { - String atlasPath = isClicked ? "images/engineers/engineer_outline.atlas" - : "images/engineers/engineer.atlas"; + public static AnimationRenderComponent createAnimationRenderComponent() { + String atlasPath = "images/engineers/engineer.atlas"; + String atlasOutlinePath = "images/engineers/engineer_outline.atlas"; AnimationRenderComponent animator = new AnimationRenderComponent( - new TextureAtlas(atlasPath)); + new TextureAtlas(atlasPath), new TextureAtlas(atlasOutlinePath)); animator.addAnimation("walk_left", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("walk_right", 0.2f, Animation.PlayMode.LOOP); animator.addAnimation("walk_prep", 0.2f, Animation.PlayMode.LOOP); @@ -79,6 +79,16 @@ public static AnimationRenderComponent createAnimationRenderComponent(boolean is animator.addAnimation("prep", 0.05f, Animation.PlayMode.NORMAL); animator.addAnimation("hit", 0.01f, Animation.PlayMode.NORMAL); animator.addAnimation("death", 0.1f, Animation.PlayMode.NORMAL); + + animator.addAnimation("walk_left_outline", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("walk_right_outline", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("walk_prep_outline", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("idle_right_outline", 0.2f, Animation.PlayMode.LOOP); + animator.addAnimation("firing_auto_outline", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("firing_single_outline", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("prep_outline", 0.05f, Animation.PlayMode.NORMAL); + animator.addAnimation("hit_outline", 0.01f, Animation.PlayMode.NORMAL); + animator.addAnimation("death_outline", 0.1f, Animation.PlayMode.NORMAL); return animator; } diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 263d6f284..c92ceb4bc 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -30,18 +30,23 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { camera.unproject(worldCoordinates); Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); Entity engineer = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); - logger.info("Clicked entity: " + engineer); + //logger.info("Clicked entity: " + engineer); // Case when engineer is not clicked if (engineer == null || engineer.getComponent(HumanAnimationController.class) == null) { return false; } + // Case when engineer is clicked - engineer.removeComponent(AnimationRenderComponent.class); - logger.info("Engineer has animation render component " + engineer.getComponent(AnimationRenderComponent.class)); - AnimationRenderComponent animator = EngineerFactory.createAnimationRenderComponent(true); - engineer.addComponent(animator); - logger.info("Engineer has animation render component " + engineer.getComponent(AnimationRenderComponent.class)); + AnimationRenderComponent animator = engineer.getComponent(AnimationRenderComponent.class); + String currentAnimation = animator.getCurrentAnimation(); + + // outline image if it is not already outlined and vice versa + if (currentAnimation.contains("_outline")) { + animator.startAnimation(currentAnimation.substring(0, currentAnimation.lastIndexOf('_'))); + } else { + animator.startAnimation(currentAnimation + "_outline"); + } return true; } diff --git a/source/core/src/main/com/csse3200/game/rendering/AnimationRenderComponent.java b/source/core/src/main/com/csse3200/game/rendering/AnimationRenderComponent.java index 0143567f3..62de022a8 100644 --- a/source/core/src/main/com/csse3200/game/rendering/AnimationRenderComponent.java +++ b/source/core/src/main/com/csse3200/game/rendering/AnimationRenderComponent.java @@ -37,6 +37,7 @@ public class AnimationRenderComponent extends RenderComponent { private static final Logger logger = LoggerFactory.getLogger(AnimationRenderComponent.class); private final GameTime timeSource; private final TextureAtlas atlas; + private final TextureAtlas atlas2; private final Map> animations; private Animation currentAnimation; private String currentAnimationName; @@ -48,6 +49,14 @@ public class AnimationRenderComponent extends RenderComponent { */ public AnimationRenderComponent(TextureAtlas atlas) { this.atlas = atlas; + this.atlas2 = null; + this.animations = new HashMap<>(4); + timeSource = ServiceLocator.getTimeSource(); + } + + public AnimationRenderComponent(TextureAtlas atlas1, TextureAtlas atlas2) { + this.atlas = atlas1; + this.atlas2 = atlas2; this.animations = new HashMap<>(4); timeSource = ServiceLocator.getTimeSource(); } @@ -73,20 +82,37 @@ public boolean addAnimation(String name, float frameDuration) { */ public boolean addAnimation(String name, float frameDuration, PlayMode playMode) { Array regions = atlas.findRegions(name); + Array regions2; + if (regions == null || regions.size == 0) { - logger.warn("Animation {} not found in texture atlas", name); - return false; + // check if there is a second atlas file + if (atlas2 != null) { + regions2 = atlas2.findRegions(name); + + if (regions2 == null || regions2.size == 0) { + logger.warn("Animation {} not found in texture atlas 2", name); + return false; + } else { + Animation animation = new Animation<>(frameDuration, regions2, playMode); + animations.put(name, animation); + logger.debug("Adding animation {}", name); + return true; + } + } else { + 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); + "Animation {} already added in texture atlas. Animations should only be added once.", + name); return false; + } else { + Animation animation = new Animation<>(frameDuration, regions, playMode); + animations.put(name, animation); + logger.debug("Adding animation {}", name); + return true; } - - 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 */ 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 4d6188c88..e612608d8 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 @@ -38,7 +38,7 @@ public class TowerFactoryTest { private String[] texture = { "images/towers/turret_deployed.png", "images/towers/turret01.png", - "images/towers/wallTower.png", + "images/towers/WallTower.png", "images/towers/fire_tower_atlas.png", "images/towers/stun_tower.png", "images/towers/DroidTower.png", From 2b68ed933ee61f5c9ef37b9317c6dbe185c7c22b Mon Sep 17 00:00:00 2001 From: Nawal Date: Sat, 30 Sep 2023 13:03:29 +1000 Subject: [PATCH 08/49] Fixed inconsistent naming of WallTower.png files --- .../com/csse3200/game/entities/factories/NPCFactoryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java index 906a1a640..ae584e2c5 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java @@ -34,7 +34,7 @@ public class NPCFactoryTest { private final String[] texture = { "images/towers/turret_deployed.png", "images/towers/turret01.png", - "images/towers/wallTower.png" + "images/towers/WallTower.png" }; private final String[] atlas = {"images/towers/turret01.atlas", "images/mobs/xenoGrunt.atlas"}; From 6b936212f74d7321c4d74c3b9c9027b671a0025d Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Sat, 30 Sep 2023 23:22:31 +1000 Subject: [PATCH 09/49] Added tower click detection --- .../csse3200/game/areas/ForestGameArea.java | 4 ++ .../game/entities/factories/TowerFactory.java | 4 +- .../game/input/UpgradeUIComponent.java | 62 +++++++++++++++++++ .../csse3200/game/screens/MainGameScreen.java | 4 ++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 86fb45744..603a00b61 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -271,6 +271,10 @@ public void create() { // spawnWeaponTower(); // spawnGapScanners(); // spawnDroidTower(); + spawnScrap(); + spawnDroidTower(); + spawnTNTTower(); + spawnIncome(); } 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 0e750647f..f3880c68c 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 @@ -24,7 +24,7 @@ import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.rendering.TextureRenderComponent; import com.csse3200.game.services.ServiceLocator; - +import com.csse3200.game.input.UpgradeUIComponent; /** * Factory to create a tower entity. * @@ -315,7 +315,7 @@ public static Entity createBaseTower() { .addComponent(new HitboxComponent().setLayer(PhysicsLayer.TOWER)) // TODO: we might have to change the names of the layers .addComponent(new PhysicsComponent().setBodyType(BodyType.StaticBody)) .addComponent(new TowerUpgraderComponent()); - + tower.setLayer(1); // Set priority to 1, which is 1 below scrap (which is 0) return tower; } } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java new file mode 100644 index 000000000..52a06442c --- /dev/null +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -0,0 +1,62 @@ +package com.csse3200.game.input; + +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.components.tower.TowerUpgraderComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UpgradeUIComponent extends InputComponent { + private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); + private final EntityService entityService; + private final Camera camera; + int value; + + /** + * Constructor for the UpgradeUIComponent + * @param camera the camera to be used, this is the camera that the game is rendered with + */ + public UpgradeUIComponent(Camera camera) { + this.value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + this.entityService = ServiceLocator.getEntityService(); + this.camera = camera; + } + + /** + * Getter for the camera + * @return the camera + */ + public Camera getCamera() { + return camera; + } + + /** + * When the mouse is clicked, this method is called. + * + * @param screenX The x coordinate, origin is in the upper left corner + * @param screenY The y coordinate, origin is in the upper left corner + * @param pointer the pointer for the event. + * @param button the button + * @return + */ + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + Vector3 worldCoordinates = new Vector3((float) screenX , (float) screenY, 0); + getCamera().unproject(worldCoordinates); // translate from screen to world coordinates + Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); + Entity clickedEntity = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); + + if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null) { + logger.info("clicked a turret that is upgradable!"); + return true; + } + return false; + } + + +} diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index 13ad9eb18..42afa287f 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -32,6 +32,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.security.Provider; + /** * The game screen containing the main game. * @@ -95,7 +97,9 @@ public MainGameScreen(GdxGame game) { /* Input components */ InputComponent dropInputHandler = new DropInputComponent(renderer.getCamera().getCamera()); + InputComponent upgradeInputHandler = new UpgradeUIComponent(renderer.getCamera().getCamera()); ServiceLocator.getInputService().register(dropInputHandler); + ServiceLocator.getInputService().register(upgradeInputHandler); InputComponent engineerInputHandler = new EngineerInputComponent(game, renderer.getCamera().getCamera()); ServiceLocator.getInputService().register(engineerInputHandler); From c4710d707e1663d08d511a7bc236720805dd132e Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Sat, 30 Sep 2023 23:38:35 +1000 Subject: [PATCH 10/49] Modified TurretSelectionScreen Class to improve UI Next objective is to make the buttons individual for --- .../turret-select/imageedit_2_8132799771.png | Bin 0 -> 1788 bytes .../components/gamearea/CurrencyDisplay.java | 6 +- .../com/csse3200/game/screens/TowerType.java | 14 +-- .../game/screens/TurretSelectionScreen.java | 108 ++++++++++-------- .../com/csse3200/game/screens/Turrets.java | 8 ++ 5 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 source/core/assets/images/turret-select/imageedit_2_8132799771.png create mode 100644 source/core/src/main/com/csse3200/game/screens/Turrets.java diff --git a/source/core/assets/images/turret-select/imageedit_2_8132799771.png b/source/core/assets/images/turret-select/imageedit_2_8132799771.png new file mode 100644 index 0000000000000000000000000000000000000000..6fafcf62f99bb40010bfa2b78d2e020d45df5ee7 GIT binary patch literal 1788 zcmZ`)eK=cL8o%+eF{Nu}x}`&>Yqp&&r5a7ErM2TLzJjR;+dilwL8E<0C>?Zsr(1$Z z(b9I?Mp49PqAE>jDUu=LGbKd@Ly)p1gc8{^?LNEn&)(-f?|a|(chB$l-t*jh&aHEv z&bxOR?1CU@x2uaI2E@YOhL$?;+V4{OK+p)Y^RR=U`dsbpAWe`Pg}7imASnK?5R{w_ zK_5XWSqeed5D>I*34*NeLXdvceYV$G2vXBH=Z-~z2b^!#KV97}U)gdZ*Hy@s&gA+E z`8M#M>i}{{tpSin?z7yH`N}orGnERYsPtNwe>AvdvF^{UK3U$Z+g1U{DWeXRQH!QD z`V@0XFNO-&M%tJR2muDSEM{u&RQAX`Wn?~8F!ewxzc=xoC0l1M zuB8ejcgAH**}6!n8UnVhYW=YBTA{3!Z`XY?_QnqV!&b>B18jiVA+6?oam$^_r7Fb^ zXc%--`mc|X%s$7oTF`17R|MXxYJKP7{Mx0G*SPYo$1=r_wC5hwrV9^VCbWxh_DyH> zPLYMvX+08r6`xQi$PiAE`=*n569M%0z$YCkzr0KDmG~5KFP3%$ly+P!>kKUGjBgW% zRPnDo>yK#cBe41+8v7%FX9>OUaDprOB(5ltH<7@bh-44ptGj>h8pjrKgRA&N&M=8H z98&emwH8ruC6CAvr3j`{1QG&Mh|X!WO=4hfv*TLdP)Fu3mUTon_9u6ad*!p;GMS!v z&%xR{rqy8b*}g?wnt1W2mm?WH65{hg%uVkh@URa{Cv%Q z1RjsD52h0+l?Lj-;EAJ3$fT5-{#8_#pWO?^L_$*%KJ5|rWwh9^ zSRv=UyBF0pw{659clh$L3(eg{mg7~P5Wl7Kn4(lqb7&`jH7G4&&bgDNG@9n0Q2U)} zM3aikv-|Mh7(T2cH;f)WI%~2h@7dJWKQ_wn5@Ze_r*Z?vyzrUKhHp>oDG4t({aUeC zE-8pb&EdwZnrWO8^@DuxP0ay&T|*|P#U)xIT$PP+mechzGx4OLyB!s7ZhN!P-KJG% zo2CN&j+xeex$7zQ2(pz$3W-KnV0=ClyZLarOh0dP;dE~nWsknG<+|D{vGqye@bJ=> zZfrM>c0H$n_I<#Z&QJtvceV#dH1cS8Xe&;X6^+zzv?s($27J#Ajtx{sOrH#hKr=&= z5~__4+Z4IDM_(^2XcQN&=k%IiT$F`J_KSSC^vCFj=x^Pbrj=~6=#Mtb*I1TA6~2i* zjFb=yS*6?f)5RIX(l>Dn2E&y;4+jl`d@AmV*&9ytYXMh17C=e+0?%HrfttZc>MfS4 z^H!|85?~GI;~DV3WHl#h9_l9UHR@jE#C~g}Eq$Q1-mICAN2cONw_pvkQa&u%tgv1u z6<2fcMG^RUaEIFc7Xn7;f#Y-OjJsmQ=Gxx?2Ag{w$M(v$|17u4!Xj=!8e;QA(|RX*}*^ zEg4BK^Itzb@b#@3`F(oh`y0l$qhD2*w#kMx?5TNvoR;aE$NTh0{PROgsTzBano}6?S%I zfKF%4U|l+zjUW5_`m>_i2Fma3{xO+clNZ!?e%2&kZ^jwBA5A^X7Z8!XdkVb{GAmkZ zEhw?Luv^W6REn$}gH3c|hg%X*qV<*G#Z!@CW!2uH-A~3t6BIiRjKZtBXtc+zGfo-0 zW>zNgB*k>OFt8=3*h#0|Ax&NBG~KlP!_S=rt<%`xwtg?AT9Q9&;*nY=3H-C)$Dq!~ z;DTcC)*&Q32+(oFapX~i)lnn@Yhhsx?1ZH$0%46nSdiG@1p3{CtC6_Np+Eiq3AV@7 Rz(xQ;t|(8(8v9GB{|5hlkvsqZ literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java index 5f3a12996..33e22aeaf 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java @@ -18,6 +18,7 @@ import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.UIComponent; import com.badlogic.gdx.scenes.scene2d.actions.Actions; +import org.w3c.dom.Text; /** * A UI component for displaying the currency owned @@ -28,6 +29,7 @@ public class CurrencyDisplay extends UIComponent { private TextButton scrapsTb; private TextButton crystalsTb; private Sound clickSound; + private TextButton test; /** * Adds actors to stage @@ -53,9 +55,11 @@ private void addActors() { ServiceLocator.getCurrencyService().getScrap().getAmount()); crystalsTb = createButton("images/economy/crystalBanner.png", ServiceLocator.getCurrencyService().getCrystal().getAmount()); + test = createButton("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", 100); table.add(scrapsTb).width(scrapsTb.getWidth() * 0.5f).height(scrapsTb.getHeight() * 0.5f); table.add(crystalsTb).width(crystalsTb.getWidth() * 0.5f).height(crystalsTb.getHeight() * 0.5f); + table.add(test).width(test.getWidth() * 0.5f).height(test.getHeight() * 0.5f); stage.addActor(table); } @@ -69,7 +73,7 @@ private TextButton createButton(String imageFilePath, int value) { tb.setDisabled(true); tb.getLabel().setAlignment(Align.right); - tb.pad(0, 0, 0, 50); + tb.pad(0, 0, 0, 0); tb.setTransform(true); return tb; diff --git a/source/core/src/main/com/csse3200/game/screens/TowerType.java b/source/core/src/main/com/csse3200/game/screens/TowerType.java index 1dd3eadf5..7b1dcd525 100644 --- a/source/core/src/main/com/csse3200/game/screens/TowerType.java +++ b/source/core/src/main/com/csse3200/game/screens/TowerType.java @@ -1,19 +1,19 @@ package com.csse3200.game.screens; public enum TowerType { - WEAPON("images/towers/turret_deployed.png", "Weapon Tower", + WEAPON("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Weapon Tower", "The Weapon Tower is a simple and basic turret that fires rapid shots at enemies dealing damage over time."), - TNT("images/towers/turret_deployed.png", "TNT Tower", + TNT("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "TNT Tower", "The TNT Tower launches explosive projectiles, dealing area damage to groups of enemies."), - DROID("images/towers/turret_deployed.png", "Droid Tower", + DROID("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Droid Tower", "Droid Towers deploy robotic helpers that assist in combat and provide support to nearby turrets."), - WALL("images/towers/turret_deployed.png", "Wall Tower", + WALL("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Wall Tower", "The Wall Tower creates barriers to block enemy paths, slowing down their progress."), - FIRE("images/towers/turret_deployed.png", "Fire Tower", + FIRE("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Fire Tower", "The Fire Tower emits flames, causing damage over time to enemies caught in its fiery radius."), - STUN("images/towers/turret_deployed.png", "Stun Tower", + STUN("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Stun Tower", "The Stun Tower releases electric shocks that temporarily immobilize and damage enemies."), - INCOME("images/towers/turret_deployed.png", "Income Tower", + INCOME("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", "Income Tower", "The Income Tower generates additional in-game currency over time."); private final String imagePath; diff --git a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java index d120d8854..e10f07dbc 100644 --- a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java @@ -3,9 +3,12 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Label; @@ -13,11 +16,15 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.csse3200.game.GdxGame; import com.badlogic.gdx.scenes.scene2d.ui.Image; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Text; import java.util.*; @@ -92,59 +99,21 @@ public void clicked(InputEvent event, float x, float y) { Table turretTable = new Table(); turretTable.center(); // Center the contents of the nested table + Pixmap pixmap200 = new Pixmap(Gdx.files.internal(String.valueOf(Gdx.files.internal(turret.getImagePath())))); + Pixmap pixmap100 = new Pixmap(150, 150, pixmap200.getFormat()); + pixmap100.drawPixmap(pixmap200, + 0, 0, pixmap200.getWidth(), pixmap200.getHeight(), + 0, 0, pixmap100.getWidth(), pixmap100.getHeight() + ); + // Load the turret image - Texture turretTexture = new Texture(Gdx.files.internal(turret.getImagePath())); + Texture turretTexture = new Texture(pixmap100); Image turretImage = new Image(turretTexture); - + TextButton button = createButton("images/turret-select/imageedit_2_8132799771.png", + "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png", 100); // Add the image to the nested table - turretTable.add(turretImage).pad(10).row(); - - // Create a label for the turret description - Label turretDescriptionLabel = new Label(turret.getDescription(), skin); - turretDescriptionLabel.setWrap(true); // Wrap text if it's too long - - // Add the description label to the nested table - turretTable.add(turretDescriptionLabel).center().width(200).pad(10).row(); // Adjust width if needed - - // Create a TextButton for the turret name - TextButton turretButton = new TextButton(turret.getTowerName(), skin); - turretButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - logger.info(String.valueOf(selectedTurrets.size())); - if (selectedTurrets.size() > MAX_SELECTED_TURRETS) { - message.setText("You can only select up to 5 turrets."); - } else { - message.setText("Select your turrets"); - } - if (selectedTurrets.contains(turret)) { - // Turret is already selected, unselect it - selectedTurrets.remove(turret); - // You can also change the button appearance to indicate unselection - logger.info(selectedTurrets.toString()); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); - } else if (selectedTurrets.size() == MAX_SELECTED_TURRETS) { - // Turret is not selected, but the max number of turrets has been reached - message.setText("You can only select up to 5 turrets."); - } else if (selectedTurrets.size() < MAX_SELECTED_TURRETS) { - // Turret is not selected, select it - selectedTurrets.add(turret); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); - logger.info(selectedTurrets.toString()); - } - else { - // Turret is not selected, select it - selectedTurrets.add(turret); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); - //logger.info(selectedTurrets.toString()); - - // You can change the button appearance to indicate selection - } - } - }); - - // Add the turret name button to the nested table - turretTable.add(turretButton).center(); + //turretTable.add(turretImage).pad(10).row(); + turretTable.add(button).pad(10).row(); // Add the nested table to the main table table.add(turretTable).pad(10).center(); @@ -161,6 +130,7 @@ public void clicked(InputEvent event, float x, float y) { // Centered the "continue" button table.add(confirmButton).center().colspan(4).padBottom(20).row(); + // Center the table within the stage table.center(); stage.addActor(table); @@ -178,6 +148,44 @@ public void render(float delta) { stage.draw(); } + private TextButton createButton(String defaultImageFilePath, String alternateImageFilePath, int cost) { + Drawable defaultDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(defaultImageFilePath))); + Drawable alternateDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(alternateImageFilePath))); + + TextButton.TextButtonStyle buttonStyle = new TextButton.TextButtonStyle(); + buttonStyle.font = new BitmapFont(); // Set your desired font + buttonStyle.up = defaultDrawable; // Default state + + // Create button + TextButton tb = new TextButton(String.format("%d", cost), buttonStyle); + + // Add click listener to toggle the image + final boolean[] isDefaultImage = {true}; // Keep track of the image state + + tb.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + super.clicked(event, x, y); + + // Toggle the image + if (isDefaultImage[0]) { + tb.getStyle().up = alternateDrawable; + } else { + tb.getStyle().up = defaultDrawable; + } + + // Update the image state + isDefaultImage[0] = !isDefaultImage[0]; + } + }); + + tb.setDisabled(true); + + return tb; + } + + + public List getTurretList() { return turretList; } diff --git a/source/core/src/main/com/csse3200/game/screens/Turrets.java b/source/core/src/main/com/csse3200/game/screens/Turrets.java new file mode 100644 index 000000000..dcd126fef --- /dev/null +++ b/source/core/src/main/com/csse3200/game/screens/Turrets.java @@ -0,0 +1,8 @@ +package com.csse3200.game.screens; + +import com.badlogic.gdx.Gdx; + +public class Turrets { + public final static int[] BASIC = { + }; +} From 1f3b40bc347c31c35d8abd5e073deab057e82ee7 Mon Sep 17 00:00:00 2001 From: Nawal Date: Sun, 1 Oct 2023 11:57:09 +1000 Subject: [PATCH 11/49] HumanAnimationController now checks if engineer has been selected & sets animation accordingly. Started to implement the engineers options menu --- .../csse3200/game/areas/ForestGameArea.java | 1 - .../components/npc/EngineerMenuComponent.java | 50 +++++++++++ .../player/HumanAnimationController.java | 90 ++++++++++++++++--- .../entities/factories/EngineerFactory.java | 2 + .../entities/factories/PlayerFactory.java | 4 +- .../game/input/EngineerInputComponent.java | 8 +- 6 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 86fb45744..4ccf3ece5 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -276,7 +276,6 @@ public void create() { private void displayUI() { Entity ui = new Entity(); - ui.addComponent(new GameAreaDisplay("Box Forest")); ui.addComponent(ServiceLocator.getGameEndService().getDisplay()); ui.addComponent(ServiceLocator.getCurrencyService().getDisplay()); spawnEntity(ui); diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java new file mode 100644 index 000000000..0ab0ff52e --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -0,0 +1,50 @@ +package com.csse3200.game.components.npc; + +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.csse3200.game.ui.UIComponent; + +public class EngineerMenuComponent extends UIComponent { + Table table; + + @Override + public void create() { + super.create(); + } + + @Override + public void draw(SpriteBatch batch) { + // draw is handled by the stage + } + + public void createMenu(float x, float y, Camera camera) { + table = new Table(); + + Vector3 entityCoordinates = new Vector3(x, y, 0); + Vector3 entityScreenCoordinate = camera.project(entityCoordinates); + Vector2 stageCoordinates = stage.screenToStageCoordinates( + new Vector2(entityScreenCoordinate.x, entityScreenCoordinate.y)); + stage.getViewport().unproject(stageCoordinates); + + table.setPosition(x, y); + table.setFillParent(true); + String imageFilePath = "images/ui/Sprites/UI_Glass_Banner_01b.png"; + Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture(imageFilePath))); + table.setBackground(drawable); + //stage.addActor(table); + + } + + public void removeMenu() { + table.clear(); + table.remove(); + } + +} diff --git a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java index c6231f29e..9308d7eb5 100644 --- a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java @@ -31,6 +31,18 @@ public class HumanAnimationController extends Component { private static final String FIRE_SINGLE_ANIM = "firing_single"; private static final String HIT_ANIM = "hit"; private static final String DEATH_ANIM = "death"; + + private static final String IDLEL_ANIM_OUTLINE = "idle_left_outline"; + private static final String IDLER_ANIM_OUTLINE = "idle_right_outline"; + private static final String WALKL_ANIM_OUTLINE = "walk_left_outline"; + private static final String WALKR_ANIM_OUTLINE = "walk_right_outline"; + private static final String WALK_PREP_ANIM_OUTLINE = "walk_prep_outline"; + private static final String FIRE_AUTO_ANIM_OUTLINE = "firing_auto_outline"; + private static final String FIRE_SINGLE_ANIM_OUTLINE = "firing_single_outline"; + private static final String PREP_ANIM_OUTLINE = "prep_outline"; + private static final String HIT_ANIM_OUTLINE = "hit_outline"; + private static final String DEATH_ANIM_OUTLINE = "death_outline"; + // Sound effects constants private static final String FIRE_AUTO_SFX = "sounds/engineers/firing_auto.mp3"; private static final String FIRE_SINGLE_SFX = "sounds/engineers/firing_single.mp3"; @@ -41,6 +53,9 @@ public class HumanAnimationController extends Component { private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( FIRE_SINGLE_SFX, Sound.class); + private boolean clicked = false; + + /** * Instantiates a HumanAnimationController and adds all the event listeners for the * Human entity - Just engineers at this stage. @@ -65,21 +80,33 @@ public void create() { * Callback that starts the idle animation facing left */ void animateIdleLeft() { - animator.startAnimation(IDLEL_ANIM); + if (clicked) { + animator.startAnimation(IDLEL_ANIM_OUTLINE); + } else { + animator.startAnimation(IDLEL_ANIM); + } } /** * Callback that starts the idle animation facing right */ void animateIdleRight() { - animator.startAnimation(IDLER_ANIM); + if (clicked) { + animator.startAnimation(IDLER_ANIM_OUTLINE); + } else { + animator.startAnimation(IDLER_ANIM); + } } /** * Callback that starts the walk animation for left movement */ void animateLeftWalk() { - animator.startAnimation(WALKL_ANIM); + if (clicked) { + animator.startAnimation(WALKL_ANIM_OUTLINE); + } else { + animator.startAnimation(WALKL_ANIM); + } // runSound.play(); } @@ -87,7 +114,11 @@ void animateLeftWalk() { * Callback that starts the walk animation for right movement */ void animateRightWalk() { - animator.startAnimation(WALKR_ANIM); + if (clicked) { + animator.startAnimation(WALKR_ANIM_OUTLINE); + } else { + animator.startAnimation(WALKR_ANIM); + } } /** @@ -95,14 +126,22 @@ void animateRightWalk() { * unused, but intended to be incorporated as engineer functionality expands */ void animatePrepWalk() { - animator.startAnimation(WALK_PREP_ANIM); + if (clicked) { + animator.startAnimation(WALK_PREP_ANIM_OUTLINE); + } else { + animator.startAnimation(WALK_PREP_ANIM); + } } /** * Callback that starts the shoot animation in single fire mode, and plays the single fire sound */ void animateSingleFiring() { - animator.startAnimation(FIRE_SINGLE_ANIM); + if (clicked) { + animator.startAnimation(FIRE_SINGLE_ANIM_OUTLINE); + } else { + animator.startAnimation(FIRE_SINGLE_ANIM); + } fireSingleSound.play(); } @@ -111,7 +150,11 @@ void animateSingleFiring() { * Currently unused, but intended to be incorporated as engineer functionality expands. */ void animateFiringAuto() { - animator.startAnimation(FIRE_AUTO_ANIM); + if (clicked) { + animator.startAnimation(FIRE_AUTO_ANIM_OUTLINE); + } else { + animator.startAnimation(FIRE_AUTO_ANIM); + } fireAutoSound.play(); } @@ -119,20 +162,47 @@ void animateFiringAuto() { * Callback that starts the 'prep' animation, i.e., raising weapon in preparation for firing */ void animatePrep() { - animator.startAnimation(PREP); + if (clicked) { + animator.startAnimation(PREP_ANIM_OUTLINE); + } else { + animator.startAnimation(PREP); + } } /** * Callback that starts the 'hit' animation when engineer is damaged */ void animateHit() { - animator.startAnimation(HIT_ANIM); + if (clicked) { + animator.startAnimation(HIT_ANIM_OUTLINE); + } else { + animator.startAnimation(HIT_ANIM); + } } /** * Callback that starts the 'death' animation when the engineer entity's health reaches zero. */ void animateDeath() { - animator.startAnimation(DEATH_ANIM); + if (clicked) { + animator.startAnimation(DEATH_ANIM_OUTLINE); + } else { + animator.startAnimation(DEATH_ANIM); + } + } + + /** + * @return true if the entity has been clicked/selected, false otherwise + */ + public boolean isClicked() { + return clicked; + } + + /** + * Sets the clicked state of the entity + * @param clicked true if the entity has been clicked/selected, false otherwise + */ + public void setClicked(boolean clicked) { + this.clicked = clicked; } } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java index 836b6b359..e9feaf2aa 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/EngineerFactory.java @@ -5,6 +5,7 @@ import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.TouchAttackComponent; +import com.csse3200.game.components.npc.EngineerMenuComponent; import com.csse3200.game.components.player.HumanAnimationController; import com.csse3200.game.components.tasks.human.HumanWanderTask; import com.csse3200.game.entities.Entity; @@ -57,6 +58,7 @@ public static Entity createEngineer() { .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(animator) .addComponent(new HumanAnimationController()) + .addComponent(new EngineerMenuComponent()) .addComponent(aiComponent); engineer.getComponent(AITaskComponent.class).addTask(new HumanWanderTask(COMBAT_TASK_PRIORITY, ENGINEER_RANGE)); diff --git a/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java index d77ff1d1d..95dd20596 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/PlayerFactory.java @@ -50,8 +50,8 @@ public static Entity createPlayer() { .addComponent(new CombatStatsComponent(1000, 5000)) .addComponent(new InventoryComponent(stats.gold)) .addComponent(inputComponent) - .addComponent(aiComponent) - .addComponent(new PlayerStatsDisplay()); + .addComponent(aiComponent); + //.addComponent(new PlayerStatsDisplay()); PhysicsUtils.setScaledCollider(player, 0.6f, 0.3f); player.getComponent(ColliderComponent.class).setDensity(1.5f); diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index c92ceb4bc..ff6584c5b 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -3,6 +3,7 @@ import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.csse3200.game.components.npc.EngineerMenuComponent; import com.csse3200.game.components.player.HumanAnimationController; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; @@ -40,12 +41,17 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { // Case when engineer is clicked AnimationRenderComponent animator = engineer.getComponent(AnimationRenderComponent.class); String currentAnimation = animator.getCurrentAnimation(); - + HumanAnimationController controller = engineer.getComponent(HumanAnimationController.class); + EngineerMenuComponent menu = engineer.getComponent(EngineerMenuComponent.class); // outline image if it is not already outlined and vice versa if (currentAnimation.contains("_outline")) { animator.startAnimation(currentAnimation.substring(0, currentAnimation.lastIndexOf('_'))); + menu.removeMenu(); + controller.setClicked(false); } else { animator.startAnimation(currentAnimation + "_outline"); + menu.createMenu(cursorPosition.x, cursorPosition.y, camera); + controller.setClicked(true); } return true; From 59b14118a496b9202a87733c488ca2655e799ff8 Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Sun, 1 Oct 2023 15:44:22 +1000 Subject: [PATCH 12/49] Updated UI of TurretSelectionScreen --- .../turret-select/imageedit_4_5616741474.png | Bin 0 -> 1913 bytes .../com/csse3200/game/screens/TowerType.java | 36 +++++------ .../game/screens/TurretSelectionScreen.java | 59 +++++++++++++----- 3 files changed, 61 insertions(+), 34 deletions(-) create mode 100644 source/core/assets/images/turret-select/imageedit_4_5616741474.png diff --git a/source/core/assets/images/turret-select/imageedit_4_5616741474.png b/source/core/assets/images/turret-select/imageedit_4_5616741474.png new file mode 100644 index 0000000000000000000000000000000000000000..f877adaeca3195ad91b00fe90c8b5b5657e8aa0d GIT binary patch literal 1913 zcmbuAS5y;t7RLVx2}F<@5Wx|F0f&|$R3io@7)l_tfV2@4NT>_aWI>pWL4qJKQpHfD z4iZIR=u6W`i&6qO0t$)+M_QC7LMXD?$9>qRJ@D%Fmk8Qg}u9gPz@TFtT{dJPsRD4vkzoX)g>#*D)e z4eS>eJP-|wtqC2WL)U*-)GAZI4y($h^j7M5UvxeZEayj^%8U#6vKz@0cn)JsgDJVh zUlp#MTeQm$^Rk&b5b)Xq`5O>Rgc|c-(&M$Io`-5GRb0b@D;ruGQqCQ`_X!Q-z%`W=K!$J$ZUL;iVKJ{Fi|czQB5c zUZ)maz&dNj!P8H-n!Mf0t9SF9m%?vSDA8$ZV?ba%Q4YRl(HNO=OL-`rA_ z1iJv8_O1q)ca+`Kt+%>4IoeAf11z{RwrRHO+DqqKGx4AJWiRUX}YbIV_FCPV*$CZ2gTBuz> zfGgN=4fpaasgvyX;L7;Jv?)?-R3|%MYitA9Tl9~+z?MQL?wVXFObkWUm`w16UM2MZFVDAhsF1mw&m_2V(E0-s zURXO%@>1h-(KvLKyo2ocldBn)ul?s3>Qb)Er19oUfArf-PD|89DH17@4%FrzWBkjn zB{Q>;`fbU|QUFT8_V>v^c=3I{X&OZOk$K+>FW(~H`y*K~0iv>R_{Lk7)qm{_{+Rjm zJ|!VxY<5k2iYd z&S)FVxr7y1tO$@zcUP!A$2RS>J(nW{-7);j-+XJ6NOEIyNg!gu{Bh5)?(CXL#mtme z?=S*cnwLyp?hB2TtsHBG5FhHdO)?)ud3Gw7>7X7A+Pxi`tAbD@GScntOG~9}L~Oza z6!HqjL*WrTGIZ60xL4~4pT~Yv?A^VCF-0)oYOwDIOFZn1#Gi8R5w{?!DrDr}1y8=0 z)u!TIUwfZUma#-cl6R$doaF2$^cR$bk4W>1mFE?j?-hSDYLvgwfFat@2!%e4GD5o< u7@HXyn;D MAX_SELECTED_TURRETS) { + message.setText("You can only select up to 5 turrets."); + } else { + message.setText("Select your turrets"); + } + if (selectedTurrets.contains(turret)) { + // Turret is already selected, unselect it + selectedTurrets.remove(turret); + // You can also change the button appearance to indicate unselection + logger.info(selectedTurrets.toString()); + turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); + } else if (selectedTurrets.size() == MAX_SELECTED_TURRETS) { + // Turret is not selected, but the max number of turrets has been reached + message.setText("You can only select up to 5 turrets."); + } else if (selectedTurrets.size() < MAX_SELECTED_TURRETS) { + // Turret is not selected, select it + selectedTurrets.add(turret); + turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); + logger.info(selectedTurrets.toString()); + } + else { + // Turret is not selected, select it + selectedTurrets.add(turret); + turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); + //logger.info(selectedTurrets.toString()); + + // You can change the button appearance to indicate selection + } + } + }); + // Add the image to the nested table - //turretTable.add(turretImage).pad(10).row(); turretTable.add(button).pad(10).row(); // Add the nested table to the main table @@ -148,7 +177,7 @@ public void render(float delta) { stage.draw(); } - private TextButton createButton(String defaultImageFilePath, String alternateImageFilePath, int cost) { + private TextButton createButton(String defaultImageFilePath, String alternateImageFilePath, String cost) { Drawable defaultDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(defaultImageFilePath))); Drawable alternateDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(alternateImageFilePath))); @@ -157,7 +186,7 @@ private TextButton createButton(String defaultImageFilePath, String alternateIma buttonStyle.up = defaultDrawable; // Default state // Create button - TextButton tb = new TextButton(String.format("%d", cost), buttonStyle); + TextButton tb = new TextButton(String.format(cost), buttonStyle); // Add click listener to toggle the image final boolean[] isDefaultImage = {true}; // Keep track of the image state From 42a8968d99493de286507aa3f7fbb3b473b038eb Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Sun, 1 Oct 2023 17:09:17 +1000 Subject: [PATCH 13/49] Improved Turret Select UI --- .../turret-select/Weapon-Tower-Clicked.png | Bin 0 -> 8536 bytes .../turret-select/Weapon-Tower-Default.png | Bin 0 -> 11944 bytes .../turret-select/wall-tower-clicked.png | Bin 0 -> 5251 bytes .../turret-select/wall-tower-default.png | Bin 0 -> 6163 bytes .../com/csse3200/game/screens/TowerType.java | 31 +++++++++++++----- .../game/screens/TurretSelectionScreen.java | 7 ++-- .../com/csse3200/game/screens/Turrets.java | 8 ----- 7 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 source/core/assets/images/turret-select/Weapon-Tower-Clicked.png create mode 100644 source/core/assets/images/turret-select/Weapon-Tower-Default.png create mode 100644 source/core/assets/images/turret-select/wall-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/wall-tower-default.png delete mode 100644 source/core/src/main/com/csse3200/game/screens/Turrets.java diff --git a/source/core/assets/images/turret-select/Weapon-Tower-Clicked.png b/source/core/assets/images/turret-select/Weapon-Tower-Clicked.png new file mode 100644 index 0000000000000000000000000000000000000000..fbfbedccb1685b722cc09ef4f1f873bfe81f8cb3 GIT binary patch literal 8536 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 JPDHLkV1l+dAyxnY literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret-select/wall-tower-default.png b/source/core/assets/images/turret-select/wall-tower-default.png new file mode 100644 index 0000000000000000000000000000000000000000..bc7ba42f86a4181a4ed574edb88a3b164fac1685 GIT binary patch literal 6163 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 T(EaH(%MW+}H_)orL`MA|0X?Vg literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/screens/TowerType.java b/source/core/src/main/com/csse3200/game/screens/TowerType.java index a290d1b88..00989af8f 100644 --- a/source/core/src/main/com/csse3200/game/screens/TowerType.java +++ b/source/core/src/main/com/csse3200/game/screens/TowerType.java @@ -1,25 +1,36 @@ package com.csse3200.game.screens; public enum TowerType { - WEAPON("Weapon Tower", "The Weapon Tower is a simple and basic turret that fires rapid shots at enemies dealing damage over time.", 0, "0"), - TNT("TNT Tower", "The TNT Tower launches explosive projectiles, dealing area damage to groups of enemies.", 1, "0"), - DROID("Droid Tower", "Droid Towers deploy robotic helpers that assist in combat and provide support to nearby turrets.", 2, "0"), - WALL("Wall Tower", "The Wall Tower creates barriers to block enemy paths, slowing down their progress.", 3, "0"), - FIRE("Fire Tower", "The Fire Tower emits flames, causing damage over time to enemies caught in its fiery radius.", 4, "0"), - STUN("Stun Tower", "The Stun Tower releases electric shocks that temporarily immobilize and damage enemies.", 5, "0"), - INCOME("Income Tower", "The Income Tower generates additional in-game currency over time.", 5, "0"); + WEAPON("Weapon Tower", "The Weapon Tower is a simple and basic turret that fires rapid shots at enemies dealing damage over time.", + 0, "0", "images/turret-select/Weapon-Tower-Default.png", "images/turret-select/Weapon-Tower-Clicked.png"), + TNT("TNT Tower", "The TNT Tower launches explosive projectiles, dealing area damage to groups of enemies.", + 1, "0", "images/turret-select/imageedit_2_8132799771.png", "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png"), + DROID("Droid Tower", "Droid Towers deploy robotic helpers that assist in combat and provide support to nearby turrets.", + 2, "0", "images/turret-select/imageedit_2_8132799771.png", "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png"), + WALL("Wall Tower", "The Wall Tower creates barriers to block enemy paths, slowing down their progress.", + 3, "100", "images/turret-select/wall-tower-default.png", "images/turret-select/wall-tower-clicked.png"), + FIRE("Fire Tower", "The Fire Tower emits flames, causing damage over time to enemies caught in its fiery radius.", + 4, "0", "images/turret-select/imageedit_2_8132799771.png", "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png"), + STUN("Stun Tower", "The Stun Tower releases electric shocks that temporarily immobilize and damage enemies.", + 5, "0", "images/turret-select/imageedit_2_8132799771.png", "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png"), + INCOME("Income Tower", "The Income Tower generates additional in-game currency over time.", + 5, "0", "images/turret-select/imageedit_2_8132799771.png", "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png"); private final String towerName; private final String description; private final int id; private final String cost; + private final String defaultImage; + private final String clickedImage; - TowerType(String towerName, String description, int id, String cost) { + TowerType(String towerName, String description, int id, String cost, String defaultImage, String clickedImage) { this.towerName = towerName; this.description = description; this.id = id; this.cost = cost; + this.defaultImage = defaultImage; + this.clickedImage = clickedImage; } public int getID() { return id; } @@ -30,4 +41,8 @@ public enum TowerType { public String getPrice() { return cost; } + public String getDefaultImage() {return defaultImage;} + + public String getClickedImage() {return clickedImage;} + } diff --git a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java index 8a7c9416a..99a9df408 100644 --- a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java @@ -77,6 +77,7 @@ public TurretSelectionScreen(GdxGame game) { Drawable pressDrawable = new TextureRegionDrawable(new TextureRegion( new Texture("images/ui/Sprites/UI_Glass_Button_Large_Press_01a1.png"))); confirmButton.getStyle().down = pressDrawable; + confirmButton.pad(0,0,6,0); confirmButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -104,8 +105,10 @@ public void clicked(InputEvent event, float x, float y) { Table turretTable = new Table(); turretTable.center(); // Center the contents of the nested table - TextButton button = createButton("images/turret-select/imageedit_2_8132799771.png", - "images/ui/Sprites/UI_Glass_Frame_Lite_01a.png", turret.getPrice()); + TextButton button = createButton(turret.getDefaultImage(), + turret.getClickedImage(), turret.getPrice()); + + button.pad(103, 15, 0, 0); button.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { diff --git a/source/core/src/main/com/csse3200/game/screens/Turrets.java b/source/core/src/main/com/csse3200/game/screens/Turrets.java deleted file mode 100644 index dcd126fef..000000000 --- a/source/core/src/main/com/csse3200/game/screens/Turrets.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.csse3200.game.screens; - -import com.badlogic.gdx.Gdx; - -public class Turrets { - public final static int[] BASIC = { - }; -} From 00397a39166e3659c880d50af38b899161ccf1dd Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Sun, 1 Oct 2023 20:37:26 +1000 Subject: [PATCH 14/49] Added helper function to get a reference to tasks from the AITaskComponent --- .../game/ai/tasks/AITaskComponent.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java index a0a91095b..bcebdb947 100644 --- a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java +++ b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java @@ -1,6 +1,7 @@ package com.csse3200.game.ai.tasks; import com.csse3200.game.components.Component; +import com.csse3200.game.components.ComponentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +36,24 @@ public AITaskComponent addTask(PriorityTask task) { return this; } + /** + * Get a task from the list of tasks. This can be used to get a reference to + * a task to modify it. This is inspired from Entity.getComponent(). + * + * @param task The task to get + * @return A reference to a task with the given class + * @param The type of task to get + */ + public T getTask(Class task) { + for (PriorityTask priorityTask : priorityTasks) { + if (priorityTask.getClass() == task) { + return (T) priorityTask; + } + } + logger.info("Task {} not found", task); + return null; + } + /** * On update, run the current highest priority task. If it's a different one, stop the old one and * start the new one. If the highest priority task has negative priority, no task will be run. From 126efac7c0cad4550f1f53252962e8e95641480c Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Sun, 1 Oct 2023 20:38:16 +1000 Subject: [PATCH 15/49] Setting up the structure for implementing moving an engineer --- .../csse3200/game/input/EngineerInputComponent.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index ff6584c5b..495b246f9 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -20,6 +20,8 @@ public class EngineerInputComponent extends InputComponent { private Camera camera; private EntityService entityService; + private Entity selectedEngineer = null; + public EngineerInputComponent(Game game, Camera camera) { this.game = game; this.camera = camera; @@ -35,9 +37,15 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { // Case when engineer is not clicked if (engineer == null || engineer.getComponent(HumanAnimationController.class) == null) { - return false; + if (selectedEngineer == null) { + return false; + } + // TODO: handle moving the engineer to cursorPosition + } + this.selectedEngineer = engineer; + // Case when engineer is clicked AnimationRenderComponent animator = engineer.getComponent(AnimationRenderComponent.class); String currentAnimation = animator.getCurrentAnimation(); From c9abba6b6c4326852735186fbbde2b528d1e4427 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Sun, 1 Oct 2023 21:00:52 +1000 Subject: [PATCH 16/49] Added basic movement, currently some bugs --- .../tasks/human/HumanMovementTask.java | 10 +++++++++- .../game/input/EngineerInputComponent.java | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanMovementTask.java b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanMovementTask.java index fa589460f..933ffacc1 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanMovementTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanMovementTask.java @@ -2,6 +2,7 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; @@ -10,7 +11,7 @@ * Move a human entity to a given position, finishing when you get close enough. Requires an entity with a * PhysicsMovementComponent. */ -public class HumanMovementTask extends DefaultTask { +public class HumanMovementTask extends DefaultTask implements PriorityTask { private final GameTime gameTime; private Vector2 target; private float stopDistance = 0.01f; @@ -18,6 +19,8 @@ public class HumanMovementTask extends DefaultTask { private Vector2 lastPos; private PhysicsMovementComponent movementComponent; + private int priority = 1000; // default priority + public HumanMovementTask(Vector2 target) { this.target = target; this.gameTime = ServiceLocator.getTimeSource(); @@ -85,4 +88,9 @@ private void checkIfStuck() { private boolean didMove() { return owner.getEntity().getPosition().dst2(lastPos) > 0.001f; } + + @Override + public int getPriority() { + return priority; + } } diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 495b246f9..46b713d30 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -3,8 +3,12 @@ import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.csse3200.game.ai.tasks.AITaskComponent; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.ai.tasks.Task; import com.csse3200.game.components.npc.EngineerMenuComponent; import com.csse3200.game.components.player.HumanAnimationController; +import com.csse3200.game.components.tasks.human.HumanMovementTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.EngineerFactory; @@ -41,7 +45,8 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { return false; } // TODO: handle moving the engineer to cursorPosition - + moveEngineer(cursorPosition); + return true; } this.selectedEngineer = engineer; @@ -65,4 +70,14 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { return true; } + private void moveEngineer(Vector2 cursorPosition) { + if (selectedEngineer == null) { + logger.info("Trying to move an engineer that is not selected"); + } + AITaskComponent movementTask = selectedEngineer.getComponent(AITaskComponent.class); + HumanMovementTask task = new HumanMovementTask(cursorPosition); + movementTask.addTask(task); + logger.info("Moving engineer to {}", cursorPosition); + } + } From d85fbbaf9ff082f0f2fa401350123b0a625fb5d5 Mon Sep 17 00:00:00 2001 From: Nawal Date: Sun, 1 Oct 2023 22:38:27 +1000 Subject: [PATCH 17/49] Added a menu that appears when an engineer is clicked --- .../components/npc/EngineerMenuComponent.java | 91 ++++++++++++++++++- .../player/HumanAnimationController.java | 10 ++ .../game/input/EngineerInputComponent.java | 6 +- 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java index 0ab0ff52e..4616590a2 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -2,16 +2,25 @@ import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.csse3200.game.components.player.HumanAnimationController; +import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.ui.UIComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EngineerMenuComponent extends UIComponent { + private Logger logger = LoggerFactory.getLogger(EngineerMenuComponent.class); Table table; @Override @@ -24,24 +33,96 @@ public void draw(SpriteBatch batch) { // draw is handled by the stage } + /** + * Creates a menu for the engineer + * @param x cursor x coordinate + * @param y cursor y coordinate + * @param camera camera of the game + */ public void createMenu(float x, float y, Camera camera) { - table = new Table(); + this.table = createTable(x, y, camera); + // add buttons + TextButton moveButton = createButton("Move"); + TextButton repairButton = createButton("Repair"); + + // add listeners to buttons + AnimationRenderComponent animator = getEntity().getComponent(AnimationRenderComponent.class); + HumanAnimationController controller = getEntity().getComponent(HumanAnimationController.class); + + moveButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + controller.deselectEngineer(animator.getCurrentAnimation()); + logger.info("Move button clicked"); + } + }); + + repairButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + controller.deselectEngineer(animator.getCurrentAnimation()); + logger.info("Repair button clicked"); + } + }); + + table.add(moveButton).grow(); + table.row(); + table.add(repairButton).grow(); + table.row(); + stage.addActor(table); + + } + + /** + * Creates a table for the menu + * @param x cursor x coordinate + * @param y cursor y coordinate + * @param camera camera of the game + * @return table for the menu + */ + private Table createTable(float x, float y, Camera camera) { + Table table = new Table(); + table.top(); + table.defaults().pad(0).space(0); + table.setSize(90, 60); // fixed table size + + // convert cursor position to stage coordinates Vector3 entityCoordinates = new Vector3(x, y, 0); Vector3 entityScreenCoordinate = camera.project(entityCoordinates); Vector2 stageCoordinates = stage.screenToStageCoordinates( new Vector2(entityScreenCoordinate.x, entityScreenCoordinate.y)); stage.getViewport().unproject(stageCoordinates); + table.setPosition(stageCoordinates.x, stageCoordinates.y); - table.setPosition(x, y); - table.setFillParent(true); - String imageFilePath = "images/ui/Sprites/UI_Glass_Banner_01b.png"; + // set table background + String imageFilePath = "images/ui/Sprites/UI_Glass_Frame_Standard_01a.png"; Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture(imageFilePath))); table.setBackground(drawable); - //stage.addActor(table); + return table; + } + + /** + * Creates a button for the menu + * @param text text to be displayed on the button + * @return the button + */ + private TextButton createButton(String text) { + String upImageFilePath = "images/ui/Sprites/UI_Glass_Button_Medium_Lock_01a2.png"; + String downImageFilePath = "images/ui/Sprites/UI_Glass_Button_Medium_Press_01a2.png"; + + Drawable upDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(upImageFilePath))); + Drawable downDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(downImageFilePath))); + TextButton button = new TextButton(text, + new TextButton.TextButtonStyle(upDrawable, downDrawable, null, new BitmapFont())); + button.setTransform(true); + return button; } + /** + * Removes the menu from the stage + */ public void removeMenu() { table.clear(); table.remove(); diff --git a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java index 9308d7eb5..c56f4ab72 100644 --- a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java @@ -2,6 +2,7 @@ import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; +import com.csse3200.game.components.npc.EngineerMenuComponent; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; @@ -205,4 +206,13 @@ public boolean isClicked() { public void setClicked(boolean clicked) { this.clicked = clicked; } + + public void deselectEngineer(String currentAnimation) { + AnimationRenderComponent animator = this.entity.getComponent(AnimationRenderComponent.class); + EngineerMenuComponent menu = this.entity.getComponent(EngineerMenuComponent.class); + + animator.startAnimation(currentAnimation.substring(0, currentAnimation.lastIndexOf('_'))); + menu.removeMenu(); + setClicked(false); + } } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index ff6584c5b..b39cbd151 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -45,15 +45,13 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { EngineerMenuComponent menu = engineer.getComponent(EngineerMenuComponent.class); // outline image if it is not already outlined and vice versa if (currentAnimation.contains("_outline")) { - animator.startAnimation(currentAnimation.substring(0, currentAnimation.lastIndexOf('_'))); - menu.removeMenu(); - controller.setClicked(false); + controller.deselectEngineer(currentAnimation); + logger.info("Engineer deselected"); } else { animator.startAnimation(currentAnimation + "_outline"); menu.createMenu(cursorPosition.x, cursorPosition.y, camera); controller.setClicked(true); } - return true; } From 43908ff4d90de3f326cbc3cf50cea3793d99e2d5 Mon Sep 17 00:00:00 2001 From: Nawal Date: Sun, 1 Oct 2023 22:46:10 +1000 Subject: [PATCH 18/49] Added comments --- .../csse3200/game/components/npc/EngineerMenuComponent.java | 4 ++-- .../game/components/player/HumanAnimationController.java | 5 +++++ .../main/com/csse3200/game/input/EngineerInputComponent.java | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java index 4616590a2..dca526b01 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -54,7 +54,7 @@ public void createMenu(float x, float y, Camera camera) { @Override public void clicked(InputEvent event, float x, float y) { controller.deselectEngineer(animator.getCurrentAnimation()); - logger.info("Move button clicked"); + //logger.info("Move button clicked"); } }); @@ -62,7 +62,7 @@ public void clicked(InputEvent event, float x, float y) { @Override public void clicked(InputEvent event, float x, float y) { controller.deselectEngineer(animator.getCurrentAnimation()); - logger.info("Repair button clicked"); + //logger.info("Repair button clicked"); } }); diff --git a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java index c56f4ab72..bcaf10f1f 100644 --- a/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/player/HumanAnimationController.java @@ -207,6 +207,11 @@ public void setClicked(boolean clicked) { this.clicked = clicked; } + /** + * Deseelects the engineer entity by starting the appropriate animation without an outline + * and removes the engineer menu from the stage + * @param currentAnimation the current animation of the entity + */ public void deselectEngineer(String currentAnimation) { AnimationRenderComponent animator = this.entity.getComponent(AnimationRenderComponent.class); EngineerMenuComponent menu = this.entity.getComponent(EngineerMenuComponent.class); diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index b7a32a440..53200cba1 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -59,7 +59,7 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { // outline image if it is not already outlined and vice versa if (currentAnimation.contains("_outline")) { controller.deselectEngineer(currentAnimation); - logger.info("Engineer deselected"); + //logger.info("Engineer deselected"); } else { animator.startAnimation(currentAnimation + "_outline"); menu.createMenu(cursorPosition.x, cursorPosition.y, camera); From d91ea8ca38a0bd50a080ba64b3d25504643b8608 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Sun, 1 Oct 2023 22:58:39 +1000 Subject: [PATCH 19/49] Added pop-up when a turret is clicked --- .../game/input/UpgradeUIComponent.java | 46 ++++++++++++++++++- .../csse3200/game/screens/MainGameScreen.java | 2 +- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 52a06442c..cb004554d 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -1,9 +1,21 @@ package com.csse3200.game.input; import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.components.gamearea.TowerUpgradeDisplay; import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; @@ -15,16 +27,20 @@ public class UpgradeUIComponent extends InputComponent { private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); private final EntityService entityService; private final Camera camera; + private final Stage stage; + + private Table upgradeTable; int value; /** * Constructor for the UpgradeUIComponent * @param camera the camera to be used, this is the camera that the game is rendered with */ - public UpgradeUIComponent(Camera camera) { + public UpgradeUIComponent(Camera camera, Stage stage) { this.value = ServiceLocator.getCurrencyService().getScrap().getAmount(); this.entityService = ServiceLocator.getEntityService(); this.camera = camera; + this.stage = stage; } /** @@ -35,6 +51,10 @@ public Camera getCamera() { return camera; } + public Stage getStage() { + return stage; + } + /** * When the mouse is clicked, this method is called. * @@ -53,10 +73,34 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null) { logger.info("clicked a turret that is upgradable!"); + createUpgradeTable(clickedEntity, screenX, screenY); + stage.addActor(upgradeTable); return true; } return false; } + private void createUpgradeTable(Entity turretEntity, int screenX, int screenY) { + upgradeTable = new Table(); + upgradeTable.align(Align.top); + upgradeTable.setPosition(screenX, screenY); + + // Create a BitmapFont for the LabelStyle + BitmapFont font = new BitmapFont(); // You can customize this font as needed + + Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/ui/Sprites/UI_Glass_Button_Small_Lock_01a2.png"))); + TextButton.TextButtonStyle style = new TextButton.TextButtonStyle( + drawable, drawable, drawable, new BitmapFont()); + + // create button + TextButton tb = new TextButton("Hello World", style); + tb.setDisabled(true); + + upgradeTable.add(tb); + + upgradeTable.setVisible(true); + } + + } diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index 42afa287f..3dc66d55a 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -97,7 +97,7 @@ public MainGameScreen(GdxGame game) { /* Input components */ InputComponent dropInputHandler = new DropInputComponent(renderer.getCamera().getCamera()); - InputComponent upgradeInputHandler = new UpgradeUIComponent(renderer.getCamera().getCamera()); + InputComponent upgradeInputHandler = new UpgradeUIComponent(renderer.getCamera().getCamera(), renderer.getStage()); ServiceLocator.getInputService().register(dropInputHandler); ServiceLocator.getInputService().register(upgradeInputHandler); From 54fbd423864e760cddc65f3b073f31e90ca1a0a9 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Mon, 2 Oct 2023 11:58:24 +1000 Subject: [PATCH 20/49] Added cleaner functionality for moving, need to now set it to move to a tile position --- .../tasks/human/HumanWanderTask.java | 56 +++++++++++-------- .../game/input/EngineerInputComponent.java | 26 +++++++-- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java index 528348b8a..71b795361 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java @@ -31,6 +31,8 @@ public class HumanWanderTask extends DefaultTask implements PriorityTask { private Task currentTask; private boolean isDead = false; + private boolean isSelected = false; + private boolean hasDied = false; /** @@ -105,35 +107,35 @@ public void update() { // otherwise doing engineer things since engineer is alive else if (!isDead){ doEngineerThings(); - currentTask.update(); } } private void doEngineerThings() { - if (currentTask.getStatus() != Status.ACTIVE) { - - // if the engineer is in move state and update has been called, engineer has arrived at destination - if (currentTask == movementTask) { - startWaiting(); - owner.getEntity().getEvents().trigger(IDLE_EVENT); - - } else if (combatTask.isTargetVisible()) { - float engY = owner.getEntity().getCenterPosition().y; - float targetY = combatTask.fetchTarget().y; - // if the engineer is positioned within the tolerance range of the mob's y position, enter combat state - if (engY < targetY + TOLERANCE && - engY > targetY - TOLERANCE) { - startCombat(); - - // move into position for targeting mob - } else { - Vector2 newPos = new Vector2(owner.getEntity().getPosition().x, combatTask.fetchTarget().y); - startMoving(newPos); - } + if (currentTask.getStatus() == Status.ACTIVE) { + return; + } + + // if the engineer is in move state and update has been called, engineer has arrived at destination + if (currentTask == movementTask) { + startWaiting(); + owner.getEntity().getEvents().trigger(IDLE_EVENT); + } else if (combatTask.isTargetVisible()) { + float engY = owner.getEntity().getCenterPosition().y; + float targetY = combatTask.fetchTarget().y; + // if the engineer is positioned within the tolerance range of the mob's y position, enter combat state + if (engY < targetY + TOLERANCE && + engY > targetY - TOLERANCE) { + startCombat(); + + // move into position for targeting mob + } else if (!this.isSelected()) { + Vector2 newPos = new Vector2(owner.getEntity().getPosition().x, combatTask.fetchTarget().y); + startMoving(newPos); } } } + /** * Handle the dying phase of the entity. Triggers an event to play the appropriate media, * sets HitBox and Collider components to ignore contact (stops the body being pushed around) @@ -150,7 +152,7 @@ private void startDying() { /** * Starts the wait task. */ - private void startWaiting() { + public void startWaiting() { swapTask(waitTask); } @@ -158,7 +160,7 @@ private void startWaiting() { * Starts the movement task, to a particular destination * @param destination the Vector2 position to which the entity needs to move */ - private void startMoving(Vector2 destination) { + public void startMoving(Vector2 destination) { movementTask.setTarget(destination); swapTask(movementTask); } @@ -181,4 +183,12 @@ private void swapTask(Task newTask) { currentTask = newTask; currentTask.start(); } + + private boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + } } diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 46b713d30..a353291ad 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -9,6 +9,7 @@ import com.csse3200.game.components.npc.EngineerMenuComponent; import com.csse3200.game.components.player.HumanAnimationController; import com.csse3200.game.components.tasks.human.HumanMovementTask; +import com.csse3200.game.components.tasks.human.HumanWanderTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.EngineerFactory; @@ -36,6 +37,7 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { Vector3 worldCoordinates = new Vector3((float) screenX , (float) screenY, 0); camera.unproject(worldCoordinates); Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); + camera.project(worldCoordinates); Entity engineer = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); //logger.info("Clicked entity: " + engineer); @@ -44,12 +46,18 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (selectedEngineer == null) { return false; } - // TODO: handle moving the engineer to cursorPosition moveEngineer(cursorPosition); return true; + } else if (engineer.equals(selectedEngineer)) { + // Deselect the engineer by clicking on itself + this.getWanderTask().setSelected(false); + selectedEngineer = null; + return true; } this.selectedEngineer = engineer; + this.getWanderTask().setSelected(true); + logger.info("Engineer size: {}", engineer.getScale()); // Case when engineer is clicked AnimationRenderComponent animator = engineer.getComponent(AnimationRenderComponent.class); @@ -70,14 +78,22 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { return true; } + private HumanWanderTask getWanderTask() { + AITaskComponent movementTask = selectedEngineer.getComponent(AITaskComponent.class); + return movementTask.getTask(HumanWanderTask.class); + } + private void moveEngineer(Vector2 cursorPosition) { if (selectedEngineer == null) { logger.info("Trying to move an engineer that is not selected"); } - AITaskComponent movementTask = selectedEngineer.getComponent(AITaskComponent.class); - HumanMovementTask task = new HumanMovementTask(cursorPosition); - movementTask.addTask(task); - logger.info("Moving engineer to {}", cursorPosition); + + HumanWanderTask wander = this.getWanderTask(); + wander.startWaiting(); + Vector2 enggpos = selectedEngineer.getPosition(); + Vector2 offset = new Vector2(cursorPosition.x > enggpos.x ? 0.17f : -0.6f , cursorPosition.y > enggpos.y ? 0.0f : -0.5f); + Vector2 dest = cursorPosition.add(offset); + wander.startMoving(dest); } } From 8aa9e9869a0e98a84fea4e776b884bcad0cc56b2 Mon Sep 17 00:00:00 2001 From: Nawal Date: Mon, 2 Oct 2023 13:16:20 +1000 Subject: [PATCH 21/49] Engineers can only move after the move button is pressed --- .../components/npc/EngineerMenuComponent.java | 5 +++++ .../game/input/EngineerInputComponent.java | 16 +++++++++++++--- .../com/csse3200/game/input/InputService.java | 9 +++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java index dca526b01..141003d44 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -14,7 +14,9 @@ import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.csse3200.game.components.player.HumanAnimationController; +import com.csse3200.game.input.EngineerInputComponent; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.UIComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,11 +51,14 @@ public void createMenu(float x, float y, Camera camera) { // add listeners to buttons AnimationRenderComponent animator = getEntity().getComponent(AnimationRenderComponent.class); HumanAnimationController controller = getEntity().getComponent(HumanAnimationController.class); + EngineerInputComponent input = ServiceLocator.getInputService().getEngineerInput(); moveButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { + input.setMoveClicked(true); controller.deselectEngineer(animator.getCurrentAnimation()); + //logger.info("Move button clicked"); } }); diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 9db93b947..533d875d1 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -26,6 +26,7 @@ public class EngineerInputComponent extends InputComponent { private EntityService entityService; private Entity selectedEngineer = null; + private boolean moveClicked = false; public EngineerInputComponent(Game game, Camera camera) { this.game = game; @@ -43,15 +44,19 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { // Case when engineer is not clicked if (engineer == null || engineer.getComponent(HumanAnimationController.class) == null) { - if (selectedEngineer == null) { + if (selectedEngineer != null && moveClicked) { + moveEngineer(cursorPosition); + selectedEngineer = null; + moveClicked = false; + return true; + } else { return false; } - moveEngineer(cursorPosition); - return true; } else if (engineer.equals(selectedEngineer)) { // Deselect the engineer by clicking on itself this.getWanderTask().setSelected(false); selectedEngineer = null; + moveClicked = false; return true; } @@ -74,6 +79,7 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { controller.setClicked(true); } return true; + } private HumanWanderTask getWanderTask() { @@ -94,4 +100,8 @@ private void moveEngineer(Vector2 cursorPosition) { wander.startMoving(dest); } + public void setMoveClicked(boolean moveClicked) { + this.moveClicked = moveClicked; + } + } diff --git a/source/core/src/main/com/csse3200/game/input/InputService.java b/source/core/src/main/com/csse3200/game/input/InputService.java index 6c2e8d2ae..bb9a8dbe0 100644 --- a/source/core/src/main/com/csse3200/game/input/InputService.java +++ b/source/core/src/main/com/csse3200/game/input/InputService.java @@ -27,11 +27,13 @@ public class InputService implements InputProcessor, GestureDetector.GestureList private final List inputHandlers = new ArrayList<>(); private final InputFactory inputFactory; + private EngineerInputComponent engineerInputComponent; public InputService() { this(InputFactory.createFromInputType(inputType)); } + public InputService(InputFactory inputFactory) { this.inputFactory = inputFactory; Gdx.input.setInputProcessor(this); @@ -46,6 +48,10 @@ public InputFactory getInputFactory() { return inputFactory; } + public EngineerInputComponent getEngineerInput() { + return engineerInputComponent; + } + /** * Register an input handler based on its priority and reorder inputHandlers. * @@ -53,6 +59,9 @@ public InputFactory getInputFactory() { */ public void register(InputComponent inputHandler) { logger.debug("Registering input handler {}", inputHandler); + if (inputHandler instanceof EngineerInputComponent) { + engineerInputComponent = (EngineerInputComponent) inputHandler; + } inputHandlers.add(inputHandler); inputHandlers.sort(comparator); } From fe1be661ec8af42aae8b8a2cf4de90fe87d22fd7 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:19:15 +1000 Subject: [PATCH 22/49] Made changes to UI upgrade box --- .../game/input/UpgradeUIComponent.java | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index cb004554d..8d55d1872 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -9,13 +9,13 @@ import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; -import com.badlogic.gdx.utils.Align; import com.csse3200.game.areas.ForestGameArea; -import com.csse3200.game.components.gamearea.TowerUpgradeDisplay; +import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; @@ -29,6 +29,8 @@ public class UpgradeUIComponent extends InputComponent { private final Camera camera; private final Stage stage; + + private Table upgradeTable; int value; @@ -41,6 +43,8 @@ public UpgradeUIComponent(Camera camera, Stage stage) { this.entityService = ServiceLocator.getEntityService(); this.camera = camera; this.stage = stage; + + } /** @@ -73,34 +77,66 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null) { logger.info("clicked a turret that is upgradable!"); - createUpgradeTable(clickedEntity, screenX, screenY); + createUpgradeTable(clickedEntity); + Vector2 UICoordinates = stage.screenToStageCoordinates(new Vector2(screenX, screenY)); + upgradeTable.setPosition(UICoordinates.x, UICoordinates.y); stage.addActor(upgradeTable); return true; } return false; } - private void createUpgradeTable(Entity turretEntity, int screenX, int screenY) { + private void createUpgradeTable(Entity turretEntity) { upgradeTable = new Table(); - upgradeTable.align(Align.top); - upgradeTable.setPosition(screenX, screenY); - - // Create a BitmapFont for the LabelStyle - BitmapFont font = new BitmapFont(); // You can customize this font as needed + upgradeTable.top(); + upgradeTable.defaults().pad(0).space(0); + upgradeTable.setSize(100,100); + Table innerUpgradeTable = new Table(); + innerUpgradeTable.top(); + innerUpgradeTable.defaults().pad(0).space(0); + innerUpgradeTable.setSize(100,100); + // set table background + String imageFilePath = "images/ui/Sprites/UI_Glass_Frame_Standard_01a.png"; + String upgradeButtonFilePath = "images/economy/scrapBanner.png"; + Drawable drawableBackground = new TextureRegionDrawable(new TextureRegion(new Texture(imageFilePath))); + innerUpgradeTable.setBackground(drawableBackground); +// upgradeTable.setBackground(drawableBackground); Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/ui/Sprites/UI_Glass_Button_Small_Lock_01a2.png"))); + Drawable econDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(upgradeButtonFilePath))); TextButton.TextButtonStyle style = new TextButton.TextButtonStyle( drawable, drawable, drawable, new BitmapFont()); - + TextButton.TextButtonStyle econStyle = new TextButton.TextButtonStyle( + econDrawable, econDrawable, econDrawable, new BitmapFont()); // create button - TextButton tb = new TextButton("Hello World", style); - tb.setDisabled(true); + int maxHealth = turretEntity.getComponent(CombatStatsComponent.class).getMaxHealth(); + Label health = new Label(String.format("Max Health: %d", maxHealth), createLabelStyle()); + Label attack = new Label(String.format("Attack: %d", turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack()), createLabelStyle()); + TextButton closeButton = new TextButton("X", style); + TextButton upgradeButton = new TextButton("Upgrade", style); + upgradeTable.add(closeButton).right().top(); + upgradeTable.row(); + + innerUpgradeTable.row(); + innerUpgradeTable.add(health); + innerUpgradeTable.row(); + innerUpgradeTable.add(attack); + innerUpgradeTable.row(); + innerUpgradeTable.add(upgradeButton); + upgradeTable.add(innerUpgradeTable).center().expand().row(); - upgradeTable.add(tb); upgradeTable.setVisible(true); } + private LabelStyle createLabelStyle() { + LabelStyle style = new LabelStyle(); + + style.font = new BitmapFont(); + style.fontColor = Color.WHITE; + return style; + } + } From 165356dd7c9053696c9ce8682be97d46643518ec Mon Sep 17 00:00:00 2001 From: Nawal Date: Mon, 2 Oct 2023 13:28:25 +1000 Subject: [PATCH 23/49] fixed some bugs with deselecting the engineer --- .../game/input/EngineerInputComponent.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 533d875d1..c2f5a40e3 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -52,34 +52,36 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { } else { return false; } - } else if (engineer.equals(selectedEngineer)) { - // Deselect the engineer by clicking on itself - this.getWanderTask().setSelected(false); - selectedEngineer = null; - moveClicked = false; - return true; } - - this.selectedEngineer = engineer; - this.getWanderTask().setSelected(true); - logger.info("Engineer size: {}", engineer.getScale()); - // Case when engineer is clicked AnimationRenderComponent animator = engineer.getComponent(AnimationRenderComponent.class); String currentAnimation = animator.getCurrentAnimation(); HumanAnimationController controller = engineer.getComponent(HumanAnimationController.class); EngineerMenuComponent menu = engineer.getComponent(EngineerMenuComponent.class); - // outline image if it is not already outlined and vice versa - if (currentAnimation.contains("_outline")) { - controller.deselectEngineer(currentAnimation); - //logger.info("Engineer deselected"); + + if (engineer.equals(selectedEngineer)) { + // Deselect the engineer by clicking on itself + this.getWanderTask().setSelected(false); + selectedEngineer = null; + moveClicked = false; + if (currentAnimation.contains("_outline")) { + controller.deselectEngineer(currentAnimation); + //logger.info("Engineer deselected"); + } } else { - animator.startAnimation(currentAnimation + "_outline"); - menu.createMenu(cursorPosition.x, cursorPosition.y, camera); - controller.setClicked(true); + this.selectedEngineer = engineer; + this.getWanderTask().setSelected(true); + moveClicked = false; + logger.info("Engineer size: {}", engineer.getScale()); + + // outline image if it is not already outlined and vice versa + if (!currentAnimation.contains("_outline")) { + animator.startAnimation(currentAnimation + "_outline"); + menu.createMenu(cursorPosition.x, cursorPosition.y, camera); + controller.setClicked(true); + } } return true; - } private HumanWanderTask getWanderTask() { From 21ec7f88acccc30d940fc4a7fe46e690bcb600e3 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:34:27 +1000 Subject: [PATCH 24/49] Fix Upgrade Tower UI Look --- .../com/csse3200/game/input/UpgradeUIComponent.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 8d55d1872..7a94cca96 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -90,11 +90,11 @@ private void createUpgradeTable(Entity turretEntity) { upgradeTable = new Table(); upgradeTable.top(); upgradeTable.defaults().pad(0).space(0); - upgradeTable.setSize(100,100); + upgradeTable.setSize(60,60); Table innerUpgradeTable = new Table(); innerUpgradeTable.top(); - innerUpgradeTable.defaults().pad(0).space(0); - innerUpgradeTable.setSize(100,100); + innerUpgradeTable.defaults().pad(10).space(0).padBottom(1); + innerUpgradeTable.setSize(60,60); // set table background String imageFilePath = "images/ui/Sprites/UI_Glass_Frame_Standard_01a.png"; String upgradeButtonFilePath = "images/economy/scrapBanner.png"; @@ -118,11 +118,11 @@ private void createUpgradeTable(Entity turretEntity) { upgradeTable.row(); innerUpgradeTable.row(); - innerUpgradeTable.add(health); + innerUpgradeTable.add(health).expandX().left(); innerUpgradeTable.row(); - innerUpgradeTable.add(attack); + innerUpgradeTable.add(attack).expandX().left(); innerUpgradeTable.row(); - innerUpgradeTable.add(upgradeButton); + innerUpgradeTable.add(upgradeButton).expandX().fillX(); upgradeTable.add(innerUpgradeTable).center().expand().row(); From 60e89fccfea00452ecec24369c5fc35c789ff762 Mon Sep 17 00:00:00 2001 From: Nawal Date: Mon, 2 Oct 2023 13:46:21 +1000 Subject: [PATCH 25/49] Added function to EntityService that gets entity at specified position and layer --- .../com/csse3200/game/entities/EntityService.java | 13 +++++++++++++ .../csse3200/game/input/EngineerInputComponent.java | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index 7adb4fc8e..3511d598b 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -173,4 +173,17 @@ private boolean entityContainsPosition(Entity entity, float x, float y) { return (x >= entityX && x <= entityX + entityWidth && y >= entityY && y <= entityY + entityHeight); } + public Entity getEntityAtPositionLayer(float x, float y, short layer) { + for (int i = 0; i < entities.size; i++) { + Entity entity = entities.get(i); + if (entityContainsPosition(entity, x, y)) { + HitboxComponent hitBox = entity.getComponent(HitboxComponent.class); + if (hitBox != null && PhysicsLayer.contains(layer, hitBox.getLayer())) { + return entity; + } + } + } + return null; + } + } diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index c2f5a40e3..3f28581e5 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -13,6 +13,7 @@ import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.EngineerFactory; +import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; @@ -39,7 +40,7 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { camera.unproject(worldCoordinates); Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); camera.project(worldCoordinates); - Entity engineer = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); + Entity engineer = entityService.getEntityAtPositionLayer(cursorPosition.x, cursorPosition.y, PhysicsLayer.ENGINEER); //logger.info("Clicked entity: " + engineer); // Case when engineer is not clicked From 7623436e0df9605cbe68a9e565532e8a4e05abfa Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Mon, 2 Oct 2023 13:50:39 +1000 Subject: [PATCH 26/49] Added a repair system, having issues with tower bounding boxes --- .../csse3200/game/areas/ForestGameArea.java | 2 ++ .../components/npc/EngineerMenuComponent.java | 19 +++++++++++++++++ .../tasks/human/HumanWanderTask.java | 2 +- .../tower/TowerUpgraderComponent.java | 2 +- .../game/input/EngineerInputComponent.java | 21 +++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 4ccf3ece5..f3c9bddef 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -258,7 +258,9 @@ public void create() { player.getEvents().addListener("spawnWave", this::spawnWave); Entity engineer = EngineerFactory.createEngineer(); + Entity tower = TowerFactory.createDroidTower(); spawnEntityAt(engineer, new GridPoint2(2, 4), true, true); + spawnEntityAt(tower, new GridPoint2(2, 5), true, true); // playMusic(); // spawnXenoGrunts(); diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java index dca526b01..59efde153 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -13,8 +13,14 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Array; import com.csse3200.game.components.player.HumanAnimationController; +import com.csse3200.game.components.tower.TowerUpgraderComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.UIComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,6 +122,19 @@ private TextButton createButton(String text) { Drawable downDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(downImageFilePath))); TextButton button = new TextButton(text, new TextButton.TextButtonStyle(upDrawable, downDrawable, null, new BitmapFont())); + button.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + EntityService entityService = ServiceLocator.getEntityService(); + Array tower = entityService.getEntitiesInLayer(getEntity(), 0.1f, PhysicsLayer.TOWER); + if (tower.size == 0) { + logger.info("No tower to repair"); + return; + } + logger.info("repairing"); + tower.get(0).getComponent(TowerUpgraderComponent.class).repairTower(); + } + }); button.setTransform(true); return button; } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java index 71b795361..499ce2937 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/human/HumanWanderTask.java @@ -168,7 +168,7 @@ public void startMoving(Vector2 destination) { /** * Starts the combat task. */ - private void startCombat() { + public void startCombat() { swapTask(combatTask); } diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java index bc04c1d1d..5717ec04f 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java @@ -58,7 +58,7 @@ void upgradeTowerMaxHealth(int increase) { /** * Restores the tower's health to its maximum health. */ - void repairTower() { + public void repairTower() { int maxHealth = getEntity().getComponent(CombatStatsComponent.class).getMaxHealth(); getEntity().getComponent(CombatStatsComponent.class).setHealth(maxHealth); } diff --git a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java index 9db93b947..c9df3ff54 100644 --- a/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/EngineerInputComponent.java @@ -1,5 +1,7 @@ package com.csse3200.game.input; import com.badlogic.gdx.Game; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; @@ -76,6 +78,25 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { return true; } + @Override + public boolean keyDown(int keycode) { + if (selectedEngineer == null) { + return false; + } + + + if (Gdx.input.isKeyPressed(Input.Keys.P)) { + manualShoot(); + } + return true; + } + + private void manualShoot() { + HumanWanderTask wander = this.getWanderTask(); + wander.startWaiting(); + wander.startCombat(); + } + private HumanWanderTask getWanderTask() { AITaskComponent movementTask = selectedEngineer.getComponent(AITaskComponent.class); return movementTask.getTask(HumanWanderTask.class); From 685752b1b30a5a1f09596206f37a36bce108184e Mon Sep 17 00:00:00 2001 From: Nawal Date: Mon, 2 Oct 2023 15:05:45 +1000 Subject: [PATCH 27/49] moved button click listener --- .../components/npc/EngineerMenuComponent.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java index a10e9975e..096fb5962 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/EngineerMenuComponent.java @@ -72,6 +72,14 @@ public void clicked(InputEvent event, float x, float y) { @Override public void clicked(InputEvent event, float x, float y) { controller.deselectEngineer(animator.getCurrentAnimation()); + EntityService entityService = ServiceLocator.getEntityService(); + Array tower = entityService.getEntitiesInLayer(getEntity(), 0.1f, PhysicsLayer.TOWER); + if (tower.size == 0) { + logger.info("No tower to repair"); + return; + } + logger.info("repairing"); + tower.get(0).getComponent(TowerUpgraderComponent.class).repairTower(); //logger.info("Repair button clicked"); } }); @@ -126,19 +134,7 @@ private TextButton createButton(String text) { Drawable downDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(downImageFilePath))); TextButton button = new TextButton(text, new TextButton.TextButtonStyle(upDrawable, downDrawable, null, new BitmapFont())); - button.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - EntityService entityService = ServiceLocator.getEntityService(); - Array tower = entityService.getEntitiesInLayer(getEntity(), 0.1f, PhysicsLayer.TOWER); - if (tower.size == 0) { - logger.info("No tower to repair"); - return; - } - logger.info("repairing"); - tower.get(0).getComponent(TowerUpgraderComponent.class).repairTower(); - } - }); + button.setTransform(true); return button; } From 325c580651dc0586cc3a8bb3c0d014a6d1444db3 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:00:33 +1000 Subject: [PATCH 28/49] Added health upgrade, repair and attack upgrade --- .../csse3200/game/areas/ForestGameArea.java | 5 +- .../tower/TowerUpgraderComponent.java | 2 +- .../game/entities/factories/TowerFactory.java | 2 + .../game/input/UpgradeUIComponent.java | 155 ++++++++++++++---- 4 files changed, 125 insertions(+), 39 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 603a00b61..8ca0a96c2 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -268,7 +268,7 @@ public void create() { // spawnSplittingXenoGrunt(15, 4); // spawnScrap(); // spawnTNTTower(); -// spawnWeaponTower(); + spawnWeaponTower(); // spawnGapScanners(); // spawnDroidTower(); spawnScrap(); @@ -604,6 +604,7 @@ private void spawnWeaponTower() { Entity stunTower = TowerFactory.createStunTower(); spawnEntityAt(fireTower, randomPos1, true, true); spawnEntityAt(stunTower, randomPos2, true, true); + spawnEntityAt(wallTower, randomPos2, true, true); } } @@ -704,7 +705,7 @@ private void spawnIncome() { GridPoint2 minPos = new GridPoint2(0, 0); GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); - for (int i = 0; i < 50; i++) { + for (int i = 0; i < 5; i++) { GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); Entity towerfactory = TowerFactory.createIncomeTower(); spawnEntityAt(towerfactory, randomPos, true, true); diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java index bc04c1d1d..937d52a6b 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java @@ -25,7 +25,7 @@ public void create() { * @param upgradeType An enum indicating the type of upgrade to do * @param value How much the upgrade should change the tower's stats, if applicable */ - void upgradeTower(UPGRADE upgradeType, int value) { + public void upgradeTower(UPGRADE upgradeType, int value) { switch (upgradeType) { case ATTACK -> {upgradeTowerAttack(value);} case MAXHP -> {upgradeTowerMaxHealth(value);} 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 f3880c68c..84e896390 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 @@ -35,6 +35,8 @@ public class TowerFactory { private static final int COMBAT_TASK_PRIORITY = 2; private static final int WEAPON_TOWER_MAX_RANGE = 40; + + private static final int BASE_FIRE_RATE = 1; private static final int TNT_TOWER_MAX_RANGE = 6; private static final int TNT_TOWER_RANGE = 6; private static final int TNT_KNOCK_BACK_FORCE = 10; diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 7a94cca96..aaefb9dc8 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -7,15 +7,18 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.csse3200.game.areas.ForestGameArea; import com.csse3200.game.components.CombatStatsComponent; +import com.csse3200.game.components.tasks.TowerCombatTask; import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; @@ -23,16 +26,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashMap; +import java.util.Map; + public class UpgradeUIComponent extends InputComponent { private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); private final EntityService entityService; private final Camera camera; private final Stage stage; + private int value; - - private Table upgradeTable; - int value; + // Create a map to store upgrade tables for each turret entity + private Map upgradeTables = new HashMap<>(); /** * Constructor for the UpgradeUIComponent @@ -43,8 +49,6 @@ public UpgradeUIComponent(Camera camera, Stage stage) { this.entityService = ServiceLocator.getEntityService(); this.camera = camera; this.stage = stage; - - } /** @@ -59,48 +63,63 @@ public Stage getStage() { return stage; } - /** - * When the mouse is clicked, this method is called. - * - * @param screenX The x coordinate, origin is in the upper left corner - * @param screenY The y coordinate, origin is in the upper left corner - * @param pointer the pointer for the event. - * @param button the button - * @return - */ @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { - Vector3 worldCoordinates = new Vector3((float) screenX , (float) screenY, 0); - getCamera().unproject(worldCoordinates); // translate from screen to world coordinates + // Clear all existing upgrade tables + + + Vector3 worldCoordinates = new Vector3((float) screenX, (float) screenY, 0); + getCamera().unproject(worldCoordinates); Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); Entity clickedEntity = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null) { logger.info("clicked a turret that is upgradable!"); - createUpgradeTable(clickedEntity); - Vector2 UICoordinates = stage.screenToStageCoordinates(new Vector2(screenX, screenY)); - upgradeTable.setPosition(UICoordinates.x, UICoordinates.y); - stage.addActor(upgradeTable); + clearUpgradeTables(); + // Check if there is an existing upgrade table for this turret entity + Table existingUpgradeTable = upgradeTables.get(clickedEntity); + + if (existingUpgradeTable != null) { + // If an upgrade table already exists, show it + stage.addActor(existingUpgradeTable); + } else { + // If no upgrade table exists, create and store a new one + Table newUpgradeTable = createUpgradeTable(clickedEntity); + Vector2 UICoordinates = stage.screenToStageCoordinates(new Vector2(screenX, screenY)); + newUpgradeTable.setPosition(UICoordinates.x, UICoordinates.y); + stage.addActor(newUpgradeTable); + + // Store the new upgrade table in the map + upgradeTables.put(clickedEntity, newUpgradeTable); + } + return true; } return false; } - private void createUpgradeTable(Entity turretEntity) { - upgradeTable = new Table(); + // Create a method to clear all existing upgrade tables + private void clearUpgradeTables() { + for (Table upgradeTable : upgradeTables.values()) { + upgradeTable.remove(); + } + upgradeTables.clear(); + } + + private Table createUpgradeTable(Entity turretEntity) { + Table upgradeTable = new Table(); upgradeTable.top(); upgradeTable.defaults().pad(0).space(0); - upgradeTable.setSize(60,60); + upgradeTable.setSize(60, 60); Table innerUpgradeTable = new Table(); innerUpgradeTable.top(); innerUpgradeTable.defaults().pad(10).space(0).padBottom(1); - innerUpgradeTable.setSize(60,60); + innerUpgradeTable.setSize(60, 60); // set table background String imageFilePath = "images/ui/Sprites/UI_Glass_Frame_Standard_01a.png"; String upgradeButtonFilePath = "images/economy/scrapBanner.png"; Drawable drawableBackground = new TextureRegionDrawable(new TextureRegion(new Texture(imageFilePath))); innerUpgradeTable.setBackground(drawableBackground); -// upgradeTable.setBackground(drawableBackground); Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/ui/Sprites/UI_Glass_Button_Small_Lock_01a2.png"))); Drawable econDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(upgradeButtonFilePath))); @@ -110,33 +129,97 @@ private void createUpgradeTable(Entity turretEntity) { econDrawable, econDrawable, econDrawable, new BitmapFont()); // create button int maxHealth = turretEntity.getComponent(CombatStatsComponent.class).getMaxHealth(); - Label health = new Label(String.format("Max Health: %d", maxHealth), createLabelStyle()); - Label attack = new Label(String.format("Attack: %d", turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack()), createLabelStyle()); + int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); + turretEntity.getComponent(CombatStatsComponent.class).setHealth(5); // for testing + int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); + Label healthLabel = new Label(String.format("Health:%d/%d", currentHealth, maxHealth), createLabelStyle()); + Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); TextButton closeButton = new TextButton("X", style); - TextButton upgradeButton = new TextButton("Upgrade", style); + closeButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + upgradeTable.remove(); + // Remove the upgrade table from the map + upgradeTables.remove(turretEntity); + } + }); + + TextButton upgradeHealth = new TextButton("+H", style); + upgradeHealth.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + if (value >= 100) { + value -= 100; + ServiceLocator.getCurrencyService().getScrap().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.MAXHP, 10); + int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); + int maxHealth = turretEntity.getComponent(CombatStatsComponent.class).getMaxHealth(); + healthLabel.setText(String.format("Health:%d/%d", currentHealth, maxHealth)); + } + } + }); + + TextButton upgradeAttack = new TextButton("+A", style); + upgradeAttack.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + if (value >= 10) { + value -= 10; + ServiceLocator.getCurrencyService().getScrap().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.ATTACK, 5); + + int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); + attackLabel.setText(String.format("Attack: %d", attack)); + } + } + }); + + TextButton repairButton = new TextButton("R", style); + repairButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + if (value >= 100) { + value -= 100; + ServiceLocator.getCurrencyService().getScrap().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.REPAIR, 0); + int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); + healthLabel.setText(String.format("Health:%d/%d", currentHealth, maxHealth)); + } + } + }); + upgradeTable.add(closeButton).right().top(); upgradeTable.row(); innerUpgradeTable.row(); - innerUpgradeTable.add(health).expandX().left(); + innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); - innerUpgradeTable.add(attack).expandX().left(); + if (attack != 0) { + innerUpgradeTable.add(attackLabel).expandX().left(); + } innerUpgradeTable.row(); - innerUpgradeTable.add(upgradeButton).expandX().fillX(); + innerUpgradeTable.add(upgradeHealth).expandX().fillX(); + if (attack != 0) { + innerUpgradeTable.add(upgradeAttack).expandX().fillX(); + } + innerUpgradeTable.add(repairButton).expandX().fillX(); upgradeTable.add(innerUpgradeTable).center().expand().row(); - upgradeTable.setVisible(true); + return upgradeTable; } private LabelStyle createLabelStyle() { LabelStyle style = new LabelStyle(); - style.font = new BitmapFont(); style.fontColor = Color.WHITE; return style; } - - - } From cb06930fcd83209db511d152a90ee324e51a22ec Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:44:44 +1000 Subject: [PATCH 29/49] Added config attackRate to all existing towers --- .../game/ai/tasks/AITaskComponent.java | 2 +- .../components/tasks/TowerCombatTask.java | 1 + .../tower/UpgradableStatsComponent.java | 19 +++++++++++++++++++ .../entities/configs/DroidTowerConfig.java | 2 ++ .../entities/configs/FireTowerConfig.java | 2 ++ .../entities/configs/IncomeTowerConfig.java | 2 ++ .../entities/configs/StunTowerConfig.java | 2 ++ .../entities/configs/TNTTowerConfigs.java | 2 ++ .../entities/configs/WallTowerConfig.java | 2 ++ .../entities/configs/WeaponTowerConfig.java | 1 + .../game/entities/factories/TowerFactory.java | 3 +-- .../game/input/UpgradeUIComponent.java | 8 +++++++- 12 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/components/tower/UpgradableStatsComponent.java diff --git a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java index a0a91095b..14c42b74e 100644 --- a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java +++ b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java @@ -86,7 +86,7 @@ public void restore() { this.update(); } - private PriorityTask getHighestPriorityTask() { + public PriorityTask getHighestPriorityTask() { try { return Collections.max(priorityTasks, Comparator.comparingInt(PriorityTask::getPriority)); } catch (NoSuchElementException e) { 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 9d1f74538..c5d0a4800 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 @@ -238,4 +238,5 @@ private void changeFireRateInterval(int perMinute) { public float getFireRateInterval() { return fireRateInterval; } + } diff --git a/source/core/src/main/com/csse3200/game/components/tower/UpgradableStatsComponent.java b/source/core/src/main/com/csse3200/game/components/tower/UpgradableStatsComponent.java new file mode 100644 index 000000000..91fcba6ff --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tower/UpgradableStatsComponent.java @@ -0,0 +1,19 @@ +package com.csse3200.game.components.tower; + +import com.csse3200.game.components.Component; + +public class UpgradableStatsComponent extends Component { + private float attackRate; + + public UpgradableStatsComponent(float attackRate) { + setAttackRate(attackRate); + } + + public void setAttackRate(float attackRate) { + this.attackRate = attackRate; + } + + public float getAttackRate() { + return attackRate; + } +} diff --git a/source/core/src/main/com/csse3200/game/entities/configs/DroidTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/DroidTowerConfig.java index 18ce675d5..3349a149c 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/DroidTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/DroidTowerConfig.java @@ -7,4 +7,6 @@ public class DroidTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/FireTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/FireTowerConfig.java index 7e697040b..cc5b75284 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/FireTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/FireTowerConfig.java @@ -4,4 +4,6 @@ public class FireTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java index 65dee1def..d2571c970 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java @@ -7,4 +7,6 @@ public class IncomeTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 0; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/StunTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/StunTowerConfig.java index fc711e70f..adf01c4f4 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/StunTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/StunTowerConfig.java @@ -4,4 +4,6 @@ public class StunTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/TNTTowerConfigs.java b/source/core/src/main/com/csse3200/game/entities/configs/TNTTowerConfigs.java index 2dbd2e53d..9385fc512 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/TNTTowerConfigs.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/TNTTowerConfigs.java @@ -7,4 +7,6 @@ public class TNTTowerConfigs { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 1; } 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 index 452eaf7e0..59c830d4f 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/WallTowerConfig.java @@ -7,4 +7,6 @@ public class WallTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + + public float attackRate = 0; } 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 index 7d00ccb65..7f0547769 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/WeaponTowerConfig.java @@ -7,4 +7,5 @@ public class WeaponTowerConfig { public int health = 1; public int baseAttack = 0; public int cost = 1; + public float attackRate = 1; } 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 84e896390..73c181982 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 @@ -35,8 +35,6 @@ public class TowerFactory { private static final int COMBAT_TASK_PRIORITY = 2; private static final int WEAPON_TOWER_MAX_RANGE = 40; - - private static final int BASE_FIRE_RATE = 1; private static final int TNT_TOWER_MAX_RANGE = 6; private static final int TNT_TOWER_RANGE = 6; private static final int TNT_KNOCK_BACK_FORCE = 10; @@ -236,6 +234,7 @@ public static Entity createWeaponTower() { weapon .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(new CostComponent(config.cost)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(aiTaskComponent) .addComponent(animator) .addComponent(new TowerAnimationController()); diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index aaefb9dc8..f3985453e 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -16,6 +16,8 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.csse3200.game.ai.tasks.AITaskComponent; +import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.areas.ForestGameArea; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.TowerCombatTask; @@ -132,8 +134,10 @@ private Table createUpgradeTable(Entity turretEntity) { int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); turretEntity.getComponent(CombatStatsComponent.class).setHealth(5); // for testing int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); + Label healthLabel = new Label(String.format("Health:%d/%d", currentHealth, maxHealth), createLabelStyle()); Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); +// Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); TextButton closeButton = new TextButton("X", style); closeButton.addListener(new ClickListener() { @Override @@ -203,8 +207,10 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.row(); if (attack != 0) { innerUpgradeTable.add(attackLabel).expandX().left(); + innerUpgradeTable.add(fireRateLabel).expandX().right(); + innerUpgradeTable.row(); + } - innerUpgradeTable.row(); innerUpgradeTable.add(upgradeHealth).expandX().fillX(); if (attack != 0) { innerUpgradeTable.add(upgradeAttack).expandX().fillX(); From 1863c2ba5d0cc3afd2f64ae40a3ae378205b6220 Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Mon, 2 Oct 2023 16:48:15 +1000 Subject: [PATCH 30/49] Added more Turret Images to show when clicked/default --- .../images/towers/imageedit_9_7173145411.png | Bin 0 -> 7525 bytes .../turret-select/droid-tower-clicked.png | Bin 0 -> 8872 bytes .../turret-select/droid-tower-default.png | Bin 0 -> 10272 bytes .../images/turret-select/fire-tower-clicked.png | Bin 0 -> 7337 bytes .../images/turret-select/fire-tower-default.png | Bin 0 -> 8185 bytes .../images/turret-select/mine-tower-clicked.png | Bin 0 -> 8254 bytes .../images/turret-select/mine-tower-default.png | Bin 0 -> 9625 bytes .../images/turret-select/stun-tower-clicked.png | Bin 0 -> 8239 bytes .../images/turret-select/stun-tower-default.png | Bin 0 -> 9179 bytes .../images/turret-select/tnt-tower-clicked.png | Bin 0 -> 7054 bytes .../images/turret-select/tnt-tower-default.png | Bin 0 -> 8361 bytes .../com/csse3200/game/screens/TowerType.java | 10 +++++----- .../game/screens/TurretSelectionScreen.java | 2 +- 13 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 source/core/assets/images/towers/imageedit_9_7173145411.png create mode 100644 source/core/assets/images/turret-select/droid-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/droid-tower-default.png create mode 100644 source/core/assets/images/turret-select/fire-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/fire-tower-default.png create mode 100644 source/core/assets/images/turret-select/mine-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/mine-tower-default.png create mode 100644 source/core/assets/images/turret-select/stun-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/stun-tower-default.png create mode 100644 source/core/assets/images/turret-select/tnt-tower-clicked.png create mode 100644 source/core/assets/images/turret-select/tnt-tower-default.png diff --git a/source/core/assets/images/towers/imageedit_9_7173145411.png b/source/core/assets/images/towers/imageedit_9_7173145411.png new file mode 100644 index 0000000000000000000000000000000000000000..c43b4675b1ce75f30ff5043de11d173a3a05c363 GIT binary patch literal 7525 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret-select/droid-tower-clicked.png b/source/core/assets/images/turret-select/droid-tower-clicked.png new file mode 100644 index 0000000000000000000000000000000000000000..4d182496da8064efdbe54a943ea8f349db7da178 GIT binary patch literal 8872 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret-select/mine-tower-clicked.png b/source/core/assets/images/turret-select/mine-tower-clicked.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8eebc75f59b4080db3dc8da73687f8f62c2657 GIT binary patch literal 8254 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�u;!D(XWM1R*U;4-j180C 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret-select/tnt-tower-clicked.png b/source/core/assets/images/turret-select/tnt-tower-clicked.png new file mode 100644 index 0000000000000000000000000000000000000000..9abee203cb4f147ec4a5218c535eecff85481b5d GIT binary patch literal 7054 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/turret-select/tnt-tower-default.png b/source/core/assets/images/turret-select/tnt-tower-default.png new file mode 100644 index 0000000000000000000000000000000000000000..09ee3b6defd398ca4581467f7f4920f0fbff7da6 GIT binary patch literal 8361 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 Date: Mon, 2 Oct 2023 17:20:52 +1000 Subject: [PATCH 31/49] Added AttackRate upgrade --- .../components/tasks/TowerCombatTask.java | 14 ++++------- .../game/entities/factories/TowerFactory.java | 8 ++++++- .../game/input/UpgradeUIComponent.java | 24 +++++++++++++++++-- 3 files changed, 33 insertions(+), 13 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 c5d0a4800..88e2d6446 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 @@ -216,18 +216,12 @@ private boolean isTargetVisible() { } /** - * Increases the fireRateInterval, changing how frequently the turret fires. Will decrease if the argument is negative. + * Changes the tower's fire rate. * - * @param perMinute The number of times per minute the turret's fire rate should increase + * @param newInterval The rate at which the tower should fire projectiles in shots per second. */ - private void changeFireRateInterval(int perMinute) { - float oldFireSpeed = 1/fireRateInterval; - float newFireSpeed = oldFireSpeed + perMinute/60f; - if (newFireSpeed == 0) { - return; - } else { - fireRateInterval = 1 / newFireSpeed; - } + private void changeFireRateInterval(int newInterval) { + fireRateInterval = newInterval; } /** 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 73c181982..abd032893 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 @@ -39,7 +39,6 @@ public class TowerFactory { private static final int TNT_TOWER_RANGE = 6; private static final int TNT_KNOCK_BACK_FORCE = 10; private static final String WALL_IMAGE = "images/towers/WallTower.png"; - private static final String RESOURCE_TOWER = "images/towers/mine_tower.png"; private static final String TURRET_ATLAS = "images/towers/turret01.atlas"; private static final String FIRE_TOWER_ATLAS = "images/towers/fire_tower_atlas.atlas"; private static final String STUN_TOWER_ATLAS = "images/towers/stun_tower.atlas"; @@ -115,6 +114,7 @@ public static Entity createIncomeTower() { income .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(aiTaskComponent) .addComponent(animator) @@ -129,6 +129,7 @@ public static Entity createWallTower() { wall .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(new TextureRenderComponent(WALL_IMAGE)); return wall; @@ -158,6 +159,7 @@ public static Entity createTNTTower() { TNTTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(new TNTDamageComponent(PhysicsLayer.NPC,TNT_KNOCK_BACK_FORCE,TNT_TOWER_RANGE)) .addComponent(aiTaskComponent) @@ -199,6 +201,7 @@ public static Entity createDroidTower() { DroidTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(new DroidAnimationController()) .addComponent(animator) @@ -233,6 +236,7 @@ public static Entity createWeaponTower() { weapon .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(aiTaskComponent) @@ -266,6 +270,7 @@ public static Entity createFireTower() { fireTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(aiTaskComponent) .addComponent(animator) @@ -295,6 +300,7 @@ public static Entity createStunTower() { stunTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent((new CostComponent(config.cost))) .addComponent(aiTaskComponent) .addComponent(animator) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index f3985453e..dfd61422b 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -22,6 +22,7 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.TowerCombatTask; import com.csse3200.game.components.tower.TowerUpgraderComponent; +import com.csse3200.game.components.tower.UpgradableStatsComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; import com.csse3200.game.services.ServiceLocator; @@ -134,10 +135,10 @@ private Table createUpgradeTable(Entity turretEntity) { int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); turretEntity.getComponent(CombatStatsComponent.class).setHealth(5); // for testing int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); - + float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); Label healthLabel = new Label(String.format("Health:%d/%d", currentHealth, maxHealth), createLabelStyle()); Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); -// Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); + Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); TextButton closeButton = new TextButton("X", style); closeButton.addListener(new ClickListener() { @Override @@ -183,6 +184,23 @@ public void clicked(InputEvent event, float x, float y) { } }); + TextButton upgradeFireRate = new TextButton("+FR", style); + upgradeFireRate.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + if (value >= 10) { + value -= 10; + ServiceLocator.getCurrencyService().getScrap().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 5); + turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(5); + float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); + fireRateLabel.setText(String.format("Fire Rate: %.2f", fireRate)); + } + } + }); + TextButton repairButton = new TextButton("R", style); repairButton.addListener(new ClickListener() { @Override @@ -207,6 +225,7 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.row(); if (attack != 0) { innerUpgradeTable.add(attackLabel).expandX().left(); + innerUpgradeTable.row(); innerUpgradeTable.add(fireRateLabel).expandX().right(); innerUpgradeTable.row(); @@ -214,6 +233,7 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.add(upgradeHealth).expandX().fillX(); if (attack != 0) { innerUpgradeTable.add(upgradeAttack).expandX().fillX(); + innerUpgradeTable.add(upgradeFireRate).expandX().fillX(); } innerUpgradeTable.add(repairButton).expandX().fillX(); upgradeTable.add(innerUpgradeTable).center().expand().row(); From 812c5d2060edb9a8a282ba6613b51a2a519489b5 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:54:18 +1000 Subject: [PATCH 32/49] changed FireRate test to adhere to new fireRate changing function --- .../csse3200/game/components/tasks/TowerCombatTask.java | 2 +- .../game/components/tower/TowerUpgraderComponent.java | 2 +- .../main/com/csse3200/game/input/UpgradeUIComponent.java | 6 ++++-- .../game/components/tower/TowerUpgraderComponentTest.java | 8 ++++---- 4 files changed, 10 insertions(+), 8 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 88e2d6446..91fecc471 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 @@ -221,7 +221,7 @@ private boolean isTargetVisible() { * @param newInterval The rate at which the tower should fire projectiles in shots per second. */ private void changeFireRateInterval(int newInterval) { - fireRateInterval = newInterval; + fireRateInterval = (float) newInterval / 5; } /** diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java index 937d52a6b..12c62ffc6 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java @@ -28,7 +28,7 @@ public void create() { public void upgradeTower(UPGRADE upgradeType, int value) { switch (upgradeType) { case ATTACK -> {upgradeTowerAttack(value);} - case MAXHP -> {upgradeTowerMaxHealth(value);} + case MAXHP -> {upgradeTowerMaxHealth( value);} case FIRERATE -> {getEntity().getEvents().trigger("addFireRate", value);} case REPAIR -> {repairTower();} } diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index dfd61422b..f423368c4 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -193,8 +193,10 @@ public void clicked(InputEvent event, float x, float y) { value -= 10; ServiceLocator.getCurrencyService().getScrap().setAmount(value); ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 5); - turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(5); + float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 0.2f; + turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(newFireRate); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 1); + float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); fireRateLabel.setText(String.format("Fire Rate: %.2f", fireRate)); } diff --git a/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java b/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java index 703a1299b..9af62e404 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java @@ -60,7 +60,7 @@ void increaseFireRate() { entity.create(); entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 60); verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 60); - assertEquals(0.5, towerCombatTask.getFireRateInterval()); + assertEquals(12.0, towerCombatTask.getFireRateInterval()); } @Test @@ -74,8 +74,8 @@ void divideByZeroDefaultToIgnore() { entity.addComponent(aiTaskComponent); towerCombatTask.start(); entity.create(); - entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, -60); - verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, -60); - assertEquals(1., towerCombatTask.getFireRateInterval()); + entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 60); + verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 60); + assertEquals(12f, towerCombatTask.getFireRateInterval()); } } From a649a1b4582558619583fcd962ca817cf8d02d94 Mon Sep 17 00:00:00 2001 From: FattyHope Date: Mon, 2 Oct 2023 18:40:09 +1000 Subject: [PATCH 33/49] test --- .../main/com/csse3200/game/components/tasks/TowerCombatTask.java | 1 + 1 file changed, 1 insertion(+) 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 91fecc471..937847ad8 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 @@ -12,6 +12,7 @@ import com.csse3200.game.services.ServiceLocator; import static java.lang.Math.round; +// test /** * 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 From e23abeb0a3e4b768607ea91bada463ebfe302df3 Mon Sep 17 00:00:00 2001 From: FattyHope Date: Mon, 2 Oct 2023 21:33:00 +1000 Subject: [PATCH 34/49] Change pop up text to image, few bugs --- .../com/csse3200/game/areas/ForestGameArea.java | 10 +++++----- .../game/components/tasks/TowerCombatTask.java | 1 - .../com/csse3200/game/input/UpgradeUIComponent.java | 13 ++++++++++--- 3 files changed, 15 insertions(+), 9 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 8ca0a96c2..ce513dcf4 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -268,16 +268,16 @@ public void create() { // spawnSplittingXenoGrunt(15, 4); // spawnScrap(); // spawnTNTTower(); - spawnWeaponTower(); + // spawnWeaponTower(); // spawnGapScanners(); // spawnDroidTower(); - spawnScrap(); - spawnDroidTower(); - spawnTNTTower(); +// spawnScrap(); +// spawnDroidTower(); +// spawnTNTTower(); spawnIncome(); } - + private void displayUI() { Entity ui = new Entity(); ui.addComponent(new GameAreaDisplay("Box Forest")); 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 937847ad8..91fecc471 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 @@ -12,7 +12,6 @@ import com.csse3200.game.services.ServiceLocator; import static java.lang.Math.round; -// test /** * 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 diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index f423368c4..d2d27f5bb 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -16,6 +16,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.areas.ForestGameArea; @@ -136,7 +137,7 @@ private Table createUpgradeTable(Entity turretEntity) { turretEntity.getComponent(CombatStatsComponent.class).setHealth(5); // for testing int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); - Label healthLabel = new Label(String.format("Health:%d/%d", currentHealth, maxHealth), createLabelStyle()); + Label healthLabel = new Label(String.format("%d/%d", currentHealth, maxHealth), createLabelStyle()); Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); TextButton closeButton = new TextButton("X", style); @@ -149,6 +150,11 @@ public void clicked(InputEvent event, float x, float y) { } }); + // Create an Image for the health icon + Drawable healthIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/heart.png"))); + Image healthIconImage = new Image(healthIconDrawable); + + TextButton upgradeHealth = new TextButton("+H", style); upgradeHealth.addListener(new ClickListener() { @Override @@ -162,7 +168,7 @@ public void clicked(InputEvent event, float x, float y) { turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.MAXHP, 10); int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); int maxHealth = turretEntity.getComponent(CombatStatsComponent.class).getMaxHealth(); - healthLabel.setText(String.format("Health:%d/%d", currentHealth, maxHealth)); + healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); } } }); @@ -214,7 +220,7 @@ public void clicked(InputEvent event, float x, float y) { ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.REPAIR, 0); int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); - healthLabel.setText(String.format("Health:%d/%d", currentHealth, maxHealth)); + healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); } } }); @@ -223,6 +229,7 @@ public void clicked(InputEvent event, float x, float y) { upgradeTable.row(); innerUpgradeTable.row(); + innerUpgradeTable.add(healthIconImage).padRight(5); // Add health icon innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); if (attack != 0) { From 70e54300ec98690fcd4f9e585ea8e49abe6acd8c Mon Sep 17 00:00:00 2001 From: FattyHope Date: Mon, 2 Oct 2023 21:54:47 +1000 Subject: [PATCH 35/49] Changed health image to heart and make the width x height the same dimensions --- source/core/assets/images/health.png | Bin 0 -> 6770 bytes .../csse3200/game/input/UpgradeUIComponent.java | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 source/core/assets/images/health.png diff --git a/source/core/assets/images/health.png b/source/core/assets/images/health.png new file mode 100644 index 0000000000000000000000000000000000000000..3273c9a50fd0c2e59051483800b0fbf42fa258bb GIT binary patch literal 6770 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 QMIRkt7vUF3=Y8+~9k5}1VgLXD literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index d2d27f5bb..ed93a069d 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -151,7 +151,7 @@ public void clicked(InputEvent event, float x, float y) { }); // Create an Image for the health icon - Drawable healthIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/heart.png"))); + Drawable healthIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/health.png"))); Image healthIconImage = new Image(healthIconDrawable); @@ -229,7 +229,7 @@ public void clicked(InputEvent event, float x, float y) { upgradeTable.row(); innerUpgradeTable.row(); - innerUpgradeTable.add(healthIconImage).padRight(5); // Add health icon + innerUpgradeTable.add(healthIconImage).padRight(5).width(32).height(32); // Add health icon innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); if (attack != 0) { From 6dbfaaa7093885931a405251ac6e76f259b11dd9 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:59:30 +1000 Subject: [PATCH 36/49] Added FireRate for all other relevant towers --- .../csse3200/game/areas/ForestGameArea.java | 21 +++++++-------- .../components/tasks/DroidCombatTask.java | 26 ++++++++++++++++--- .../components/tasks/FireTowerCombatTask.java | 25 +++++++++++++++++- .../components/tasks/StunTowerCombatTask.java | 24 ++++++++++++++++- .../components/tasks/TowerCombatTask.java | 12 +++++++-- .../game/input/UpgradeUIComponent.java | 4 +-- 6 files changed, 91 insertions(+), 21 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 8ca0a96c2..02c5177eb 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -263,7 +263,7 @@ public void create() { // playMusic(); // spawnXenoGrunts(); // startWaveTimer(); -// spawnScrap(); + spawnScrap(); // spawnDeflectXenoGrunt(15, 5); // spawnSplittingXenoGrunt(15, 4); // spawnScrap(); @@ -271,10 +271,10 @@ public void create() { spawnWeaponTower(); // spawnGapScanners(); // spawnDroidTower(); - spawnScrap(); - spawnDroidTower(); - spawnTNTTower(); - spawnIncome(); +// spawnScrap(); +// spawnDroidTower(); +// spawnTNTTower(); +// spawnIncome(); } @@ -598,13 +598,10 @@ private void spawnWeaponTower() { for (int i = 0; i < NUM_WEAPON_TOWERS + 10; i++) { GridPoint2 randomPos1 = RandomUtils.random(minPos, maxPos); - GridPoint2 randomPos2 = RandomUtils.random(minPos, maxPos); - Entity wallTower = TowerFactory.createWallTower(); - Entity fireTower = TowerFactory.createFireTower(); - Entity stunTower = TowerFactory.createStunTower(); - spawnEntityAt(fireTower, randomPos1, true, true); - spawnEntityAt(stunTower, randomPos2, true, true); - spawnEntityAt(wallTower, randomPos2, true, true); +// Entity wallTower = TowerFactory.createWallTower(); + Entity droidTower = TowerFactory.createDroidTower(); + spawnEntityAt(droidTower, randomPos1, true, true); +// spawnEntityAt(stunTower, randomPos2, true, true); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java index 9f1159de4..384549af7 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java @@ -11,6 +11,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The DroidCombatTask runs the AI for the DroidTower 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 @@ -35,6 +37,7 @@ public class DroidCombatTask extends DefaultTask implements PriorityTask { // class attributes private final int priority; // The active priority this task will have private final float maxRange; + private float fireRateInterval; private Vector2 towerPosition = new Vector2(10, 10); // initial placeholder value - will be overwritten private final Vector2 maxRangePosition = new Vector2(); private PhysicsEngine physics; @@ -54,6 +57,7 @@ public enum STATE { public DroidCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -69,7 +73,7 @@ public void start() { this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); // Default to idle mode owner.getEntity().getEvents().trigger(WALK); - + owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); endTime = timeSource.getTime() + (INTERVAL * 500); } @@ -81,8 +85,12 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); - endTime = timeSource.getTime() + (INTERVAL * 1000); - } + if (towerState == STATE.SHOOT_UP || towerState == STATE.SHOOT_DOWN) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } else { + endTime = timeSource.getTime() + (INTERVAL * 1000); + } + } } /** @@ -193,5 +201,17 @@ public boolean isTargetVisible() { return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); } + private void changeFireRateInterval(int newInterval) { + fireRateInterval = 1 / ((float) newInterval / 5); + } + + /** + * Function for getting the turret's fire rate. + * + * @return The fireRateInterval variable + */ + public float getFireRateInterval() { + return fireRateInterval; + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java index e2f1327ef..abf01bb79 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java @@ -14,6 +14,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The FireTowerCombatTask runs the AI for the FireTower class. The tower implementing this task will scan for enemies * in a straight line from the current position to a maxRange, and change the state of the tower. @@ -28,10 +30,12 @@ public class FireTowerCombatTask extends DefaultTask implements PriorityTask { public static final String ATTACK = "startAttack"; public static final String DEATH = "startDeath"; + //Class attributes private final int priority; private final float maxRange; + private float fireRateInterval; private Vector2 towerPosition = new Vector2(10, 10); private final Vector2 maxRangePosition = new Vector2(); private PhysicsEngine physics; @@ -50,6 +54,7 @@ public enum STATE { public FireTowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -63,6 +68,7 @@ public void start() { // get the tower coordinates this.towerPosition = owner.getEntity().getCenterPosition(); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); + owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); //default to idle state owner.getEntity().getEvents().trigger(IDLE); @@ -76,7 +82,10 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); - endTime = timeSource.getTime() + (INTERVAL * 1000); + if (towerState == STATE.ATTACK) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } else + endTime = timeSource.getTime() + (INTERVAL * 1000); } } @@ -172,4 +181,18 @@ private int getInactivePriority() { public boolean isTargetVisible() { return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); } + + private void changeFireRateInterval(int newInterval) { + fireRateInterval = 1 / ((float) newInterval / 5); + } + + /** + * Function for getting the turret's fire rate. + * + * @return The fireRateInterval variable + */ + public float getFireRateInterval() { + return fireRateInterval; + } + } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java index be56625f7..cce8ec833 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java @@ -14,6 +14,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The StunTowerCombatTask runs the AI for the StunTower class. The tower scans for mobs and targets in a straight line @@ -31,6 +33,7 @@ public class StunTowerCombatTask extends DefaultTask implements PriorityTask { //Following are the class constants private final int priority; private final float maxRange; + private float fireRateInterval; private Vector2 towerPosition = new Vector2(10, 10); private final Vector2 maxRangePosition = new Vector2(); private PhysicsEngine physics; @@ -51,6 +54,7 @@ public enum STATE { public StunTowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -64,6 +68,7 @@ public void start() { //get the tower coordinates this.towerPosition = owner.getEntity().getCenterPosition(); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); + owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); //set the default state to IDLE state owner.getEntity().getEvents().trigger(IDLE); @@ -77,7 +82,11 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); - endTime = timeSource.getTime() + (INTERVAL * 1000); + if (towerState == STATE.ATTACK) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } else { + endTime = timeSource.getTime() + (INTERVAL * 1000); + } } } @@ -160,4 +169,17 @@ public int getInactivePriority() { public boolean isTargetVisible() { return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); } + + private void changeFireRateInterval(int newInterval) { + fireRateInterval = 1 / ((float) newInterval / 5); + } + + /** + * Function for getting the turret's fire rate. + * + * @return The fireRateInterval variable + */ + public float getFireRateInterval() { + return fireRateInterval; + } } 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 91fecc471..1908cca9d 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 @@ -3,6 +3,7 @@ import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.areas.ForestGameArea; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsEngine; @@ -10,6 +11,9 @@ import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import static java.lang.Math.round; /** @@ -37,6 +41,7 @@ public class TowerCombatTask extends DefaultTask implements PriorityTask { private GameTime timeSource; private long endTime; private final RaycastHit hit = new RaycastHit(); + private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); private enum STATE { IDLE, DEPLOY, FIRING, STOW @@ -48,6 +53,7 @@ private enum STATE { * @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.fireRateInterval = 1; @@ -56,6 +62,7 @@ public TowerCombatTask(int priority, float maxRange) { } /** + * THIS IS REDUNDANT AND NOT USED * @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 * @param fireRate The number of times per second this tower should fire its weapon @@ -81,7 +88,7 @@ public void start() { owner.getEntity().getEvents().trigger(IDLE); // Set up listener to change firerate owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); - + logger.info("TowerCombatTask started"); endTime = timeSource.getTime() + (INTERVAL * 500); } @@ -221,7 +228,8 @@ private boolean isTargetVisible() { * @param newInterval The rate at which the tower should fire projectiles in shots per second. */ private void changeFireRateInterval(int newInterval) { - fireRateInterval = (float) newInterval / 5; + logger.info("Changing fire rate to: " + newInterval); + fireRateInterval = 1 / ((float) newInterval / 5); } /** diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index f423368c4..af8b5434f 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -193,9 +193,9 @@ public void clicked(InputEvent event, float x, float y) { value -= 10; ServiceLocator.getCurrencyService().getScrap().setAmount(value); ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 0.2f; + float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 30; turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(newFireRate); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 1); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, (int) newFireRate * 5); float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); fireRateLabel.setText(String.format("Fire Rate: %.2f", fireRate)); From 639de80c87764694379d5323faaebd5e97cd3c93 Mon Sep 17 00:00:00 2001 From: FattyHope Date: Mon, 2 Oct 2023 22:15:17 +1000 Subject: [PATCH 37/49] Changed attack damage of turrets from text to image --- source/core/assets/images/attack.png | Bin 0 -> 557 bytes .../com/csse3200/game/areas/ForestGameArea.java | 2 +- .../csse3200/game/input/UpgradeUIComponent.java | 14 +++++++------- 3 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 source/core/assets/images/attack.png diff --git a/source/core/assets/images/attack.png b/source/core/assets/images/attack.png new file mode 100644 index 0000000000000000000000000000000000000000..c9dfff668c69412efd04b76cdbe9e48eea2fae05 GIT binary patch literal 557 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKLEX+WWqKVr7fs{mmPlzjsmXJ7q{(N9yU|U;T zZf@@P@84IhT&Wmuehw(dSQ6wH%;50sMjDWP*we)^q~g}wTaH|p9Yl^le8MKHUG`RC zm)=3Q7LVF8`ppr|6 zfT9zSVKlAxvcS`=eoifa=0Ze(QWK=!dtX^6^j!1Vk8LiU<=a=pZr25?hHAUB{zz)C z)O@SsA@6q_Juj6V-rEl{3ub8L54%hJFXf+C*UVj1!U+`iXoniTQb=jwU6sg2;Dz@Y_^pD z%(bd8Pk@}9woPrx&ZH}A!~OJ-g-=WI=RV^XYMsvv_Zg6JqOwc1&PNg1yvI`BU=O|#hK2x2$k#KREn37@^mVT) ONZ8ZW&t;ucLK6Vc9>}x+ literal 0 HcmV?d00001 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 ce513dcf4..10b2913c5 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -268,7 +268,7 @@ public void create() { // spawnSplittingXenoGrunt(15, 4); // spawnScrap(); // spawnTNTTower(); - // spawnWeaponTower(); + spawnWeaponTower(); // spawnGapScanners(); // spawnDroidTower(); // spawnScrap(); diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index ed93a069d..339202507 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -138,7 +138,7 @@ private Table createUpgradeTable(Entity turretEntity) { int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); Label healthLabel = new Label(String.format("%d/%d", currentHealth, maxHealth), createLabelStyle()); - Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); + Label attackLabel = new Label(String.format("%d", attack), createLabelStyle()); Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); TextButton closeButton = new TextButton("X", style); closeButton.addListener(new ClickListener() { @@ -150,10 +150,13 @@ public void clicked(InputEvent event, float x, float y) { } }); - // Create an Image for the health icon + // Create an Image for the icons Drawable healthIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/health.png"))); Image healthIconImage = new Image(healthIconDrawable); + Drawable attackIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/attack.png"))); + Image attackIconImage = new Image(attackIconDrawable); + TextButton upgradeHealth = new TextButton("+H", style); upgradeHealth.addListener(new ClickListener() { @@ -185,7 +188,7 @@ public void clicked(InputEvent event, float x, float y) { turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.ATTACK, 5); int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); - attackLabel.setText(String.format("Attack: %d", attack)); + attackLabel.setText(String.format("%d", attack)); } } }); @@ -225,19 +228,16 @@ public void clicked(InputEvent event, float x, float y) { } }); - upgradeTable.add(closeButton).right().top(); - upgradeTable.row(); - innerUpgradeTable.row(); innerUpgradeTable.add(healthIconImage).padRight(5).width(32).height(32); // Add health icon innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); if (attack != 0) { + innerUpgradeTable.add(attackIconImage).padRight(5).width(32).height(32); // Add attack icon innerUpgradeTable.add(attackLabel).expandX().left(); innerUpgradeTable.row(); innerUpgradeTable.add(fireRateLabel).expandX().right(); innerUpgradeTable.row(); - } innerUpgradeTable.add(upgradeHealth).expandX().fillX(); if (attack != 0) { From 0b570a391c87cb9c878ea2e6f81e407b21644573 Mon Sep 17 00:00:00 2001 From: FattyHope Date: Mon, 2 Oct 2023 22:24:33 +1000 Subject: [PATCH 38/49] Change fire rate from text to image --- source/core/assets/images/glass.png | Bin 0 -> 13839 bytes .../csse3200/game/input/UpgradeUIComponent.java | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 source/core/assets/images/glass.png diff --git a/source/core/assets/images/glass.png b/source/core/assets/images/glass.png new file mode 100644 index 0000000000000000000000000000000000000000..f9d9d87ea7378224c4d8ad2d3e80c90fea4453d9 GIT binary patch literal 13839 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 literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index c132ecd98..3a364e3c0 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -157,6 +157,9 @@ public void clicked(InputEvent event, float x, float y) { Drawable attackIconDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/attack.png"))); Image attackIconImage = new Image(attackIconDrawable); + Drawable fireRateDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/glass.png"))); + Image fireRateImage = new Image(fireRateDrawable); + TextButton upgradeHealth = new TextButton("+H", style); upgradeHealth.addListener(new ClickListener() { @@ -207,7 +210,7 @@ public void clicked(InputEvent event, float x, float y) { turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, (int) newFireRate * 5); float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); - fireRateLabel.setText(String.format("Fire Rate: %.2f", fireRate)); + fireRateLabel.setText(String.format("%.2f", fireRate)); } } }); @@ -232,10 +235,13 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.add(healthIconImage).padRight(5).width(32).height(32); // Add health icon innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); + if (attack != 0) { innerUpgradeTable.add(attackIconImage).padRight(5).width(32).height(32); // Add attack icon innerUpgradeTable.add(attackLabel).expandX().left(); innerUpgradeTable.row(); + + innerUpgradeTable.add(fireRateImage).padRight(5).width(32).height(32); // Add fire rate icon innerUpgradeTable.add(fireRateLabel).expandX().right(); innerUpgradeTable.row(); } From cbc945b89260f5634759f4b7456df939c822a214 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Tue, 3 Oct 2023 00:13:19 +1000 Subject: [PATCH 39/49] Implemented Income Rate Upgrade --- .../csse3200/game/areas/ForestGameArea.java | 1 + .../game/components/tasks/CurrencyTask.java | 11 ++- .../tower/IncomeUpgradeComponent.java | 19 ++++ .../tower/TowerUpgraderComponent.java | 6 +- .../entities/configs/IncomeTowerConfig.java | 2 + .../game/entities/factories/TowerFactory.java | 5 +- .../game/input/UpgradeUIComponent.java | 99 +++++++++++++++++++ 7 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 source/core/src/main/com/csse3200/game/components/tower/IncomeUpgradeComponent.java diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index c04e7691e..d53db7857 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -276,6 +276,7 @@ public void create() { // spawnTNTTower(); // spawnIncome(); spawnIncome(); + spawnDroidTower(); } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java index c9e21d846..c280db0bd 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java @@ -39,7 +39,8 @@ public CurrencyTask(int priority, int interval) { @Override public void start() { super.start(); - endTime = timeSource.getTime() + (30 * 1000); + owner.getEntity().getEvents().addListener("addIncome",this::changeInterval); + endTime = timeSource.getTime() + (30 * 1000L); owner.getEntity().getEvents().trigger(IDLE); } @@ -53,7 +54,8 @@ public void update() { if (timeSource.getTime() >= endTime) { owner.getEntity().getEvents().trigger(MOVE); updateCurrency(); // update currency - endTime = timeSource.getTime() + (30 * 1000); // reset end time + logger.info(String.format("Interval: %d", interval)); + endTime = timeSource.getTime() + (interval * 1000L); // reset end time } } @@ -89,6 +91,11 @@ public int getPriority() { return priority; } + public void changeInterval(int newInterval) { + interval = newInterval; + logger.info("Interval changed to: " + interval); + } + public void setInterval(int interval) { this.interval = interval; } diff --git a/source/core/src/main/com/csse3200/game/components/tower/IncomeUpgradeComponent.java b/source/core/src/main/com/csse3200/game/components/tower/IncomeUpgradeComponent.java new file mode 100644 index 000000000..ffbb93e12 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tower/IncomeUpgradeComponent.java @@ -0,0 +1,19 @@ +package com.csse3200.game.components.tower; + +import com.csse3200.game.components.Component; + +public class IncomeUpgradeComponent extends Component { + private float incomeRate; + + public IncomeUpgradeComponent(float incomeRate) { + setIncomeRate(incomeRate); + } + + public void setIncomeRate(float incomeRate) { + this.incomeRate = incomeRate; + } + + public float getIncomeRate() { + return incomeRate; + } +} diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java index 12c62ffc6..f4e2a3aaf 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java @@ -3,13 +3,15 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.Component; +import static com.csse3200.game.screens.TowerType.INCOME; + /** * Listens for an event from the popup menu to upgrade * the turret entity this component is attached to. */ public class TowerUpgraderComponent extends Component { public enum UPGRADE { - ATTACK, MAXHP, FIRERATE, REPAIR + ATTACK, MAXHP, FIRERATE, REPAIR, INCOME } @Override @@ -27,10 +29,12 @@ public void create() { */ public void upgradeTower(UPGRADE upgradeType, int value) { switch (upgradeType) { + case INCOME -> {getEntity().getEvents().trigger("addIncome", value);} case ATTACK -> {upgradeTowerAttack(value);} case MAXHP -> {upgradeTowerMaxHealth( value);} case FIRERATE -> {getEntity().getEvents().trigger("addFireRate", value);} case REPAIR -> {repairTower();} + } } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java index d2571c970..9e79376e2 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java @@ -9,4 +9,6 @@ public class IncomeTowerConfig { public int cost = 1; public float attackRate = 0; + public float incomeRate = 30; + } 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 abd032893..e7e2e6512 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 @@ -97,10 +97,8 @@ public static Entity createIncomeTower() { IncomeTowerConfig config = configs.income; // Create the CurrencyIncomeTask and add it to the AITaskComponent - CurrencyTask currencyTask = new CurrencyTask(INCOME_TASK_PRIORITY, INCOME_INTERVAL); + CurrencyTask currencyTask = new CurrencyTask(INCOME_TASK_PRIORITY, (int) config.incomeRate); - int updatedInterval = 1; - currencyTask.setInterval(updatedInterval); AITaskComponent aiTaskComponent = new AITaskComponent().addTask(currencyTask); @@ -116,6 +114,7 @@ public static Entity createIncomeTower() { .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) + .addComponent(new IncomeUpgradeComponent(config.incomeRate)) .addComponent(aiTaskComponent) .addComponent(animator) .addComponent(new EconTowerAnimationController()); diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index e8d5e87a4..09ee23a39 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Label; @@ -17,11 +18,13 @@ import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.utils.Scaling; import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.areas.ForestGameArea; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.TowerCombatTask; +import com.csse3200.game.components.tower.IncomeUpgradeComponent; import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.components.tower.UpgradableStatsComponent; import com.csse3200.game.entities.Entity; @@ -140,6 +143,17 @@ private Table createUpgradeTable(Entity turretEntity) { Label healthLabel = new Label(String.format("%d/%d", currentHealth, maxHealth), createLabelStyle()); Label attackLabel = new Label(String.format("Attack: %d", attack), createLabelStyle()); Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); + Table costDisplay = new Table(); + costDisplay.setWidth(0); + costDisplay.setBackground(drawableBackground); + // Create an Image for the scrap icon + Drawable costDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/economy/scrap.png"))); + Image costImage = new Image(costDrawable); + costDisplay.add(costImage).center(); + costImage.setScaling(Scaling.none); + Label costDisplayLabel = new Label("100", createLabelStyle()); + costDisplay.add(costDisplayLabel).padLeft(0); + TextButton closeButton = new TextButton("X", style); closeButton.addListener(new ClickListener() { @Override @@ -171,6 +185,15 @@ public void clicked(InputEvent event, float x, float y) { healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); } } + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + costDisplayLabel.setText("10"); + costDisplay.setVisible(true); + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costDisplay.setVisible(false); + } }); TextButton upgradeAttack = new TextButton("+A", style); @@ -188,8 +211,19 @@ public void clicked(InputEvent event, float x, float y) { attackLabel.setText(String.format("Attack: %d", attack)); } } + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + costDisplayLabel.setText("10"); + costDisplay.setVisible(true); + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costDisplay.setVisible(false); + } }); + + TextButton upgradeFireRate = new TextButton("+FR", style); upgradeFireRate.addListener(new ClickListener() { @Override @@ -206,6 +240,18 @@ public void clicked(InputEvent event, float x, float y) { float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); fireRateLabel.setText(String.format("Fire Rate: %.2f", fireRate)); } + + } + + + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + costDisplayLabel.setText("10"); + costDisplay.setVisible(true); + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costDisplay.setVisible(false); } }); @@ -223,6 +269,18 @@ public void clicked(InputEvent event, float x, float y) { healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); } } + + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + costDisplayLabel.setText("10"); + costDisplay.setVisible(true); + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costDisplay.setVisible(false); + } + + }); upgradeTable.add(closeButton).right().top(); @@ -232,6 +290,41 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.add(healthIconImage).padRight(5).width(32).height(32); // Add health icon innerUpgradeTable.add(healthLabel).expandX().left(); innerUpgradeTable.row(); + TextButton upgradeIncome = null; + if (turretEntity.getComponent(IncomeUpgradeComponent.class) != null) { + Label incomeLabel = new Label(String.format("Income: %.2f", turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate()), createLabelStyle()); + innerUpgradeTable.add(incomeLabel).expandX().left(); + innerUpgradeTable.row(); + + upgradeIncome = new TextButton("+I", style); + upgradeIncome.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + if (value >= 10 && turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() >= 5) { + value -= 10; + ServiceLocator.getCurrencyService().getScrap().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + float newIncome = turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() - 5; + turretEntity.getComponent(IncomeUpgradeComponent.class).setIncomeRate(newIncome); + turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.INCOME, (int) newIncome); + incomeLabel.setText(String.format("Income: %.2f", newIncome)); + } + + } + + + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + costDisplayLabel.setText("10"); + costDisplay.setVisible(true); + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costDisplay.setVisible(false); + } + }); + } if (attack != 0) { innerUpgradeTable.add(attackLabel).expandX().left(); innerUpgradeTable.row(); @@ -244,10 +337,16 @@ public void clicked(InputEvent event, float x, float y) { innerUpgradeTable.add(upgradeAttack).expandX().fillX(); innerUpgradeTable.add(upgradeFireRate).expandX().fillX(); } + if (upgradeIncome != null) { + innerUpgradeTable.add(upgradeIncome).expandX().fillX(); + } innerUpgradeTable.add(repairButton).expandX().fillX(); upgradeTable.add(innerUpgradeTable).center().expand().row(); + upgradeTable.add(costDisplay).left(); + costDisplay.setVisible(false); upgradeTable.setVisible(true); + return upgradeTable; } From 0281bd31c7dff2c82e6d2769cb245f470aaf5a46 Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Tue, 3 Oct 2023 00:14:09 +1000 Subject: [PATCH 40/49] Added Showing Description on Hover --- .../turret-select/imageedit_15_5627113584.png | Bin 0 -> 2541 bytes .../turret-select/imageedit_28_4047785594.png | Bin 0 -> 3892 bytes .../assets/sounds/turret-select/Modern4.wav | Bin 0 -> 118886 bytes .../game/screens/TurretSelectionScreen.java | 98 +++++++++++++++--- 4 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 source/core/assets/images/turret-select/imageedit_15_5627113584.png create mode 100644 source/core/assets/images/turret-select/imageedit_28_4047785594.png create mode 100644 source/core/assets/sounds/turret-select/Modern4.wav diff --git a/source/core/assets/images/turret-select/imageedit_15_5627113584.png b/source/core/assets/images/turret-select/imageedit_15_5627113584.png new file mode 100644 index 0000000000000000000000000000000000000000..14412cd66720448b081fb7308537c73df456e477 GIT binary patch literal 2541 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 Nv=RF7YIXbY{{axLU5fw! literal 0 HcmV?d00001 diff --git a/source/core/assets/sounds/turret-select/Modern4.wav b/source/core/assets/sounds/turret-select/Modern4.wav new file mode 100644 index 0000000000000000000000000000000000000000..98b9386fade3587874514bbde895870f7e286328 GIT binary patch literal 118886 zcmeFa1(X~&w=FCcHP4utnVB(;DQ0G7#u#IWnb|QjGc(7`%*+t;G#5#4S5M}~$^9Vz zegAs*y|wPtQkA;8N_DmlN;=h3w@Rf-Ew541s9eK}9eeak7mpA^i9jlBCM4btfk-4C zsa~aC{S-J~rDmmCRq9o$ABB4LHUl~qE}o}A(LDL{EyeZL zeSZ||=>#S27+V+dS;Tp(NWT{uM;Z73wJ11e6&s2@QW)wCb*q@))ML*%aPH5Aee?N` zx)ay^wOIE#(XLe-zaL#VTE+eQG46Zovm4iYA|LUBe4MV%5i ziW9wJ6<4H)#DSyz_j3;PjQ#f#SGVD_4ZWq{sNfh|mvOY=vkiCJ(5lr+Y|A2A7V#vB zcyRRK7=`|g#xWkQu}bvsB_8gJ59%ywi65y`k|1*AJONNzB_WU{KuL&tqDYCYTjvuJ z9q07O(W?J(PUDI3ePZ;2b&qvSjAtZ9Jqa;*Qhb*b*C&Y->pBBPkCX%?gy+TJK0k`} zYzZ{kNkU*v2t3y3c=#L-DB}Zhd?1g9qgA3&k3w(6Vixh4^LS`CK2gz580`h|OfOGH zzVZ~mmt^>y0?$f?V=59r(RoTdHwErZfoCN{-zCMflj504(0&p;Hz}Tw?Dvu!J)Ioq zlcP_Q~Nbp8V6G3t*v*Z;^h-j@e>7ygB}LyLX*8$Oml=Tp(@GX9YN${(QZdpyYR z@F;SZ=LEI2$phYjJmy2lE4~t_j-uDDqsM+jPw5sPXiDOtnF*!2@wpfYkc#99sZP$4 zI^+mxN_LW#WDRLemXnTT8Rek{r5Oi8TT|J z&B;*gmy#yrIB7sWkh&xltxu}ahU7=um@J_!$Qjy&Jf}m5mrf@JT~9*vEO|oTlf5*G zj--WX8QO$?B7^A+GJ_T%%jiwMn)c$0X*8cm_p$D@4XaE&EG0c|z9YlUt)z_En@}@1 zxoo`Q%Zz3GC!+~(XT;|XjB~7>F_N`5zGDLok^;0wG+Fny4hBBkGVo^XRcF|n!l>ojJN76BZbz?Xr|>b)@#&|^yhkK z{gQr7|5dMS9MdluXZ0rLef^6W&}XsKMp<6l@bT%!Ci2ASNQ;;mgvI6~A)3t)C$J)t zgI|+o@>X&xa$nv+$|yzX4COezp!^_wR?Z8i@|_q^wu|?ac+v)?rPN7TAjMaXOB>|d zQa<^Xv`#uAMN7X(UBt%HF2Nyr>1HtpEiX1FSA($zZv(1=H?;sp*c_Lz&gqymQ|U>??eU~Z_VrQ&dl6Z(@0J(YQY$HJy_C_)CgqNNNl7f;Z6t@h8(fA zq*d%by4OBR;C8#1#W7OM?f6Yh>?kWevi~fNwy%|hT9-()EH6j$vOzqXxtZlKo}0z=q-ImCfiYWMqQ43Uw3^`-+Re}- zb#SP^S|*fPO%wVMP7=Bp&J#KnZWX#3UKaWi_Jwk&ZNmfA=iysw54Dn(K)bA6(c0>B zb%)W{IBm2yC!1|p3)Y^O2e{(CD)VVOD!dj*i@uKbs<2C()aKMFPX?+nqSPX#!JIxywHp4UTuJuR6DQM zSBt5e!Y9M2!(GA~Lpj3rLrOSV$R7#?)sQckBJ2p&3zrD33{MET)R@pTwNE&+=2mZO zN7d!}SZ#>WO7CFSFj}x5%x1hgYeAaw_OvVMEDWNp#nD1_X`+}z9xZw0KJsd%j#AE+ z&UV~(&z8YH*xu1DIHudXJLcMVIexO=b(FE+bG)+cc677#aNJd7M-FAEy`y~HHc@ie z=7^ATA-6n+rkA=AyI6(4rkUAcBAK)JTfH;8p_Ml;s@aSi;S~CtP--n+sF2zy*fxA1 zurX9D5FNVfpA($#FBTl&R|9?h_XCsscLRs~F#$P{E7&bCCip3!2d4z5hpL9khBJp1 zHL?0yO|CuA3hFQQR)%5BH?yz@tQoxLY|@5arppAocv~zZsZv+jrA$?9wxzarwng?$ z_K}V{j_S_)j*#=`;0co9q&7!+LT&mXMncLtOAc|i6@<5)6S**_+@!2coW2=os95=ay-5quCNn15IoVsi4^LnoAr+V+4CYnDtz?|^lF7vn zb2`7+rZ`vF-#H6A(z(_;3c9>FCU?GergBbjh8?1FlcTYtm}8oKrG35at!<6svQ3r~ z!=fs3TJec^ovsx|kPb92Pfnhi=h$51C$p)Z&&Z*D(4y3RYE*cBI9q5&s8w)H@L=G6 zplBdZ;I@CQf1babf2g1Ohxy<6mixoLH~w7yDuL1d3jxF5GdL%ZJ5)Vr3ug!kYLajY zEt6VBucA#iM(J*nI;w%K1h?rV#;l)n=PR-+Frpn+R@tH+S$pG z#MRKb!Ij08*nPv*$lcW4*L~F8$*sHdyW@H8xO8`8*J1ZQXKi=DvCoy*5pX86M>~m4 zaomz0+2%>}mFi+yS*16`Wu(4Po?j&&%u0NzamZ}07Y4pVz*kFkg+rmtp(DX|!PS9t zfero|fg3)rKa+32f3bI=zl?W|-{alpw|QUtb9f5|`gxZHUVF0z2m3Ar3-~95q5|#0 zo?s(2SE!xVIXpo>s-7^i>Q1)QXv)*G?PLR&g?zMuxKo%f<&w_H3+3lZPCeaHF29dtJLe0FZ~{OY{s>Fzw^2|A{DS~xO!mfNSgPukAA&M6O^ zJLR*EandjLs$w}C74FDeNh7HdKQB<0hwd<@@ow-^g|tRSeD#uM57$@Ih614m!5zVE zfoXw!f!Y2${^P!d{$#$P{zcwl{%YR&{w&^0{#@Qvf!5y1fur6;!ScTS!7si+p_Bf4 z;e&xH>aAcCEnaxE-WAv$X$e>xqc;zl_sL9NS;$Ryi5GuCF8zhrkf zlR9Nr1=kZ-UH5EvNl$u@?iu5m5p~cLh&t)X5xvZlJGz#KN8NERiz?)f7uDTW$1~E| z(cRBc$5qLm%xNk|?aSoqw*1m5d5@4)%14I@>-i;;ktO46j4tpCXY?0pA#Fo=Pk3gi zL1<|(aqxOT_2&xM{M-E%eNFv4z1e{+wLg)!5ct>IU&wpaKh9etp!hxocKUV&$NA@n zh6fgemjw5#PeL(TNwtizLtAQ=Haz^6IR;U(N#oOg;#T2>R8IO%IU`TCm9(9 zqk+~$e;q!n&I(ltw+X%p zHVCW;^zx7J@9>THrS|Rj?(in@_VlidY2jTVru3FqZLQf-^0oUo6! zC3k+d*Kw70ws&`N)$si2c11PxERKqfqS1?@ibbnY-$iGQP8FRY`cl;EsA^IDqn3DX zd(OHQ&smq-y~6p)*}}2eVcM$MM<`d7FH%{#wzybaML*Loyc8+TCb5~uW8*O)^w_hO#LB=+X?4)reg z+I?kwdwsHhf-R*+NS(m-Io} zBll2p*`C-Y+e`4clfD`PY; zwrH!h0;;0k2#pHO4yFnY3EcHh@*nX1>O1RA<0IZR-cB)fz2?`f-s4|0d3S%U;=TQK zwl`yp;9C?k+gH|G$sgrQ4S$g|m_AS-)H>KLd^B`aEvjbIPit$9_C|gd#ZL31yanw| zy+T^?XX&(L$Ssr(w&%9}_F9flj#ZG(d#+Ee&+dKh$DVqg!N?~RES>h-V*i1^~Uqb>2*JF+;MHN&v7=j<#&9Qci4JM$&?pD7wHGOMc9Z@ zUP6|Uk2Ttuvc5%MraH8S;h(}eLe5ae;ITl3zA*CM8> zuXM~vUyYdOz9})?{h^qYf$82)fqK5@!7>PEY6r5Z6M{c#&qDY0x@tZ1q4t3FH@cIQ zOcXBgMdA>eN6sqlS1wAq?QNBbj@P#H&bkip&H2Rrz_rEm*f0Z1_;&`Q0~bQYgGP8nsG{~Fyi#wb zxy`rw2sYf*cp5%{9w#4#)1`g;D(C`HGyD?&EXSUN-R$gSY1zDRTIJ(Y`&2exO<+>RTr4$kH7VXjJ^-tH5g z5}pK6_dP|Usz&9Dni!>e=0(l-^oxq}WQc0vUhWy|^0_BDQ@gu6(zx>2!;YKE4tp!P zw(XvHPp*h)b|cv?L~#!tXtw9?^`mAlEt3(YF4E3pe6T8bF|<4|J$S$CfG?-}o4?*?xg?{@FUm?uD--{ zb2!?NwQ*)I-Ns)TQ%D<@P~p3I(!9tGP$cVl;X_ZZh2*JS5&XHSRf$Y=j*zo(qD zb(Y5|FU6d49pQ+0kW>&d@e^dWS(--~N6p3B4@Nolg+{}()aSt#;a7q0L-s(WU~PZb zz!BdLe=T1szYJgT%-hlT%KL*a%2(Uh-1oEZy6=v!o4>9J8FZBv}!UvCUi-C8Jr&u1%`+61V#oY z`d1-(dF|ietLpFRyXkA>8|~}pYwBC*YwYv-hJw3id`h60|JT4Z|GePDz~oT-;3ABA zPpSRF6c)J-VzVt~RwDr)Vh$s>*>AKUsU^;!o27SxAs3a3+kTQ;**7WO9cOG!oEPj_ zT)Q1tT|=F9-057K+$$lcrt7^spZl`AqJScNMzA_7#orhY&8hlm;|HyTo=g=qG5kF23f&7841Rzg zOci|T?;hyxf8?4NA*&=)BMqB#de#AxXzN&@}#dYg`N?w2_D%cl~;<%?QIQ}?)KKUhK_pn zjLuw+tIppXja*}#2VA-{;Hu?vxktDR*JRguS8r_jU4G{^XG3RI=Um4s$8P&$`yQKS zTdEjJANj3Z2>9L$-6 zAv7+yGMGA;E_gF=1X0b9z>+|-z|KIcz}vw1K*`{(z}8^JVA;^^;D^w-(5`U3@Eo;- zI#ny8Ez~RN`;1P;Q*)LXpPywvU^e+@%v$ag1_@8a&7vURlM*UHIi5|j1#PD7g#DSl zk7K<>$(?3$_DX+bT+ue`7u9Ln!4x|q>4KROSl=Y|^fiB?NtpE?U4Q>f}LjA(GLiN?%;UBb( zYHfX&*4enMPr;n%ewKy3=goO)I)_vfuF$@sC{B~|N{i)M@?51gtX~UTd3yzWj6I=a zl;f z2A2dg23rSr2Fe6m2a3T5)WBGNM6f{Ma&dmVMr!@OnaA+6YGz{6ixs8wcthbB=_S6QKTC=@Qcf-PQL3Hw(^cq z_8pF74(goYDByhOsNhWJEaWWg6r9vsv}2QFi@l_S*f-mY+PJNrQpDCouBTL& zn#g&@nvz2(Bt9eYg+2T&nZ}OrKIRrPRH(xM$Fmv!rph)m-pncE`YzYa9x*MAp*C`bc-bb*mrZ7mjozj;1Egv#^^96~t(7`i-4Q+-P8qg`mxQ{8 ziiBPVe+v!|?h6(Ut_ZqeoOIekB@*8EFGR@Z8mdc*o zKEuAw{?4A#k;&25QPHu*@q^=nBd_DUBWz#qSY_`BpC>z3*e2LR$`@NA;-Y0Vn*PG(j1lTpE3tXDCvY0dN`+Ayt;x>J1-*27)H zO@Q)R=vb&tXgYLkaOhreSm;D>N$7m=PUv$mTR2~6Hh7mrmBZWBIpNk?88wq`sH%QR zdt^YT&H2U&HqAWBr(&jVCf`rzlC8o5x=36g43}nzb>tyZBBhCZLdmQ&w>?sx*oMO5 zi}u;}KK9f0Q?QV_{k}bk2L_osqXIekn#yD5a4z zizTHzLN&1ftt%8F^=L6(pOj+_c|Ef^>xK1_`T8j1y0%VFg*m;S)O6aX@K5k$@51rJ zJ;G-~uJG*8iO|5%FQNXSF`;RpnZSG?H?&?zM5L|W8QO}wp8z?4>U>} z&CHZ$WhSsx~MRb*uscv#$4(YD@p(#CAr z?Ir93?9J>O?d|O+?RD(O?V0SW?T>8T?SpN}?7Fhi)?UeA+b54wLXh%ol3lJY=9fAN zwZx&cqcEKepsV;8a)|wc)tq%qGLM_ZFt0mAk8fPks_S{Qx!Nk#r{+@ItLMY-!$ZR3 z!xh4%!WqKOaMG|hlqDPpRSzc&PYzdw$6OGut`haKI#g|=xiy=<6~3OX46QC@iPRg)^iG z{mAQ(#JmTu$fmGi=1%jN@!aqj$&Jo>3;l++U8|ub)*h-;)gfwfHII5Y91Qml-wIa@ zp9$v)Uk&FCe+pL#XTUsZPxW;8ike9+ugz1>YpJz1`X0?;G}Dh7@r>c-4Wlw!VkY6e z*jrwiA0X+;1gev|!VQ{8Tp?T(JBt0Kv{JNuL7FdjkfW7P@{dYe<&<(#;flwW$yUZz zz}Co?#n#v++P<@$SE6kLmD5VJ(oUHr|0WA^W4VpASK2O$Qb71#%qI*KI?*+B5xGjP zVzpDjxU2%J$|jma&HKh)qmZHL&_g|ezD}D5e7Uu`>K!$wI#az9Zl%r*f3Nlk7gw8y z%VWi%tvVe3d}sKvYKDtx&DFIUQ0jHHUHV(CwlPUpjS|LY_`goS&-pw+M{JBb$|msvNSgso;B z&F5IR%xY#a`Wy50t9ml5KCIQYY84QR_|$9a9`$Ef)$;0(YAUst>QaZR@zj-ScJ-dx zSWT}jQio|?^@G+->#E<;LV8PmmJ!g4nG21#W>s@B6ImmEiX|qKus&RyOrl9>8R0&C zFU%FDh}D2EC~m^KU1m9hJWXDXNGnRoqjXW)DBG2h$_r&OI5|R*Y%P@-C5v(v)^?mS zK+dZO@=1A^R6+ht+$~iW6G@8^d%mN)F}teL0i-xR!Uqx?-^UxW5ZjE^R<}9P9AG>( zKI-L+p87VOYdQ60+J3E;))3L8O?wRuyQHpD&#Lp(Tk0Y;pzc<)YtPkQT6*oQ)=$fi zx&6(0O}&V5L%)c5mma2QCSzO7^Q;vc!ISdhSh@F-nPeTUK^qE+z=Zw6VzI555B%E) zeEH<$nC+b=d$E;JDk?pdG0JpcTm($Bm2=7fWw%mZnV{%$C1tt%RW2xxllMwatT+5D z%@p5=pM`Q_1>qOr7y6XGBw1;G(u0iRJNaFvu>!0T`^8*fa>EY}HZ?-}WqllI&7?ok zu4%)yDOx_Qu@+E^YFE{)+7UG;)`q^*ZmOL$O;$fkum|nOkjG+02 zM`S!LOt22XbC3^g2(QL2vmIt8mc|@q&N1E^NsNZZD*d`%T5qbq*1l>>U`yM<+7#Ck zX=$}DYBKE+Wb(0E8uhMN?OU%^)`Hq(t*-tIcC&(B)YzvVHi{ZGAn|X^hUR$YGjsB} z>;^Bz2g66Crc;0~KW!jfrLTofLU%EQS)rj=RSt>=rFK%3d|av{N6Dk*YVt~XfV>qv zT_?}RevI4}TP8UdR-<1^KS~oMNlGJ45Z8%R%q;d5<_nLhC{&=Gk&$o?c_Ud!KV(@v zWv^K+R)w80cbS#U%;q&?8Kf(-A%V`FdLyhjD|!*k^+oG*fMbC6QR|}l5a&4cQCdEI zz19&t-ULoFeGsCc2awGwh!##8XUuA5UG~s?!TPX)+=ZN^4SW@;LJHHjXStjkNaM>h z3~@H(GKZ8x+$}Cd+?fDvjipHhA7Yo*U6fv!~{6)}58(CcDaK@s=bjc~1_LzO)t%(#N!~&_Q@BycX(;&Ba~fdC@NA zlxjntrbuU`0}_+&NSWm4QgQi_R9Zd@3%dfIq?`0a$|5b5Zi+RezL0E194pQgqQyk8 z$Frzg@X!%-EcuFDrB;9bd;ku#|ido5ft1XI^8@gp8)b8ud0~rBTCZ1xu6F*rw}xfBhl+;(0x%eo{|` zV@mz8o?SOFj?H28(K{F$VN+ss4!hFATy2~(J!V0ynXYH5nV$c|mU7Ngk@0*1^0*Sw zg=7j%kA%TB$W+NB+!dAxMMaM|P3$K=5U-0Vq>NHcsWYt2GHIH0R$3rEmFB?ijFKK> zRsFP-TUsoA7CTC-;aO_p`p-f?aU8}C$83~P?Mo>?0ywNinuk-@O7rnY+Gx{01 zjdezASf*u00c8G6Fw2>5%oS!e=3x8SV3w7CVhedE%#&hCDF&=cQhLlbkE)|njNZ(6)q|(wMNbXL_CC!%}iG8FMVkxPq zs9_a)v$$QTC)N^Tgtv6OFoY%+Tyz=MrL)lNWFtAibCYWD5zi3;4`C-@$?LKc<~y^G zInK;#<}u$I&x{?$Vq+{2wueouiTJGoFja(})idlycO#WC(SWT9SA7m4Fc4Ut&=IxMcca4mK_w|$Iv^}M;p)G{M$Ud4Yn1bcON{fRb zr)$MS;#u*n_)xS-FU922V=;|%9u{c5Xo^3Hcg63-)uJYJ5H|@a#CpPM!ACm@(_lL@ z)A@8id|y?vn>^xWNH2blOS~>$%pSAitOu-}z{Z%1&4OlG^P}PA-Z z&d?JXkCF9p5#==M7xi5DTnp!i8d;1zMsutdEdj>2#sagX88GLY4Vi8pV(nQbevM7# zWqF8i=dBTgo+C3zPRht+*z(uNH7F+J7RCr;g>%9!fgmdhyn$Em3N26-{o^jc@idDNJE+!Hf9KV z{SiiNMT7;yMB$!r8CB>>;vnhOq=JGrMfwGN+r9 z;4P|{xy%Hn9dh^4I0nzL#<*t8HLgP{9~tuuud&`pV4gy(@*cAQDa_4geeZFvWOWrieTJY7SdbS6wIDxa&xv>-2ByS z3%UHo%m?oGWgfO4wn{*YwfRT3oR{HW;s44Zb9N^A4*2GgT=XO9Ps`E+bSfn4E-e5} zYA-YurbC~02*-pA;N(MS;|n37_(Vu4UKf&z2L%UaHe$fBYZxJ~5p2Sb@O#CD@n`|F ztFT%fp?^te6LJ!H#62+MlN2`QIL{2-c*0Wfh3pb*4u711m13Vw22DI;E`+=d28z~Z zO|!OH6cU>aqn-?AJ;ZVy%>3pEc+8b%d-F2#%(!^~KK+Z?9~ndYVXqk5#VT{gX7OtL zDPM%V+D{m@lqDx%U!3$AsZI0HnRF0%c$7*4r-g;$LMx%WFaojULgA3G3HrE8cmup2 zf##hs3yAv*r-a(VY9S*e`YWvl*-Ru1rgvyDI-B}PRl12V(w1yTmU2sS4cX}v`5|7O zcY}NUgLik>Ok`)=Vl8+|XkG{Y0k*Rs@`Hzvs>s`&M`ZefRKk4WXxfJ! zLEnExUO-wQGo-Y>&=Ir`hi9BB?8J!YS7A1Mzyuuo18ozWFO2VxO z@Yp|@Gr*_uW+QmVy5>}~0X#{Y2)^sUAH*C-2KKgKhur$VsZwH~J&{b%F zu||2JxsXHnL9h!sVKZ&QPQ1J9Hdgq|U=|!TEiDVzL&iWuHJv%whpYaiV0sjs@ zP~skb0rEMUO=GQDLyQSCg3=(o{Z;dlxz*eY-C76EEi(r|EBnEU42FJ=H7|m*zoF(~ zcO&s;N0x^zWNje{i&zv!m(?-0oywc?D|{(3(O+TKCkIBky)Xm2n>c8Yd`}D00kkh{ z=>~cgw$xAULVO{QkQKR&g@v|4DQH_sVF3Ie&~&p;W;Ui^7AG_7i~UlJMXqAbLj<-GJev3CRrn4* z4*B$_d3N+_NBF-LWHfmQDNO($Ux^k4zMgay;;IYu5_sqXXA;5MeB3Hg9CuTV?K zf@4yAra1o^ao96}Syu*@}T;egX+J|60$HM~D=LvZR$f%#40tZ(C z;TZNa>k4hG4-^#;j}(LFC-MFuRB`!xvT_*t#R8o`?M@$mdtYx~YlAtC5^!AnfN#G8r;@5WW6} zBnOoxX%XOS0v-;eXKQ_8dGs1&TL;{yDJuV}NlGn+z^a1_!4D+k7?vGC2z4*jbo`TMNBAikR#^ z%K&^8cyhciREAH7Z{G|3e!}k)}1y)?FZPR!k9x%OG{9RX2fij4R7zfLtAIiXDi{`hobcc zuw=Oq4NBxBBHv|vH*CyQ%%FFMHK>3{CL=~PGUhJcgBv$tZ;k=yc0{LZU^$keECOGb zu*2{J=h-&I(Z|>q$g>T-k`bekay%Vx3)viv{W?hhCB6lkZoQFZ^3o(T-bAWFCSa{) z6Zm%te&Pe>yO4Yfn$yCU6@$O74*hCDo6@edCHU0>TG<%ZvKDZD2h@3iJq6^F(j15o z;sKu*BfjfoEXG}J;o-~T2`Nb_yaSgQ?|^-Re>%%&@D;o_9|lj~40>1+7*j(^MebuC zA*uJFTNl93Um>#xQ1-&d?MDoDguQ@Ah(S%_?^trolNEs8)!_Ldm9^m;dh?AKH(Ue< zKjS?w>+Qcnm_us_e1jmL^AV@*#f;NU*qBf76%w>5DI%?`(8hwaD)tTF)tV!AZVA3N zhXrZ~j#Z-xX=%z~b>Cq&=L%w$o#Y8@%Tc`1wS?3sKS4el!iwd`XvIaY;9aw=(2Z$` zFM9JKydLlshc!(PTk3*+R~a&NfZ{2;1zw&9mrkPm%5Gym;}JW{-m>e^xhG8FpD|M< z09kTasRFzsuL=J3K(9?j>s#Vo*B``Kb~)x8$KWltPLR+lkoz34 zEiPic>!%?uybJx`%V#2n>CXoMT@%FHrFm|i36w?wA*ODDFa`+U1JxUF@eR259=KwF z*kI3?6Jwwh++ev8uat-WHiO>vX9B;n!j@#Ab|5uKQu>*==p($fcMd(W6Fsv4 zJ@hm1wL_0pChdW*Qe^)63*IHX!Cyo3&%lDOM=UxCGhMwPSq&heWiTt04H%PfHzZZy z8nAqY{r`aSK7v``Uzr=WBpKv58;=jZXMk)L!8?f6AqnkaHHTx=un_vUkH3Qllz=Zi z;_EV`0PH{=$Wu>5Qj_r>;Tmx82x8KkkhC|@#~|j}1YmJP4ilgxMm-S?K-WG1`xDFn zTmkP6V=itT<^pB_i`e*1LQLY;xiB4&HM`axd}V47q)H@yx>UC*M--C zq?Ut?C;)$v1@;Tz*?Rk zni&Ime2=l+Q_S92a(M!^?O4ZLf_@nfPt%*sfR|_`_=(=U{%L?EE9Q;`K6oS z-(l$BT13IKupbUCcH=*R!j6!&1{gb4gv1pCj@&?y8T?9zlA7lN-U6^fC4jObzO9Q| z8=&lqo*4s_^U=m;v~>b)-UrIBcsEvoMN5M>gbM>-HAGQu@NQ~9@Nhir%slk}T12Hg z5g#9h&p3r~z&Xh41z@>=(c)>0IF17G9w6U{9$1V|Q^CO@ur6I7 z{UUgVh3_`^M&8fe%uiw@xCP#7K33{13j1Qz)|S^oTv{31cd$97fV3nmWJ%yDgISx3 zKv)CV8{ymbu$q0q!I7xVf^}JqwW+ zt-!x(u$)EklyuN`Cn5?zXn4vG@Cy+goQwIw@sO@T{AWaty}^@qu!N1lpIX3TML6YA zzK8Yy9{N@ReNY8g)W!&*X~d>XM8C|3rP_ct4xz2fh#j6|9yx$_ogI<4zwMwQ6==y1 znkvGkH-;W|1-c=K|0ls;%!4+q1ofN1$(_Ku5BBu{5FY^ceL%khHg_XrdO0+A4ti!h zEaqTR4{}frE#`&pr9#^dtmOn@v0nk-4UFS|1Y7VUC8X(&X`8>xz!oPF8-yI*h zgc;!@3X^QG;w2HQRfkly0G&O^NciT-Ksp;^oQ2S?Wx%ikh?YZgm!d2{eKyWcLTv=B zW0(x={D-lOw?Y6=bE<@}w6S_Dy zg0Tnq*a;}wVQa%%p|pS$w#1n>K-2-(bi=iManDeo8V|0`hF@60k70imJ@*`My?gN% zya=2zRd^6 zW|3h)*$3Bl#6691Z&kz#C4ny|Y)eX#JL2DU#4jK4?)?MIZe7Iw2=?0`RV$z~bFrTS zYDe?Qkh@Xv{6jIu7yupn5or5j-xqq?4`&DAnqjzV46dGno|y}~vJ#T86;a<|Se1+L zun!=g?_oc!UsP}+0!;z_<%q;Fb=|1q(70 zh^9l+CL@9#3!6C{sQQCz-QY=EK`QH^&nkj{MPWa);VH@S8wd{IQ=u8}(a#UT!^`mX z#~`6QVb$02U*Hd?z*>xj)QtfB!=RHxfM^Khb{NV?)W_nSg>5#jS%hoXV80#v!`Pok zkKKV@zryIqi#U)*W<(^C20kzs>|1eYOC`utT|`waU;#UU&R)=?{_ti$VU#!wIypSD z{R~V$N6z$xJa&g-+nCo%XHe9=xZ-NBu zj_~dl+IosM-(w%ZGX(s~MHKWe1$sC$@a2b$mV#7Og5|3TlnsHhIkvWt)sB$9F5ppD z@Ukm3tqV#=AZ&|sE%2!!uCaQgGEkNQ%0fVy1AP^XFFovM63oFk5W_IUhF-|%8&L8P z(sT`de+K$<1YFz=ery3J*Maht;LK9!*J6}~s4v8s#gO8qkzUx2+Fo3J1pRUvI(!AQ z5_hqGj-LC#U&8-=hJ32qW2?0snI&UdV*DQlQOv@C^$3(BhvLbJ%YYT|9vl z-3Go(@D?Z0?}s5R$lgN9=>x6L=&iBBw-{{Ye8U%8K638|n3e7?YL+z2Ae2RUmCOBRCs?ON}6Z zjex8HNIs;j_g5J6V z&OHUPchK?}NQ#CYwSGCq13HqB42Wa0!`9`)Ruo%laN~RMu@W#=1vhH|O$}hF0lBRK zbQZ23fW88_R~EGr;9DWwl^geFK~JScTS?Jp(b(I7kHKPx@H;JExDV24X^GX_4}kF| zFkS+!XF%<7;5-8Q4+866aA(hdlmn@#DZ1`?VSvKbF;+kuaQiz@JWBi`u~`ua6E_yl@$4;XKNR*TxR(4>=~ z{8w=E2v8i3lw&~lE9w^dQ>dN8HJ5Phb?on8{}8RbKx@B6@O^-MTAHq*M+Hcy1J*4* zbR}7YhuI<+Eh_WF+7toG60kcKH@^egauLK9>e8r}#HV7Y6~a~dpuIV<&w_nAAWR7k zCPJGYv~7b2w0@yVg@5-#dOl(V^BP=y3Oo7$+imp!HR#V}_>A)rl&8VZlfZI3g2%#S z$>Ld@JCB;x6W4I%OU@1=-_Ucl!IIB!{`E9j5w;QB52 z(z`(Q5PfA~dyRHKKsqch6pYBH#XlGD#fSVPMQ^797t^EPGlRbD*m6fO<^#%t*a`zr z5tO2lQULY*sO1I1T;N+aT%8&Bq{qFfz`>;GtAx;Ni+^@JMT9Pxcxo6=_W|W+Q1e@a zs@Kq+=Ro)vls*96cOi4PvE2lM8xh17p4+J3L9zH{*^3RlgpMds95t+RY zq!!kDz;ZuQ?&7<95nR?)7B)*J-{S7~*nh^}i@hbA8t`$T6!BCW`qk1w%Z?@jJ(irN zfLx`Ha3L)yP9MRV5hyZ6IGY)tGvj=w$T!v%snH`TfX?EXrE~GohQ&80_6ph-@C*iz zt3fLQ5qtq~F9y=|8R#s@vM^eFv@HB{pnMv^YVq_j@Wz(MIQs0oepM!RnGpY^M5GI~;g#BiW9(8rbqw=~5U;o}F;_8ZW? z!~RW#>NnucYm`4W>yvfX!t@Tc->|o2@-y!HioJ!+;+=}UWm^ceL5ScJK!L?WOHN%8 z$}B!60i~ATNDi7U+iGD=89`#9NfFtSN4~MVXEN|D3GPkwJ2vaL*gR<0g`Ts1z0SfX zM)c3(p{0YCow0ny*N9YER?o5yaX8;cu)f7UuDpw!vAAvZgk_y9?thG6^J4EuI~MOO z*))LC;-B>!gi^#aNuWiE$Y~UMJsxWDfi@v(i9mH?)RIIHB*rneB*rljwuIOcV2dBQ z!_wra-?8E6M1W03yGWmm@Xw5Bg^8zI79b3CR*zfJh7T0R0HMW+FF^Sj#o9hbwoeh{ zA0v3IZ>_7WtK)E4t%T5895#mbOtN3wm0JtoR6#_O(@-6AGw7`t;PQX(oJU#X|4lPNtw8gUKmSkDl zV@a7Clv`YhD;5&#Q|#u(_txf$+~LHX4zv=BO$IiLcX9ZvU$|tjp$49BVbri!Ba~Sb zh9g*m5sEF!ga5I8TMyxTYYRuV*t_w90b0@{*s!FHCs;jc^{Dk*nAX!R4Y7LK`b|fx z*JH6-Jh1S_7K`$~Zq^mn7W>PO*1gtd;gYaf?ON?yPqO~dvG}u|j`X7lHAuY%PK!3} z_e}-jILsD*t@6iaaVhRf>#o@Q4IHgLi$!L&Z~a9c8Nq0ww0`9?7O6#*Mcp5pMeje` zVz099u`&>OWuiEtWWJ|LpkZ_N_ksb6bDl zwa)*&zi+SnXLYNkZ@>F{E&uhZZ(FeHe=c#D|I`kUh`k2JhuUOi@OY5Jn`*!?iMNi*u ze?(K(J%8sf4#(d;{+%}eOz)p*`gh;`c@+LFHmm-h+xmC({AXNok;0#2hyVQPpSS#H zI{r%I-~ard(fqmP*zf;29sm2WL0s?rt7pVf`S)@CqbuWD`PZ1@==t}@xN+7$KmPfN z-}dZ(Mr(chcm85qiK8y=3D)PhdTc9yx4l2^`j);w>Tz=c-;SH(p8oAIj`nZQ#nxlx z`tL}}Kk7+qPXCW$tt$MxV)5QW^~d&CjB(@RZ)vsW!Tu<5b7TMf_{TT@7~fy9e2c+a zhp|3ev(W#n#Lb`m_4o&>I3C5$hsN>g~v1X&=%D3}^f6OVyo;Ch7 zYZ!M&+|g<^_6Zgi3rFmXs5P${JHIVQ=5ejLUTc=xnyw0d z-_{zL1D~wfe;GCFzX4h6Wfs@1`ATcn*;;S0=IO0DdTS>BOJohgT6M5iQ{Mi*qGYY0 zy}$~RwTkvEvXb@^>t)u8nzhFHCbAaz9M@YJM6a$zXhvXz+<#M7)bYwLe9 zS^sUwTDNv%1torD9m!e+v)0J0^+0QVH!C)4@FD9KRQ9Wjl7wGdoF#S}Lp- zCc~YHaDOybXROs58OW{w5M`}b2k>-jrNmn6j9sseU6Z%gaBpCh-CC!6N>au%5g=dm__3Ey19RkyLGeIGR|bKy1C4nLqzVt_h~RT+-Gf+t4-o3)B( zt?Fd}mDzzMFV<@dVU60#H?Z<5${{nPJhCY&Ag{v8rKpIUit;Gs@VN}m7sr{x=G+8Dl2fN23jlU&W62#-i!f0Yjyb%`uPT^ItRLrfgk&@ZNs)9lCNcD zYc0Yy7ujdCk)1XZ#~H}lnu$y_D<^Fpu3C)jpOwgx*%-lUWH3p70$j<7Fyt`i5`XLi-Aj%-r2O%46AW-&0CRcCZ z?}|(y>kY~#;9@NxtAO4r26?sKtV|81>cU!E? zon6S$S_|41f!Z0!@tlBdL?jnQ zE0D#z7VkZ*M_%uGWNWX*H>-eh39@46Ae(YB(2ank{)h~<_Gqm>S}hOm6@XPu2l@0M z=T!r~cd!a~z`4`l-EQ>$8X&VWt0#i$VgIYWGXb)qI-_tfrAZ0KRB6}@APf?btrXBv z7)8P&Dgq+H=&;BlvI#gvkVPqW3?gu0hx)jf$Ze!WlG^xF@C6o5cFZfkoB8GG%rkGr?D}-p*33Wez-;@j zypqZM>_O-pjoK;9ip^yv>~b_JM|aS|s)j2+FQVP9z+8eTS;gj$*Z$KWT z9z5&Eo+CJB0$Dqoy7+st^(Cn7ATJIxt48{YqOT&YKy7lU3Gus!2tGh52a{*xP^bCj zv+)Z&hg)C~o|WhEKrF%Wu^2zke4HS2@Vv}G?|AkYN&Y^_)_p|2B{^E3Jim&pC`0xa zCP&no?Iv?xqYYmTBDKk&Y)szKEVU3m(GpGln*38u6b`End&#Td+GwulOZ>;KkJZisVijJwr2EhE9}8 zvyw+p+6iP|Hc@*PHA`@LtU%Kmye(^R>#V|mv<#olLVO={_&=ql5zldWBL+dF7xl0W zN;Nw_m9v&7`!D42IQ4Ho?aQ0AZEMM-=V;v@N8fMJH-JTTu02`UifA=M-z{jl2~9Tz zZK-IkMbzp9_tJgr(Fc7)$<{0~JBLhNO8j1?HQhyT`gi&WdFDz(wmQABdgu(=mY$SJ zUWmu|MY@@k`nlljSWc8S1m8{`KIuHXJDXV7;oDq>-g&%}jR!qqU{g7vylj|qK+-19&Zsn_H^39(X@;Gh+P*-%r8-)us(}?NomBcHoDSS z>*8)zjy7W}gT1yM$+0$LEkgzTZ_J}JRU&h7mNWfrhmVJ7VZXm_vX~Udx_$M zWY{D0X_IL$a{i@n1u8ZKhuJ!`t;T1j*exJupW@Z2WbhbTo`=ZK9?+4OT7Jjs>s%yz9F4{ zuLm_~5b;yXKOGHo(Xs?htBKtUtedEVn|N&l^=}PPTS_}RkG->LmBy3f!$Kc;3t5^< z{8GqLjgU^D?|sI+Tj`q>2DOO&b~Y|VCi zT9~fna3*nkIC!r5(#H>D43tIAKN34I6YgH95~pYuJo9An?=jHK!@m$e0Tup=>y zo}|8%b|}5XSo-)$=$OWm&6>mZY+iX1UDMfT5~H`@!DU3yCeKwPTF`45#avFyTrBi| zCCJa8(7zw0{oKRYa|_wIjvQS;`DURmi+VVM`qZCxzc+QO3(@I_igv7R*lvTacD&b- z(ODNF);o*{CO{^eTD*XIyq1i34Q9K@jgP4V=P;VrFS3?rY*>>qVtumd4ocPmeLZPu z2GCCoC*vNaHfGVHPNYUoCKD&4X(H=mY>(mDaJB}J(Y{4ONaVrA2s#NY13Um`H6LOB_d1?jhvd!zh*GYGBCRe#CbG+Tatl)V>y#&6I%fc8<}BnGoRm=sg-@u*#|wDsO!yk54QBKzVEgoZcWJT`Vf-qN8jaBcr1p#!qfqIl5}Nc zA6F>0!&lz{H&Ut<)SQKA%q5buP^vNMB$n~SGK;#Eg)YTBf**E7_-#T>PY zmg+^mjcnm@Cy)CJe7`NiH_zgXE>fr^)yUE7$kckMY)o#opheAK#N9r8$L)-QZp8C` z)?RG&Vw~9%{oT=aAA5Bmb{TwgYyq8H$%VSK$f+o+67&^8pMJSoSA7nJZ=d_=fp<~^ zw~(QEXq0{HQrBjd+LC~QW1p(_-vS#*se@m+O7O-J6j zhc>AVElD~=ng?whYEn-X8Vb&6N#qL#FFFyxFT1APtb2+pGO~Yf?nwp>d5=lKsos2GL_@)Me5L66t18?$#W&gmE2`>S#!fW zpKUqLmhj#Rw$?&qBV=Adn_NxX!#B$vH+4ez|bRv!JQoLX<7 z?H$gti#~lnk00@Pj5@CCgZkxl{pxrz`uH-?u0V~cOu4F~GL`;98gFE&N2?*74bjn% z%x%D0pY6IlyMe7*>?044+-Q}^%krE>zMY~x>N==ASMuz9Mt*(*SIvgk?EgQLsc(nU zy@|rj^kKU4xsmd(L#ZMv&(%u)uH^YjBDI?L*Rq!!y)OoB+i0nFQk&)cIl%Sc56O*B zQF#)T=R#Gp`sHAdqv2BesR|*pDuy`9TNd3&(RY=Gnlz%NwHDjgvUN3E+N&y$6{&gU z8S$0ju{e)%9mxA}9xbS5?`u|g^jsaLAKs6;{Oh}0=npp&k^JksiRWrPni9{|3%tLP z{qop5@m%qne8g@qj|X}DkVjn^KSBI-)m*c~HGf_n2>Bl5*SU;ESF5X1Ub(KSqe8x` ztI0y?smUt8m7H~onOt@i*;9_Yva~6>j$Mp)MGhIc52P<%!~TN0ajNG^Za%rEY_YI^3Po!qFI?o-FuMVstWO{95l&Cmco{NfTcL5 z1jowNq_ZhEb-zXTS#(EAo-66g_goz!OXZr{OIhVblCMn8GAWIItAd^@InH+Sj`os6 zE8cI}4W)f3i=Hy+i@u%XTw_W+Nph7+qa2v>Bgs8glJb@!5|;+8q2*`5`FR`$#W%_iX1rdAw|#CZZb`=lu|jZv?zP! z8r&IP&G%is$8qXu_HhPzlhpHk$eBM0`s6CneKN&R&Kl+Eg=mylM?RhCEt40iB<25Q z(5kq~ZxuaPWq7SL@0Vf^-JK~3n|#mJ1)L}GT*+;rdHR~?FLy@tTpb~wKBio9P02ka z=bIc=a#ro7NU-_?GOI6&MEq3VO6OUq?99fM%LKKV0rPcvU* z;zvq!$|)u%oLpmaS|y8KRivZm>gO<#PcC|{L@Ro(3VM=a{FFJ-qa%&cb0zmwzTZlo z-RQQ`qoS)-uf|21K0=v}k}kQK82Z-p`Gmt3;bxu6)mx@>BQRb!Yjjo-371I#qMzd{c?#@Qc1H#rLbO zE4>>%S4YEDhPVQFgzO?RM zYi}JT2UGOQNt^s~s(U{UpCo+=HI6uYRe zpzlg0h)yJVj}qUNoK*5tMPF6)TO|&x_&2_rc*vsPO4*+8B~#qu916|i(9DNqhCuX{ zMZZ?wz*SDg&Gx7NKbNiLEgMjMW+4Apf((>(N@?Qrrw`cJG+q2+2 z!mn>9GXay}e8vYsRnKK;Kj+fSE%qV;so zlN^8gx{}(QoKb&&c&+Y#;!sf8nchy~nGj2!pXtx}zML=7sq&n turretList; private TextButton confirmButton; + private String turretDescriptionText; private GdxGame game; private SpriteBatch batch; + private String turretDescription; + private String turretName; + TextButton turretDescriptionLabel; private Sprite introSprite; private Label message; - private Label turretsPicked; private Table table; + private TextButton descriptionLabel; private static final String TEXTURE = "planets/background.png"; private Set selectedTurrets = new HashSet<>(); @@ -67,13 +76,11 @@ public TurretSelectionScreen(GdxGame game) { turretList.addAll(Arrays.asList(TowerType.values())); // Restrictions can be added to the arrays i.e. map == "Forest" && level == 1 using for loop - Skin skin = new Skin(Gdx.files.internal("flat-earth/skin/flat-earth-ui.json")); message = new Label("Select your turrets", skin); - turretsPicked = new Label("Turrets picked: ", skin); confirmButton = createButton("images/turret-select/imageedit_4_5616741474.png", - "images/ui/Sprites/UI_Glass_Button_Large_Press_01a1.png", "Continue"); + "images/ui/Sprites/UI_Glass_Button_Large_Press_01a1.png", "Continue", "", ""); Drawable pressDrawable = new TextureRegionDrawable(new TextureRegion( new Texture("images/ui/Sprites/UI_Glass_Button_Large_Press_01a1.png"))); confirmButton.getStyle().down = pressDrawable; @@ -85,10 +92,20 @@ public void clicked(InputEvent event, float x, float y) { } }); + turretDescriptionLabel = createButton("images/turret-select/imageedit_28_4047785594.png", + "images/turret-select/imageedit_28_4047785594.png", "", "", turretDescriptionText); + + BitmapFont font = new BitmapFont(); + Label.LabelStyle labelStyle = new Label.LabelStyle(); + labelStyle.font = font; // Set your desired BitmapFont + descText = new Label(turretDescriptionText, labelStyle); + descText.setWrap(true); + descText.setWidth(190f); + + turretName = ""; // Centered the message and turrets label table.add(message).center().colspan(4).row(); - table.add(turretsPicked).center().colspan(4).row(); int towersPerRow = 4; // Set the number of towers to display per row int numRows = (int) Math.ceil((double)turretList.size() / towersPerRow); // Calculate the number of rows @@ -105,11 +122,19 @@ public void clicked(InputEvent event, float x, float y) { Table turretTable = new Table(); turretTable.center(); // Center the contents of the nested table + descriptionLabel = createButton("images/turret-select/imageedit_15_5627113584.png", + "images/turret-select/imageedit_15_5627113584.png", "Description: ", turretName, ""); + + //turretDescriptionText = createButton("images/turret-select/imageedit_20_9050213399.png", + // "images/turret-select/imageedit_20_9050213399.png", ) + + TextButton button = createButton(turret.getDefaultImage(), - turret.getClickedImage(), turret.getPrice()); + turret.getClickedImage(), turret.getPrice(), turret.getTowerName(), turret.getDescription()); button.pad(103, 15, 0, 0); button.addListener(new ClickListener() { + @Override public void clicked(InputEvent event, float x, float y) { logger.info(String.valueOf(selectedTurrets.size())); @@ -123,20 +148,17 @@ public void clicked(InputEvent event, float x, float y) { selectedTurrets.remove(turret); // You can also change the button appearance to indicate unselection logger.info(selectedTurrets.toString()); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); } else if (selectedTurrets.size() == MAX_SELECTED_TURRETS) { // Turret is not selected, but the max number of turrets has been reached message.setText("You can only select up to 5 turrets."); } else if (selectedTurrets.size() < MAX_SELECTED_TURRETS) { // Turret is not selected, select it selectedTurrets.add(turret); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); logger.info(selectedTurrets.toString()); } else { // Turret is not selected, select it selectedTurrets.add(turret); - turretsPicked.setText("Turrets picked: " + selectedTurrets.toString()); //logger.info(selectedTurrets.toString()); // You can change the button appearance to indicate selection @@ -162,6 +184,20 @@ public void clicked(InputEvent event, float x, float y) { // Centered the "continue" button table.add(confirmButton).center().colspan(4).padBottom(20).row(); + descriptionLabel.setPosition(Gdx.graphics.getWidth() - descriptionLabel.getWidth(), Gdx.graphics.getHeight() - descriptionLabel.getHeight()); + float turretDescriptionLabelX = Gdx.graphics.getWidth() - turretDescriptionLabel.getWidth() - 11; + float turretDescriptionLabelY = Gdx.graphics.getHeight() - descriptionLabel.getHeight() - turretDescriptionLabel.getHeight() - 7; // Adjusted vertical position + +// Set the position for turretDescriptionLabel + turretDescriptionLabel.setPosition(turretDescriptionLabelX, turretDescriptionLabelY); + descText.setPosition(turretDescriptionLabelX + 18, turretDescriptionLabelY + 70); + +// Add the actors to the stage + stage.addActor(turretDescriptionLabel); + stage.addActor(descriptionLabel); + stage.addActor(descText); + + // Center the table within the stage table.center(); @@ -174,13 +210,21 @@ public void clicked(InputEvent event, float x, float y) { public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + batch.begin(); introSprite.draw(batch); batch.end(); - stage.draw(); + + stage.act(); // Update the stage + stage.draw(); // Draw the stage + } + + public List getTurretList() { + return turretList; } - private TextButton createButton(String defaultImageFilePath, String alternateImageFilePath, String cost) { + private TextButton createButton(String defaultImageFilePath, String alternateImageFilePath, String cost, + String towerName, String turretDesc) { Drawable defaultDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(defaultImageFilePath))); Drawable alternateDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(alternateImageFilePath))); @@ -189,9 +233,8 @@ private TextButton createButton(String defaultImageFilePath, String alternateIma buttonStyle.up = defaultDrawable; // Default state // Create button - TextButton tb = new TextButton(String.format(cost), buttonStyle); + TextButton tb = new TextButton(cost, buttonStyle); - // Add click listener to toggle the image final boolean[] isDefaultImage = {true}; // Keep track of the image state tb.addListener(new ClickListener() { @@ -211,15 +254,38 @@ public void clicked(InputEvent event, float x, float y) { } }); + // Add a hover listener to update turretName when hovered over + tb.addListener(new InputListener() { + @Override + public void enter(InputEvent event, float x, float y, int pointer, com.badlogic.gdx.scenes.scene2d.Actor fromActor) { + super.enter(event, x, y, pointer, fromActor); + turretDescription = towerName; // Update turretDescription when hovering over the button + turretDescriptionText = turretDesc; + updateDescriptionLabel(); + updateDescriptionText(); + } + + @Override + public void exit(InputEvent event, float x, float y, int pointer, com.badlogic.gdx.scenes.scene2d.Actor toActor) { + super.exit(event, x, y, pointer, toActor); + turretDescription = ""; // Reset turretDescription when exiting the button + turretDescriptionText = ""; + updateDescriptionLabel(); + updateDescriptionText(); + } + }); + tb.setDisabled(true); return tb; } + private void updateDescriptionLabel() { + descriptionLabel.setText("Description: " + turretDescription); + } - - public List getTurretList() { - return turretList; + private void updateDescriptionText() { + descText.setText(turretDescriptionText); } @Override From 88241320370d336b3901a912d187837783422f69 Mon Sep 17 00:00:00 2001 From: SonjaMcNeilly Date: Tue, 3 Oct 2023 00:19:11 +1000 Subject: [PATCH 41/49] Updated Currency Display --- .../csse3200/game/components/gamearea/CurrencyDisplay.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java index 33e22aeaf..5f3a12996 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java @@ -18,7 +18,6 @@ import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.UIComponent; import com.badlogic.gdx.scenes.scene2d.actions.Actions; -import org.w3c.dom.Text; /** * A UI component for displaying the currency owned @@ -29,7 +28,6 @@ public class CurrencyDisplay extends UIComponent { private TextButton scrapsTb; private TextButton crystalsTb; private Sound clickSound; - private TextButton test; /** * Adds actors to stage @@ -55,11 +53,9 @@ private void addActors() { ServiceLocator.getCurrencyService().getScrap().getAmount()); crystalsTb = createButton("images/economy/crystalBanner.png", ServiceLocator.getCurrencyService().getCrystal().getAmount()); - test = createButton("images/ui/Sprites/UI_Glass_Frame_Standard_01a.png", 100); table.add(scrapsTb).width(scrapsTb.getWidth() * 0.5f).height(scrapsTb.getHeight() * 0.5f); table.add(crystalsTb).width(crystalsTb.getWidth() * 0.5f).height(crystalsTb.getHeight() * 0.5f); - table.add(test).width(test.getWidth() * 0.5f).height(test.getHeight() * 0.5f); stage.addActor(table); } @@ -73,7 +69,7 @@ private TextButton createButton(String imageFilePath, int value) { tb.setDisabled(true); tb.getLabel().setAlignment(Align.right); - tb.pad(0, 0, 0, 0); + tb.pad(0, 0, 0, 50); tb.setTransform(true); return tb; From af22dc5dfc74caae6714959db8a6f296ef8d3527 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Tue, 3 Oct 2023 00:29:15 +1000 Subject: [PATCH 42/49] Changed the buttons to be images --- source/core/assets/images/health_upgrade.png | Bin 0 -> 11226 bytes source/core/assets/images/upgrade.png | Bin 0 -> 33249 bytes .../csse3200/game/input/UpgradeUIComponent.java | 15 ++++++++------- 3 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 source/core/assets/images/health_upgrade.png create mode 100644 source/core/assets/images/upgrade.png diff --git a/source/core/assets/images/health_upgrade.png b/source/core/assets/images/health_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..227239bcbbf080a1a510a473b4c56008366370b5 GIT binary patch literal 11226 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/upgrade.png b/source/core/assets/images/upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..d45aa576830eb22b163c6dd47dc0b16f83fb2317 GIT binary patch literal 33249 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 100) { value -= 100; ServiceLocator.getCurrencyService().getScrap().setAmount(value); @@ -179,7 +179,8 @@ public void clicked(InputEvent event, float x, float y) { } }); - TextButton upgradeAttack = new TextButton("+A", style); + Drawable attackStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/attack_upgrade.png"))); + ImageButton upgradeAttack = new ImageButton(attackStyle); upgradeAttack.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { From 7789bfcfa0b81a0f327d02a1d6ff36ff1b16428a Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Tue, 3 Oct 2023 00:35:00 +1000 Subject: [PATCH 43/49] Fixed wrong image path --- .../src/main/com/csse3200/game/input/UpgradeUIComponent.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 46a459f1a..d74480a74 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -15,11 +15,8 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; -<<<<<<< HEAD -======= import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.utils.Scaling; ->>>>>>> cd6213c7d2005b93243b4dd58bf270415c88222f import com.csse3200.game.ai.tasks.AITaskComponent; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.areas.ForestGameArea; @@ -207,7 +204,7 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) } }); - Drawable attackStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/attack_upgrade.png"))); + Drawable attackStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/health_upgrade.png"))); ImageButton upgradeAttack = new ImageButton(attackStyle); upgradeAttack.addListener(new ClickListener() { @Override From 54708507434773a9362dba277982f4cb9f0a98d7 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Tue, 3 Oct 2023 00:43:28 +1000 Subject: [PATCH 44/49] Fixed file path name bug for WallTower so it doesnt crash on POSIX systems --- .../images/towers/{wallTower.png => wall_tower.png} | Bin .../com/csse3200/game/areas/ForestGameArea.java | 4 ++-- .../game/components/gamearea/GameAreaDisplay.java | 4 ++-- .../game/entities/factories/TowerFactory.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename source/core/assets/images/towers/{wallTower.png => wall_tower.png} (100%) diff --git a/source/core/assets/images/towers/wallTower.png b/source/core/assets/images/towers/wall_tower.png similarity index 100% rename from source/core/assets/images/towers/wallTower.png rename to source/core/assets/images/towers/wall_tower.png 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 3ed44061f..63fca5f5c 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -89,7 +89,7 @@ public class ForestGameArea extends GameArea { "images/mobs/Hurt.png", "images/mobs/Idle.png", "images/mobs/rangeBossRight.png", - "images/towers/wallTower.png", + "images/towers/wall_tower.png", "images/background/building2.png", "images/iso_grass_3.png", "images/terrain_use.png", @@ -591,7 +591,7 @@ private void spawnWeaponTower() { for (int i = 0; i < NUM_WEAPON_TOWERS + 10; i++) { GridPoint2 randomPos1 = RandomUtils.random(minPos, maxPos); GridPoint2 randomPos2 = RandomUtils.random(minPos, maxPos); - Entity wallTower = TowerFactory.createWallTower(); + Entity wall_tower = TowerFactory.createWallTower(); Entity fireTower = TowerFactory.createFireTower(); Entity stunTower = TowerFactory.createStunTower(); spawnEntityAt(fireTower, randomPos1, true, true); diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java index 83582470b..47096ea75 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java @@ -76,7 +76,7 @@ public void create() { for (int i = 0; i < 2; i++) { // Use "building1" for the first tower and "building2" for the second tower skin.add("default", new Label.LabelStyle(new BitmapFont(), Color.WHITE)); - skin.add("building1", new Texture("images/towers/WallTower.png")); + skin.add("building1", new Texture("images/towers/wall_tower.png")); // Load textures for building1 and building2 towers1[i] = new Image(skin, "building1"); towers1[i].setBounds(Gdx.graphics.getWidth() * 40f / 100f, Gdx.graphics.getHeight() * 80f / 100f, 100, 100); @@ -131,7 +131,7 @@ public void touchUp(InputEvent event, float x, float y, int pointer, int button) for (int i = 0; i < 2; i++) { // Use "building1" for the first tower and "building2" for the second tower skin.add("default", new Label.LabelStyle(new BitmapFont(), Color.WHITE)); - skin.add("building2", new Texture("images/towers/WallTower.png")); + skin.add("building2", new Texture("images/towers/wall_tower.png")); towers2[i] = new Image(skin, "building2"); towers2[i].setBounds(Gdx.graphics.getWidth() * 50f / 100f, Gdx.graphics.getHeight() * 80f / 100f, 100, 100); stage.addActor(towers2[i]); 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 1341746fd..2b8cbb06d 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 @@ -38,7 +38,7 @@ public class TowerFactory { private static final int TNT_TOWER_MAX_RANGE = 6; private static final int TNT_TOWER_RANGE = 6; private static final int TNT_KNOCK_BACK_FORCE = 10; - private static final String WALL_IMAGE = "images/towers/wallTower.png"; + private static final String WALL_IMAGE = "images/towers/wall_tower.png"; private static final String RESOURCE_TOWER = "images/towers/mine_tower.png"; private static final String TURRET_ATLAS = "images/towers/turret01.atlas"; private static final String FIRE_TOWER_ATLAS = "images/towers/fire_tower_atlas.atlas"; From d73366e5d6c7d055bb4afb63f40f280efef63db4 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Tue, 3 Oct 2023 00:50:22 +1000 Subject: [PATCH 45/49] Corrected income rates and attack rates, fixed componentTest to correctly reflect attackrate changes --- .../csse3200/game/input/UpgradeUIComponent.java | 14 +++++++++----- .../tower/TowerUpgraderComponentTest.java | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index d5830ebe9..6f04ad320 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -142,7 +142,7 @@ private Table createUpgradeTable(Entity turretEntity) { float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); Label healthLabel = new Label(String.format("%d/%d", currentHealth, maxHealth), createLabelStyle()); Label attackLabel = new Label(String.format("%d", attack), createLabelStyle()); - Label fireRateLabel = new Label(String.format("Fire Rate: %.2f", fireRate), createLabelStyle()); + Label fireRateLabel = new Label(String.format("%.2f", fireRate), createLabelStyle()); Table costDisplay = new Table(); costDisplay.setWidth(0); costDisplay.setBackground(drawableBackground); @@ -239,7 +239,7 @@ public void clicked(InputEvent event, float x, float y) { value -= 10; ServiceLocator.getCurrencyService().getScrap().setAmount(value); ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 30; + float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 0.2f; turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(newFireRate); turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, (int) newFireRate * 5); @@ -295,7 +295,10 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) innerUpgradeTable.row(); TextButton upgradeIncome = null; if (turretEntity.getComponent(IncomeUpgradeComponent.class) != null) { - Label incomeLabel = new Label(String.format("Income: %.2f", turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate()), createLabelStyle()); + Drawable incomeDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/economy/scrap.png"))); + Image incomeImage = new Image(incomeDrawable); + Label incomeLabel = new Label(String.format("%.2f", turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate()), createLabelStyle()); + innerUpgradeTable.add(incomeImage).padRight(5).width(32).height(32); innerUpgradeTable.add(incomeLabel).expandX().left(); innerUpgradeTable.row(); @@ -304,14 +307,14 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) @Override public void clicked(InputEvent event, float x, float y) { value = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (value >= 10 && turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() >= 5) { + if (value >= 10 && turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() >= 10) { value -= 10; ServiceLocator.getCurrencyService().getScrap().setAmount(value); ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); float newIncome = turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() - 5; turretEntity.getComponent(IncomeUpgradeComponent.class).setIncomeRate(newIncome); turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.INCOME, (int) newIncome); - incomeLabel.setText(String.format("Income: %.2f", newIncome)); + incomeLabel.setText(String.format("%.2f", newIncome)); } } @@ -346,6 +349,7 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) innerUpgradeTable.add(upgradeIncome).expandX().fillX(); } innerUpgradeTable.add(repairButton).expandX().fillX(); + upgradeTable.add(closeButton).right().row(); upgradeTable.add(innerUpgradeTable).center().expand().row(); upgradeTable.add(costDisplay).left(); diff --git a/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java b/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java index 9af62e404..973937fb1 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/TowerUpgraderComponentTest.java @@ -60,7 +60,7 @@ void increaseFireRate() { entity.create(); entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 60); verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 60); - assertEquals(12.0, towerCombatTask.getFireRateInterval()); + assertEquals(((float) 1 /12), towerCombatTask.getFireRateInterval()); } @Test @@ -76,6 +76,6 @@ void divideByZeroDefaultToIgnore() { entity.create(); entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 60); verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 60); - assertEquals(12f, towerCombatTask.getFireRateInterval()); + assertEquals((1/12f), towerCombatTask.getFireRateInterval()); } } From 756e89427f69b74983d901e7487d0e45206c5ccb Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Tue, 3 Oct 2023 01:18:55 +1000 Subject: [PATCH 46/49] Added new buttons for upgrades --- source/core/assets/images/damage_upgrade.png | Bin 0 -> 3801 bytes source/core/assets/images/hammer.png | Bin 0 -> 2789 bytes source/core/assets/images/health_upgrade.png | Bin 11226 -> 0 bytes source/core/assets/images/heart_upgrade.png | Bin 0 -> 3168 bytes source/core/assets/images/hourglass_upgrade.png | Bin 0 -> 3550 bytes source/core/assets/images/scrap_upgrade.png | Bin 0 -> 3563 bytes .../csse3200/game/input/UpgradeUIComponent.java | 15 +++++++++------ 7 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 source/core/assets/images/damage_upgrade.png create mode 100644 source/core/assets/images/hammer.png delete mode 100644 source/core/assets/images/health_upgrade.png create mode 100644 source/core/assets/images/heart_upgrade.png create mode 100644 source/core/assets/images/hourglass_upgrade.png create mode 100644 source/core/assets/images/scrap_upgrade.png diff --git a/source/core/assets/images/damage_upgrade.png b/source/core/assets/images/damage_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..043750ffbc8a73de623fb5d8023bc0914f6d9e58 GIT binary patch literal 3801 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 W{N;qN?tp#D#%tYr+9@|i+J6A25aXlSlvhq3 zv3F}d^16{l9d0CBONC2DO1q_yM{Go^?ti>adr$Z7x%)ro_y4^<-}mGEk{BMY+FD;} zArJ^{cQ=|BJe$MAR6`B^>)&ZIh9^y-+deS@v07g-ln@tl3=s%b10K^);z!?2;y`>1 ziwm(qjEpaY(Fg>2yG+R9gn$wx8w}zJD5&xJ1{9LVrJ#Im={UNO3I_AsB1NEgqz97| z8NwlQQQN;pl4T^A0UwmGkTQO#KunTRPz!uX@LF+puv9T}!90$oQ--eEy0EvBV`DHe<;lpGAwA5ke5_1&X0C5eIY$ zht)JySR*7+MIcK8iI@-+x*RCRvdTz2Y&CL=FHgXQq+-iY2tXQ30#ZrcU44k-{4@ma9JJU%N3#0mvL zDCCM8NmM8l62XFD?FgTqyHlwQ5fsP^g)hWjuFgnz7pfgVw6jCwF~EYlbUMjhAeOKM z9MGLcLBY|00BhXf?O_|jkh79i2#U0{qzj3~QIr7%#Zkl`ge_P+ z=KW<4EYeGZL73_P$csgo7z&g~St8IW2=>;W<{cJR9;+zWMLV$nY2w1&C&j%ChdYL1 zxzeiO%}TQa1#pKG!L5wZByNQ}Xslc$Mzu96o%Ce1DG*ZB+;wXxW(wLWyp7 z-kUiLDgWwdS)rXiNw&BzzFI9C-{X@Ebd7`=7#L`n{1`Pe_HlD;g-X_%O_met1JZJ> z;R^kiZk>|COd!6ucVAt<;LTWn^!(BC8rOZISfh|e2a}X6?>J?KkD5h-S z6>n#(J{>M6kGy^;mph%$HQh#RnNvubYeLkmcfL)}xu$P473|exPiPw$AAJ(lVRM`4t6W;#VpaS;J@o>Q;JB`F z|4d2Yo6%ha!q07O+SJV`rd0;3JyBycJo`}jow>P4DWA{pA=cm-$0H&(7;0WRYq5V< zVys?xWUui}m7Us-I|^>h7;=Q|my0hdr>W=a6x{7?xO3vWXhXnUJM?Rv-)sMMCGrD# zYD%2okx}fmwe_Zp_R#oa7!a z%K_BZ6!>G(%rslFv?kOlY`Gi8*f%En8Q`G*PthO!D;qmKQY_ARK1w|BxGrqi91@G*C8LO=zHuK?D{B zG&QU1#J$ZwqvEsb_!sF7_&tSJRH;!8!tpfp#RJdIhK+f)kS=|>b{%Ku$jAspe0i#~ zvorl3$WBhwFp2fmdNJ9Wy5%x-^k#EhQu@>AiS!iXDmVT2d243PJA6&=Pj$%U@)Tyq z;p$T}A0F5SJ;7>ULCRjOQFs+bkcQ z_TlV)p}PK-&V=XO597@YU({85Q~#XZ744JH`ssG^4edYC$A9h+4vNj0)wc4~n4W-v znX`#UgCqm?49j`)#i|`R<(v72XY#9Pjsx~@zgMcV|GhQXC`V>gSTosLepr}PBI*O4(`d)%jM!E0?<%!&s2PUS_9q{@W%2^hRFy~Mc-@#m;N`q$ z;onSpF8OC|-Q9k?y16qjMR#2A-A-%YgEsNn1MNrFlae-SX1HSF@}FX4O>sr(0)yUH zT#a9HGr)ZDSB|bu{fT>mFdkQ)W*0};kv5E%ky%n~^z+hM_lAu|2WLH0tgKF(yb1{@ zjwEqDKZ z4Ix+0a6Ra?g`Oj2-qWlZuaUizWt#!xMC%57>-=L3{dEnO8S=3~$u(n>l$6wFo1Bb< zAk8Y>;R8>}!tt<3qGZ~qPK=UmhP literal 0 HcmV?d00001 diff --git a/source/core/assets/images/health_upgrade.png b/source/core/assets/images/health_upgrade.png deleted file mode 100644 index 227239bcbbf080a1a510a473b4c56008366370b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11226 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 diff --git a/source/core/assets/images/heart_upgrade.png b/source/core/assets/images/heart_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..40dec728ec31183d7ca45de24fa46147aebfbc90 GIT binary patch literal 3168 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 Qhx8AB-yokt@5mkh0i%=a*8l(j literal 0 HcmV?d00001 diff --git a/source/core/assets/images/hourglass_upgrade.png b/source/core/assets/images/hourglass_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..45e83baa29da9917635c8d5f81283999c8536801 GIT binary patch literal 3550 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 literal 0 HcmV?d00001 diff --git a/source/core/assets/images/scrap_upgrade.png b/source/core/assets/images/scrap_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..01f9fb6a7b68e5250ab0230a1e1dc2a783156474 GIT binary patch literal 3563 zcmbVP3pkW%8y-qz%O=#I))*zxoX>+CX3!8#Os%NZ9KIQonfb=dU=)&KBdT48O=Oe5 zB&<{pl{A}WSJF|*vN;r59k7&2@qZ)v+y83+-Ru9Z>z()gzW09b=Y9_Fb6u0n_Vb!= zXkiG0!RE8pF#Vw!0S#+|InZylZP9vYnk!$kNeP2>(X~TI10K$Y!Ssg3oIq8e?^-$^ zl%lx;kO!dEQaOZ%!JJ&waxOm%P$77LNGx+k4qm*BM2H2>$S+C0SYJ5<2ohSB}AXyKB+}2oiU+Qc|<~POb6tXXeB3F4q*HNB^aUL z10Io(OdG8?ayml+a8;m!1A>wdiDG|{jKD))BkaBu%LHJQa^*({047%jI3w{`JOPEn zqOb%G7E8xdpsYFIuyic;J=7Nzh=tLgf|3YyJn>IZsAL3O758t!0zO>`Dx_S4e z0x)u!2#J^pBb@b? zQ>wT!KEPr+Bcb4+#bN=S%g55VR007-;F5VLEQLrzamjcR3cwPvTp^E2BapZs&ND%N zgti2<=ilE30mz3q{v(e}Akip73KvDe0~8dVN))1aQ~?P^p^&LWE)_>6QOFEb$63TJ( z^hF8)!lzdfF=DECASbn#!WqfeRs$eFPJb4EDjxsD^7Q$rPyizRA64?+x)KzsqPPmc zO$5d6Z>tdVSK^i2$iI>Pk5c(w)2F2WscQcp>C<81hjL{i0P3(9q}CaXwimrm3g*A_ zHMRFq-}(TDnxS?%(}kgznLZB4AZi8FrN=bmNEl2%iN$o|1SVd}3Qj$;!R+UqVLQK5 zW;bOMj$FSaqOWbwSY&wIpxnYRft8j7H!+JHIzBhKdrN0(?ICyz+$3#X!$J8ieg3>< zLt8aRkJZNqX3+8H?qpv-r`+BbDeIID_SR9Pz=q zjy=x0F|%IT4(-dyRy&V?yr&HE!=GI@bggJ8)Op)?Sr2O^?}!y&yEDtND6Yqc-NquN zMKA20nAF#F6T6ci7&5$Eo*bf;EE(4w-Du9@$0f-h)y=LZ`KV9auWRwLx(;6waJcyD z&Dl%FYuE#TecEf9e5ej~NRcH<&>esNPSr4!v9Ll%|F;wPaNg^I;HEFi{9g?tQDNzSGx*u0s8)D zn1}<(noO%kD?S0KLASYr5k5cIC2Tk=P$kD3%94S2UCQ z!xuG(X1m1KZ+fX)wYPhdCXOBNnrYR>sr7e+<6^z`G|%Q#+N1Y27Bp^rT~=*u>bA7y zWq+%(@O<+K+_*c@((MuK>cdk`8yy$mVnzCH8gtI*w#s0WN8VNw?_7p8Biu2!-Fr_H z3%wTDBb|2I#Dfkos8x2cj{f8)I!|82ySEuHGQ~#UjQTFmN!hkAVL1Pesox~4TJDL< zJ6(Bfnemtf!=Of2(5~}JBVx)o*|)vTaXyt&Ztk|g-Z^u&=*1RTO10CD&2gVc_w|c1 zJ0}g_9^^2$uw9)Fz^F!V8Frwq1Po|`G%IBeN|9-JFxDv7F5&3L zaHE8Sc6NW*4e1|+sa=;=t1c~irMa3FQaRz|UfbO@y6xq?F7)6mPdBsmazC~yGnY^^ z|JtRH&N98~d+xA^3%${DvmdjalrPL2;;GE}van+Ww%^chqWErsk?B>Ko`|C|Q)S{mw*3BWTk3;hV8CE(-$~j{7Ca>xnk=z7!Di}Fxb{>}5-_+r#bl5T0Dn|+i7IdyK zaF4mMwbJP8EfwJn4PJG!Ld)9G9*2<0Cq=YbF`Y%^s(ojF3$O7xl6!KVN5&gMi^0Sx zuh)0ud9Al7>|-4PwrLAvIzdwMv+$Sadc7jNu)%&>X+mQ_O@v}#bH9$WjYo5~tZqX>7jw&rvWJ1O5>K)LoZJ42b) zXE-9Cr-A66iMe90^}Beue?8VO$qng!`&9ROP|78b3%}VmH`{(y&pkio12eiwaW!?Txp+l}{F^7m6;m154k zeqd;D@u!E(v8esG&g*&=MxGX(^Ol};w;m0RFrl;N+*|+Cf;p=tJ19VIyoU(sjOZ|8Wt78P&dCjf&Y>-B`5j1uMOn5p@5%)=c? znQ4n)RnL}kC5m{z(CQYMNm-dqPL9AbM|JOBcF5-5XUA=Q(#Sc@Wbxsy9iAtW9F`l? ze%+s5`^;f0HGjn1r0B*d+m+zGcVW|3&{zjuQn@DAzsR(4-Z_b9p~v!_GML%v|k#8nqCLeE03mLF&!*mww=vBDC{vktcUC_45|M$6j(+_1< z*cLaV`*T(fmWXO1hn+k^?g!7W22Ss>f(M0P4J!8eKInvKTZaA{)|rd|@LHZU@{Fjb zrL;_l?KGs>G(}X%a)4I^1=|Q&XQ+ zu=$TZaR`CmaLVh&r(vRt`+IvU;Xiqn?|Y;B*b^ttIw+GYEUj?2=}YAuv4{U4 uOPtg-@IPr&@T(a5Zw5000$D;|Uzk0#Hh_lqxgC(Momd`z%pcshCj1+#$E3{w literal 0 HcmV?d00001 diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 40982834a..4211b7e81 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -173,7 +173,7 @@ public void clicked(InputEvent event, float x, float y) { Image fireRateImage = new Image(fireRateDrawable); - Drawable healthStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/health_upgrade.png"))); + Drawable healthStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/heart_upgrade.png"))); ImageButton upgradeHealth = new ImageButton(healthStyle); upgradeHealth.setScale(0.8f); upgradeHealth.addListener(new ClickListener() { @@ -203,7 +203,7 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) } }); - Drawable attackStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/health_upgrade.png"))); + Drawable attackStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/damage_upgrade.png"))); ImageButton upgradeAttack = new ImageButton(attackStyle); upgradeAttack.addListener(new ClickListener() { @Override @@ -232,7 +232,8 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) - TextButton upgradeFireRate = new TextButton("+FR", style); + Drawable asStyle = new TextureRegionDrawable(new TextureRegion(new Texture("images/hourglass_upgrade.png"))); + ImageButton upgradeFireRate = new ImageButton(asStyle); upgradeFireRate.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -263,7 +264,8 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) } }); - TextButton repairButton = new TextButton("R", style); + Drawable repair = new TextureRegionDrawable(new TextureRegion(new Texture("images/hammer.png"))); + ImageButton repairButton = new ImageButton(repair); repairButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -304,8 +306,9 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) innerUpgradeTable.add(incomeLabel).expandX().left(); innerUpgradeTable.row(); - upgradeIncome = new TextButton("+I", style); - upgradeIncome.addListener(new ClickListener() { + Drawable income = new TextureRegionDrawable(new TextureRegion(new Texture("images/scrap_upgrade.png"))); + ImageButton attackStyleButton = new ImageButton(asStyle); + attackStyleButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { value = ServiceLocator.getCurrencyService().getScrap().getAmount(); From e4fab8b6eb58c39326da951b513246f2d13535e9 Mon Sep 17 00:00:00 2001 From: Ryan McNeilly Date: Tue, 3 Oct 2023 01:24:29 +1000 Subject: [PATCH 47/49] Updated old hourglass icon --- source/core/assets/images/hourglass.png | Bin 0 -> 10309 bytes .../csse3200/game/input/UpgradeUIComponent.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 source/core/assets/images/hourglass.png diff --git a/source/core/assets/images/hourglass.png b/source/core/assets/images/hourglass.png new file mode 100644 index 0000000000000000000000000000000000000000..2c264091275d02e2fd2d3393796528d186a9d956 GIT binary patch literal 10309 zcmeI2e@qi+7{{wXXMvjObx!J>nW<+>bXF-gk;FlJtn|2JP{-Y+IfE!Xj1vQa9O~U@ySqmW_Vu4d(8F6`TFl3QiB&;Osl^s(lZ-q5)DeVJaEv)bM+tkACL zCA3Fn@2uEYHL`n;I+R1HBzo&8e{ya)!M);Y7w(gJ8T_~CVE@nM!>x9coa&J1Js*^_ z%%*Nj^0{SWa$FjVtxdPCX>pj?Eaf)wt-8(iOkEF=c~llRjGt`7sQl{l&W2*vsSFro zzWMxcyzl-MlwWh5r+^g78e_re{HT&-l?2~fFDpn@2Q10iuWPkMtSf^*IoF(^3^=T1 zEsjD~-SjwRLKML(bFE?vMuqTTe`HU*s)1B>H(}neO>FD;XWLB*D&&?e8^&P-H0%fT zd2doSSr9)V#43h-TXYb^IGI>VTWp@C6XK1*j$K2;%rGBS-$O)%ghB0O5l8uL^KVDHoH9l671R#}iAiV;+V> z-tty9sd(3k5(PXNN1Ki2*mb{AZ6F8YP&NV)z(8dzr>a4z&Cs`<%Mnyw9~y|0$H)&Y zHp3qpl!!oQ8)2Zw!u>+%vU#3I*$xEbK?89L^d`$)woX6FL3a2>7>JWn@NAmGb)yy~ zI&e@K48&hL?{yTi|06KqEHHIb1nYn(7*yReSqDUs(UGhJqG09?5v&8EU{LnYWE~+2 z=Aa^22X%o#Gcl8OP!}>hl6C&ld9Obin0wAvBimXAh@(L5UIj%402x+(gm4sRhdOGY zm;r*r%A6r1il>g_P`m>2VdWH{3jw$?xEN{~&`4O7Q`v|jwt1@tY9@74cr|6-fI>W- z3AGuZ99HBE(9*PPJUBbcX}bpA&| zZr)vUlCJxdNltgzAfYg%FLZbO)bz|1FdjDl37y4^38#qp%*c5n{-1e={cX~lha_@U zVb&nwm#m(ab-T^ajVW*`8Ei1`Xf!S!B(Sh84wEaDM0256`jhye1Vf8jEA>nKv?^@x z!;~v7i`=KX2mQMB0km3WHO}LQ3-G?1-a+$Epvd$?x@o-9t-l-$qliBVQkpAHxbuns zH9fzp?1>xemR>xu?om{h Date: Tue, 3 Oct 2023 01:40:34 +1000 Subject: [PATCH 48/49] Removed upgrades for TNT tower --- .../src/main/com/csse3200/game/input/UpgradeUIComponent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 20a2bbca0..cffd36cc6 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -23,6 +23,7 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.TowerCombatTask; import com.csse3200.game.components.tower.IncomeUpgradeComponent; +import com.csse3200.game.components.tower.TNTDamageComponent; import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.components.tower.UpgradableStatsComponent; import com.csse3200.game.entities.Entity; @@ -78,8 +79,8 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); Entity clickedEntity = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); - if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null) { - logger.info("clicked a turret that is upgradable!"); + if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null && clickedEntity.getComponent(TNTDamageComponent.class) == null) { +// logger.info("clicked a turret that is upgradable!"); clearUpgradeTables(); // Check if there is an existing upgrade table for this turret entity Table existingUpgradeTable = upgradeTables.get(clickedEntity); From cdb49b9f337ea6f9e467bf30cc0e709092505036 Mon Sep 17 00:00:00 2001 From: Kevin <104761532+Hasakev@users.noreply.github.com> Date: Tue, 3 Oct 2023 02:00:35 +1000 Subject: [PATCH 49/49] Fixed all issues, regarding the renaming of wallTower to wall_tower (to fix POSIX error) --- .../core/src/main/com/csse3200/game/areas/ForestGameArea.java | 2 +- .../com/csse3200/game/entities/factories/NPCFactoryTest.java | 2 +- .../com/csse3200/game/entities/factories/TowerFactoryTest.java | 2 +- 3 files changed, 3 insertions(+), 3 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 bf09242fc..b74fa46ac 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -87,7 +87,7 @@ public class ForestGameArea extends GameArea { "images/mobs/Hurt.png", "images/mobs/Idle.png", "images/mobs/rangeBossRight.png", - "images/towers/wallTower.png", + "images/towers/wall_tower.png", "images/background/building2.png", "images/iso_grass_3.png", "images/Dusty_MoonBG.png", diff --git a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java index 9ef153c8c..e07093e74 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/NPCFactoryTest.java @@ -56,7 +56,7 @@ public class NPCFactoryTest { private final String[] texture = { "images/towers/turret_deployed.png", "images/towers/turret01.png", - "images/towers/WallTower.png" + "images/towers/wall_tower.png" }; private final String[] atlas = { "images/towers/turret01.atlas", 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 e612608d8..7d2f75c65 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 @@ -38,7 +38,7 @@ public class TowerFactoryTest { private String[] texture = { "images/towers/turret_deployed.png", "images/towers/turret01.png", - "images/towers/WallTower.png", + "images/towers/wall_tower.png", "images/towers/fire_tower_atlas.png", "images/towers/stun_tower.png", "images/towers/DroidTower.png",