From 4bbef11b0e2692b6742274125f7052f95f3502ae Mon Sep 17 00:00:00 2001 From: Shivam Date: Fri, 8 Sep 2023 01:20:12 +1000 Subject: [PATCH] Added files StunTowerCombatTask, StunTowerAnimationController, stun_tower.png, stun_tower.atlas and finished the base functionality for createStunTower method in TowerFactory. --- .../assets/images/towers/stun_tower.atlas | 118 ++++++++++++ .../core/assets/images/towers/stun_tower.png | Bin 0 -> 6954 bytes .../csse3200/game/areas/ForestGameArea.java | 178 +++++++++--------- .../components/tasks/StunTowerCombatTask.java | 109 +++++++++++ .../tower/StunTowerAnimationController.java | 35 ++++ .../game/entities/factories/TowerFactory.java | 32 +++- 6 files changed, 381 insertions(+), 91 deletions(-) create mode 100644 source/core/assets/images/towers/stun_tower.atlas create mode 100644 source/core/assets/images/towers/stun_tower.png create mode 100644 source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java create mode 100644 source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java diff --git a/source/core/assets/images/towers/stun_tower.atlas b/source/core/assets/images/towers/stun_tower.atlas new file mode 100644 index 000000000..feeea736b --- /dev/null +++ b/source/core/assets/images/towers/stun_tower.atlas @@ -0,0 +1,118 @@ + +stun_tower.png +size: 1024, 64 +format: RGBA8888 +filter: Nearest, Nearest +repeat: none +attack + rotate: false + xy: 2, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 4 +attack + rotate: false + xy: 136, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 9 +attack + rotate: false + xy: 203, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 1 +attack + rotate: false + xy: 270, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 6 +attack + rotate: false + xy: 404, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 3 +attack + rotate: false + xy: 538, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 8 +attack + rotate: false + xy: 672, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 0 +attack + rotate: false + xy: 739, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 5 +attack + rotate: false + xy: 873, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 2 +attack + rotate: false + xy: 940, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 7 +idle + rotate: false + xy: 69, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 1 +idle + rotate: false + xy: 337, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 3 +idle + rotate: false + xy: 471, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 0 +idle + rotate: false + xy: 605, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 5 +idle + rotate: false + xy: 605, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 4 +idle + rotate: false + xy: 806, 2 + size: 65, 45 + orig: 65, 45 + offset: 0, 0 + index: 2 diff --git a/source/core/assets/images/towers/stun_tower.png b/source/core/assets/images/towers/stun_tower.png new file mode 100644 index 0000000000000000000000000000000000000000..0d5c0d4f6c69a165cf03552b2a3c8e24e284fac5 GIT binary patch literal 6954 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 fixedPositions = new ArrayList<>(); //Generating ArrayList - - fixedPositions.add(new GridPoint2(5, 8)); - fixedPositions.add(new GridPoint2(12, 4)); - fixedPositions.add(new GridPoint2(20, 10)); - fixedPositions.add(new GridPoint2(33, 17)); - - for (GridPoint2 fixedPos : fixedPositions) { - Entity tree = ObstacleFactory.createMountain(); - spawnEntityAt(tree, fixedPos, true, false); - } - } +// private void spawnBuilding1() { +// GridPoint2 minPos = new GridPoint2(0, 0); +// GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); +// +// for (int i = 0; i < NUM_BUILDINGS; i++) { +// GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); +// Entity building1 = ObstacleFactory.createBuilding1(); +// spawnEntityAt(building1, randomPos, true, false); +// } +// } +// private void spawnBuilding2() { +// GridPoint2 minPos = new GridPoint2(0, 0); +// GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); +// +// for (int i = 0; i < NUM_BUILDINGS; i++) { +// GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); +// Entity building2 = ObstacleFactory.createBuilding2(); +// spawnEntityAt(building2, randomPos, true, false); +// } +// } + +// private void spawnMountains() { +// ArrayList fixedPositions = new ArrayList<>(); //Generating ArrayList +// +// fixedPositions.add(new GridPoint2(5, 8)); +// fixedPositions.add(new GridPoint2(12, 4)); +// fixedPositions.add(new GridPoint2(20, 10)); +// fixedPositions.add(new GridPoint2(33, 17)); +// +// for (GridPoint2 fixedPos : fixedPositions) { +// Entity tree = ObstacleFactory.createMountain(); +// spawnEntityAt(tree, fixedPos, true, false); +// } +// } private Entity spawnPlayer() { Entity newPlayer = PlayerFactory.createPlayer(); @@ -324,34 +326,34 @@ private void spawnXenoGrunts() { } } - private Entity spawnGhostKing() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(0, 0); - GridPoint2 randomPos - = RandomUtils.random(minPos, maxPos); - // = new GridPoint2(26, 26); - Entity ghostKing = NPCFactory.createGhostKing(player); - spawnEntityAt(ghostKing, randomPos, true, true); - return ghostKing; - - } - - private Entity spawnBossKing2() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); - - for (int i = 0; i < NUM_BOSS; i++) { - int fixedX = terrain.getMapBounds(0).x - 1; // Rightmost x-coordinate - int randomY = MathUtils.random(0, maxPos.y); - GridPoint2 randomPos = new GridPoint2(fixedX, randomY); - bossKing2 = BossKingFactory.createBossKing2(player); - spawnEntityAt(bossKing2, - randomPos, - true, - false); - } - return bossKing2; - } +// private Entity spawnGhostKing() { +// GridPoint2 minPos = new GridPoint2(0, 0); +// GridPoint2 maxPos = terrain.getMapBounds(0).sub(0, 0); +// GridPoint2 randomPos +// = RandomUtils.random(minPos, maxPos); +// // = new GridPoint2(26, 26); +// Entity ghostKing = NPCFactory.createGhostKing(player); +// spawnEntityAt(ghostKing, randomPos, true, true); +// return ghostKing; +// +// } + +// private Entity spawnBossKing2() { +// GridPoint2 minPos = new GridPoint2(0, 0); +// GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); +// +// for (int i = 0; i < NUM_BOSS; i++) { +// int fixedX = terrain.getMapBounds(0).x - 1; // Rightmost x-coordinate +// int randomY = MathUtils.random(0, maxPos.y); +// GridPoint2 randomPos = new GridPoint2(fixedX, randomY); +// bossKing2 = BossKingFactory.createBossKing2(player); +// spawnEntityAt(bossKing2, +// randomPos, +// true, +// false); +// } +// return bossKing2; +// } /** * Creates multiple projectiles that travel simultaneous. They all have same @@ -364,13 +366,13 @@ private Entity spawnBossKing2() { * @param speed The speed of the projectiles. * @param quantity The amount of projectiles to spawn. */ - private void spawnMultiProjectile(Vector2 position, Entity target, int direction, int space, Vector2 speed, int quantity) { - int half = quantity / 2; - for (int i = 0; i < quantity; i++) { - spawnProjectile(position, target, space * half, direction, speed); - --half; - } - } +// private void spawnMultiProjectile(Vector2 position, Entity target, int direction, int space, Vector2 speed, int quantity) { +// int half = quantity / 2; +// for (int i = 0; i < quantity; i++) { +// spawnProjectile(position, target, space * half, direction, speed); +// --half; +// } +// } /** * Returns projectile that can do an area of effect damage @@ -393,11 +395,13 @@ private void spawnWeaponTower() { for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity weaponTower = TowerFactory.createWeaponTower(); + //Entity weaponTower = TowerFactory.createWeaponTower(); Entity wallTower = TowerFactory.createWallTower(); Entity fireTower = TowerFactory.createFireTower(); - spawnEntityAt(weaponTower, randomPos, true, true); + Entity stunTower = TowerFactory.createStunTower(); + //spawnEntityAt(weaponTower, randomPos, true, true); spawnEntityAt(fireTower, randomPos, true, true); + spawnEntityAt(stunTower, randomPos, true, true); spawnEntityAt(wallTower, new GridPoint2(randomPos.x + 3, randomPos.y), true, true); } } @@ -440,16 +444,16 @@ public void dispose() { this.unloadAssets(); } - private void spawnScrap() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); - - for (int i = 0; i < 50; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity scrap = DropFactory.createScrapDrop(); - spawnEntityAt(scrap, randomPos, true, false); - } - } +// private void spawnScrap() { +// GridPoint2 minPos = new GridPoint2(0, 0); +// GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); +// +// for (int i = 0; i < 50; i++) { +// GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); +// Entity scrap = DropFactory.createScrapDrop(); +// spawnEntityAt(scrap, randomPos, true, false); +// } +// } private void spawnIncome() { GridPoint2 minPos = new GridPoint2(0, 0); 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 new file mode 100644 index 000000000..1c2cc5863 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java @@ -0,0 +1,109 @@ +package com.csse3200.game.components.tasks; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.ProjectileFactory; +import com.csse3200.game.physics.PhysicsEngine; +import com.csse3200.game.physics.PhysicsLayer; +import com.csse3200.game.physics.raycast.RaycastHit; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; + + +public class StunTowerCombatTask extends DefaultTask implements PriorityTask { + //constants + private static final int INTERVAL = 1; + private static final short TARGET = PhysicsLayer.NPC; + //Following constants are names of events that will be triggered in the state machine + public static final String IDLE = "startIdle"; + public static final String ATTACK = "startAttack"; + + //Following are the class constants + private final int priority; + private final float maxRange; + private Vector2 towerPosition = new Vector2(10, 10); + private final Vector2 maxRangePosition = new Vector2(); + private PhysicsEngine physics; + private GameTime timeSource; + private long endTime; + private final RaycastHit hit = new RaycastHit(); + + //enums for the state triggers + private enum STATE { + IDLE, ATTACK + } + private STATE towerState = STATE.IDLE; + + public StunTowerCombatTask(int priority, float maxRange) { + this.priority = priority; + this.maxRange = maxRange; + physics = ServiceLocator.getPhysicsService().getPhysics(); + timeSource = ServiceLocator.getTimeSource(); + } + + @Override + public void start() { + super.start(); + //get the tower coordinates + this.towerPosition = owner.getEntity().getCenterPosition(); + this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); + //set the default state to IDLE state + owner.getEntity().getEvents().trigger(IDLE); + + endTime = timeSource.getTime() + (INTERVAL * 5000); + } + + public void update() { + if (timeSource.getTime() >= endTime) { + updateTowerState(); + endTime = timeSource.getTime() + (INTERVAL * 1000); + } + } + + public void updateTowerState() { + switch (towerState) { + case IDLE -> { + if(isTargetVisible()) { + owner.getEntity().getEvents().trigger(ATTACK); + towerState = STATE.ATTACK; + } + } + case ATTACK -> { + if (!isTargetVisible()) { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } else { + owner.getEntity().getEvents().trigger(ATTACK); + Entity newProjectile = ProjectileFactory.createFireBall(owner.getEntity(), + new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.75), + (float) (owner.getEntity().getPosition().y + 0.75)); + ServiceLocator.getEntityService().register(newProjectile); + } + } + } + } + + public void stop() { + super.stop(); + owner.getEntity().getEvents().trigger(IDLE); + } + + public int getPriority() { + return !isTargetVisible() ? 0 : priority; + } + + public int getActivePriority() { + return !isTargetVisible() ? 0 : priority; + } + + public int getInactivePriority() { + return isTargetVisible() ? priority : 0; + } + + public boolean isTargetVisible() { + return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); + } +} diff --git a/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java new file mode 100644 index 000000000..8ff908b35 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java @@ -0,0 +1,35 @@ +package com.csse3200.game.components.tower; + +import com.badlogic.gdx.audio.Sound; +import com.csse3200.game.components.Component; +import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; + +public class StunTowerAnimationController extends Component { + //Event name constants + private static final String IDLE = "startIdle"; + private static final String ATTACK = "startAttack"; + //animation name constants + private static final String IDLE_ANIM = "idle"; + private static final String ATTACK_ANIM = "attack"; + + //further sounds can be added for the tower attacks/movement + + AnimationRenderComponent animator; + + @Override + public void create() { + super.create(); + animator = this.entity.getComponent(AnimationRenderComponent.class); + entity.getEvents().addListener(IDLE, this::animateIdle); + entity.getEvents().addListener(ATTACK, this::animateAttack); + } + + void animateIdle() { + animator.startAnimation(IDLE_ANIM); + } + + void animateAttack() { + animator.startAnimation(ATTACK_ANIM); + } +} 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 c290e4212..90edc11af 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -1,7 +1,9 @@ package com.csse3200.game.entities.factories; import com.csse3200.game.components.tasks.FireTowerCombatTask; +import com.csse3200.game.components.tasks.StunTowerCombatTask; import com.csse3200.game.components.tower.FireTowerAnimationController; +import com.csse3200.game.components.tower.StunTowerAnimationController; import com.csse3200.game.entities.configs.*; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.TextureAtlas; @@ -22,6 +24,8 @@ import com.csse3200.game.rendering.TextureRenderComponent; import com.csse3200.game.services.ServiceLocator; +import java.util.ServiceConfigurationError; + /** * Factory to create a tower entity. * @@ -34,7 +38,8 @@ public class TowerFactory { private static final int WEAPON_TOWER_MAX_RANGE = 40; private static final String WALL_IMAGE = "images/towers/wallTower.png"; private static final String TURRET_ATLAS = "images/towers/turret01.atlas"; - private static final String FIRE_TURRET_ATLAS = "images/towers/fire_tower_atlas.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"; private static final String IDLE_ANIM = "idle"; private static final float IDLE_SPEED = 0.3f; private static final String DEPLOY_ANIM = "deploy"; @@ -49,7 +54,11 @@ public class TowerFactory { private static final float FIRE_TOWER_PREP_ATTACK_SPEED = 0.2f; private static final String FIRE_TOWER_ATTACK_ANIM = "attack"; private static final float FIRE_TOWER_ATTACK_SPEED = 0.25f; - private static final int INCOME_INTERVAL = 300; + private static final String STUN_TOWER_IDLE_ANIM = "idle"; + private static final float STUN_TOWER_IDLE_SPEED = 0.33f; + private static final String STUN_TOWER_ATTACK_ANIM = "attack"; + private static final float STUN_TOWER_ATTACK_SPEED = 0.12f; + private static final int INCOME_INTERVAL = 300; private static final int INCOME_TASK_PRIORITY = 1; private static final baseTowerConfigs configs = @@ -135,7 +144,7 @@ public static Entity createFireTower() { AnimationRenderComponent animator = new AnimationRenderComponent( ServiceLocator.getResourceService() - .getAsset(FIRE_TURRET_ATLAS, TextureAtlas.class)); + .getAsset(FIRE_TOWER_ATLAS, TextureAtlas.class)); animator.addAnimation(FIRE_TOWER_IDLE_ANIM, FIRE_TOWER_IDLE_SPEED, Animation.PlayMode.LOOP); animator.addAnimation(FIRE_TOWER_PREP_ATTACK_ANIM, FIRE_TOWER_PREP_ATTACK_SPEED, Animation.PlayMode.NORMAL); animator.addAnimation(FIRE_TOWER_ATTACK_ANIM, FIRE_TOWER_ATTACK_SPEED, Animation.PlayMode.LOOP); @@ -147,6 +156,7 @@ public static Entity createFireTower() { .addComponent(animator) .addComponent(new FireTowerAnimationController()); + fireTower.setScale(3, 3); return fireTower; } @@ -154,10 +164,24 @@ public static Entity createStunTower() { Entity stunTower = createBaseTower(); StunTowerConfig config = configs.stunTower; + AITaskComponent aiTaskComponent = new AITaskComponent() + .addTask(new StunTowerCombatTask(COMBAT_TASK_PRIORITY, WEAPON_TOWER_MAX_RANGE)); + + AnimationRenderComponent animator = + new AnimationRenderComponent( + ServiceLocator.getResourceService() + .getAsset(STUN_TOWER_ATLAS, TextureAtlas.class)); + animator.addAnimation(STUN_TOWER_IDLE_ANIM, STUN_TOWER_IDLE_SPEED, Animation.PlayMode.LOOP); + animator.addAnimation(STUN_TOWER_ATTACK_ANIM, STUN_TOWER_ATTACK_SPEED, Animation.PlayMode.LOOP); + stunTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) - .addComponent((new CostComponent(config.cost))); + .addComponent((new CostComponent(config.cost))) + .addComponent(aiTaskComponent) + .addComponent(animator) + .addComponent(new StunTowerAnimationController()); + stunTower.setScale(1.5f, 1.5f); return stunTower; }