Skip to content

Commit

Permalink
Added fire rate upgrade functionality to TowerUpgraderComponent, also…
Browse files Browse the repository at this point in the history
… added functionality to TowerCombatTask for supporting fire rate upgrades.
  • Loading branch information
AlasdairS4698737 committed Sep 6, 2023
1 parent c75f782 commit 82715be
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.csse3200.game.physics.raycast.RaycastHit;
import com.csse3200.game.services.GameTime;
import com.csse3200.game.services.ServiceLocator;
import static java.lang.Math.round;

/**
* The TowerCombatTask runs the AI for the WeaponTower class. The tower will scan for targets in a straight line
Expand All @@ -28,6 +29,7 @@ public class TowerCombatTask extends DefaultTask implements PriorityTask {

// class attributes
private final int priority; // The active priority this task will have
private float fireRateInterval; // time interval to fire projectiles at enemies in seconds
private final float maxRange;
private Vector2 towerPosition = new Vector2(10, 10); // initial placeholder value - will be overwritten
private final Vector2 maxRangePosition = new Vector2();
Expand All @@ -48,6 +50,20 @@ private enum STATE {
public TowerCombatTask(int priority, float maxRange) {
this.priority = priority;
this.maxRange = maxRange;
this.fireRateInterval = 1;
physics = ServiceLocator.getPhysicsService().getPhysics();
timeSource = ServiceLocator.getTimeSource();
}

/**
* @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
*/
public TowerCombatTask(int priority, float maxRange, float fireRate) {
this.priority = priority;
this.maxRange = maxRange;
this.fireRateInterval = 1/fireRate;
physics = ServiceLocator.getPhysicsService().getPhysics();
timeSource = ServiceLocator.getTimeSource();
}
Expand All @@ -63,6 +79,8 @@ public void start() {
this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y);
// Default to idle mode
owner.getEntity().getEvents().trigger(IDLE);
// Set up listener to change firerate
owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval);

endTime = timeSource.getTime() + (INTERVAL * 500);
}
Expand All @@ -75,7 +93,11 @@ public void start() {
public void update() {
if (timeSource.getTime() >= endTime) {
updateTowerState();
endTime = timeSource.getTime() + (INTERVAL * 1000);
if (towerState == STATE.FIRING) {
endTime = timeSource.getTime() + round(fireRateInterval * 1000);
} else {
endTime = timeSource.getTime() + (INTERVAL * 1000);
}
}
}

Expand Down Expand Up @@ -172,4 +194,24 @@ private boolean isTargetVisible() {
// If there is an obstacle in the path to the max range point, mobs visible.
return physics.raycast(towerPosition, maxRangePosition, TARGET, hit);
}

/**
* Increases the fireRateInterval, changing how frequently the turret fires. Will decrease if the argument is negative.
*
* @param perMinute The number of times per minute the turret's fire rate should increase
*/
private void changeFireRateInterval(int perMinute) {
float oldFireSpeed = 1/fireRateInterval;
float newFireSpeed = oldFireSpeed + perMinute/60f;
fireRateInterval = 1/newFireSpeed;
}

/**
* Function for getting the turret's fire rate.
*
* @return The fireRateInterval variable
*/
public float getFireRateInterval() {
return fireRateInterval;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.csse3200.game.components.CombatStatsComponent;
import com.csse3200.game.components.Component;
import static java.lang.Math.round;

/**
* Listens for an event from the popup menu to upgrade
Expand All @@ -20,15 +21,16 @@ public void create() {

/**
* Determines which type of upgrade to perform based on arguments provided by the event trigger.
* Note: The fire rate upgrade is in shots per minute.
*
* @param upgradeType An enum indicating the type of upgrade to do
* @param value How much the upgrade should change the tower's stats, where applicable
* @param value How much the upgrade should change the tower's stats
*/
void upgradeTower(UPGRADE upgradeType, int value) {
switch (upgradeType) {
case ATTACK -> {upgradeTowerAttack(value);}
case MAXHP -> {upgradeTowerMaxHealth(value);}
case FIRERATE -> {/*Not implemented at the present moment*/}
case FIRERATE -> {getEntity().getEvents().trigger("addFireRate", value);}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.csse3200.game.components.tower;

import com.csse3200.game.ai.tasks.AITaskComponent;
import com.csse3200.game.components.CombatStatsComponent;
import com.csse3200.game.components.tasks.TowerCombatTask;
import com.csse3200.game.entities.Entity;
import com.csse3200.game.extensions.GameExtension;
import com.csse3200.game.physics.PhysicsService;
import com.csse3200.game.services.GameTime;
import com.csse3200.game.services.ServiceLocator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -12,14 +17,18 @@
@ExtendWith(GameExtension.class)
class TowerUpgraderComponentTest {
Entity entity;
TowerUpgraderComponent towerUpgraderComponent;
CombatStatsComponent combatStatsComponent;

@BeforeEach
void beforeEach() {entity = new Entity();}
void beforeEach() {
entity = new Entity();
towerUpgraderComponent = spy(TowerUpgraderComponent.class);
combatStatsComponent = new CombatStatsComponent(100,10);
}

@Test
void increaseAttackStat() {
TowerUpgraderComponent towerUpgraderComponent = spy(TowerUpgraderComponent.class);
CombatStatsComponent combatStatsComponent = new CombatStatsComponent(100,10);
entity.addComponent(towerUpgraderComponent);
entity.addComponent(combatStatsComponent);
entity.create();
Expand All @@ -30,13 +39,27 @@ void increaseAttackStat() {

@Test
void increaseMaxHealthStat() {
TowerUpgraderComponent towerUpgraderComponent = spy(TowerUpgraderComponent.class);
CombatStatsComponent combatStatsComponent = new CombatStatsComponent(100,10);
entity.addComponent(towerUpgraderComponent);
entity.addComponent(combatStatsComponent);
entity.create();
entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.MAXHP, 50);
verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.MAXHP, 50);
assertEquals(150, combatStatsComponent.getMaxHealth());
}

@Test
void increaseFireRate() {
entity.addComponent(towerUpgraderComponent);
AITaskComponent aiTaskComponent = new AITaskComponent();
ServiceLocator.registerPhysicsService(mock(PhysicsService.class));
ServiceLocator.registerTimeSource(mock(GameTime.class));
TowerCombatTask towerCombatTask = new TowerCombatTask(10, 10, 1);
aiTaskComponent.addTask(towerCombatTask);
entity.addComponent(aiTaskComponent);
towerCombatTask.start();
entity.create();
entity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 60);
verify(towerUpgraderComponent).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, 60);
assertEquals(0.5, towerCombatTask.getFireRateInterval());
}
}

0 comments on commit 82715be

Please sign in to comment.