-
Notifications
You must be signed in to change notification settings - Fork 4
Demon Boss Task
The DemonBossTask
class is responsible for executing the AI logic for the Demon Boss entity within the game. This class handles the actions that the Demon Boss executes. The class is designed to be added to an AiTaskComponent, which should be attached to a Demon Boss entity.
To utilize DemonBossTask
, execute the following steps:
- Create an instance of
DemonBossTask
. - Add it to an
AiTaskComponent
instance that is connected to a Demon Boss entity.
// Create a Demon Boss Entity
demon = MobBossFactory.createDemonBoss();
// Create an AiTaskComponent instance
AITaskComponent aiTaskComponent = new AITaskComponent();
// Add the DemonBossTask to the AiTaskComponent
aiTaskComponent.addTask(new DemonBossTask());
// Add AiTaskComponent to Droid entity
demon.addComponent(aiTaskComponent);
The update()
and changeState(DemonState state)
methods manage the Demon Boss's states and transitions. These methods toggle between multiple states described by the DemonState
enum: TRANSFORM
, IDLE
, SMASH
, BREATH
, CLEAVE
, TAKE_HIT
, CAST
, WALK
, and DEATH
.
- Description: Starting state, where the Demon Boss comes into existence on the screen.
- Behavior: Triggers the starting transform animation.
-
Transition: After the starting animation is finished, it will automatically change to the
IDLE
state, but if health drops to 0 before the transformation is complete then it'll transition to theDEATH
state.
-
Description: Default state, initiates the
jump(Vector2 finalPos)
method. - Behavior: Moves the Demon Boss to a new position 3 units away from the current position.
-
Transition: Changes state to
SMASH
.
- Description: Demon Boss landing onto an area and dealing damage to the surrounding area.
-
Behavior: All human entities within the
SMASH_RADIUS
will receiveSMASH_DAMAGE
from usingjumpComplete()
method. -
Transition: Calls either the
fireBreath()
or thecleave()
method for transition. Changes toBREATH
state if there aren't any human entities nearby. Otherwise, it will transition to theCLEAVE
state.
- Description: Demon Boss breaths fireballs towards the human entities.
- Behavior: Launches an given amount of projectiles with a given effect at the human entities.
-
Transition: Transitions to
IDLE
once sequence is complete.
- Description: Demon Boss attacks the nearest human entity (target).
-
Behavior: Deals
CLEAVE_DAMAGE
to the target. -
Transition: Transitions to
IDLE
once sequence is complete.
- Description: This state is activated when health drops to half or lower.
-
Behavior: When Demon Boss's health drops to half, a different animation will be played and
halfHealth()
is called to activateCAST
state afterwards. -
Transition: Transitions to
CAST
once animation is complete.
-
Description: When Demon Boss's health drops to half it starts healing by
HEALTH_TO_ADD
everyHEAL_TIMES
seconds. -
Behavior: Demon Boss's health will increase by
HEALTH_TO_ADD
everyHEAL_TIMES
seconds. -
Transition: Transitions to
IDLE
once sequence is complete.
- Description: The walking state with animation.
-
Behavior: Triggers
WALK
.
- Description: This state is activated when the Demon Boss's health drops to zero.
- Behavior: Flags Demon Boss for deletion once the death animation is finished and spawns Slimey Boy.
private static final int SMASH_DAMAGE = 30;
private static final int SMASH_RADIUS = 3;
private static final int CLEAVE_DAMAGE = 50;
private static final int HEALTH_TO_ADD = 10;
private static final int HEAL_TIMES = 10;
private int numBalls = 3; // numbers of projectiles to be fired
private boolean aoe = true; // effect the projectile will apply
private ProjectileEffects effect = ProjectileEffects.BURN; // whether the effect will be applied in a radius or not
Method that calls the event that corresponds with the state:
private void animate() {
// Check if same animation is being called
if (prevState.equals(state)) {
return; // skip rest of function
}
switch (state) {
case CAST -> demon.getEvents().trigger("demon_cast_spell");
case IDLE -> demon.getEvents().trigger("demon_idle");
case WALK -> demon.getEvents().trigger("demon_walk");
case DEATH -> demon.getEvents().trigger("demon_death");
case BREATH -> demon.getEvents().trigger("demon_fire_breath");
case SMASH -> demon.getEvents().trigger("demon_smash");
case CLEAVE -> demon.getEvents().trigger("demon_cleave");
case TAKE_HIT -> demon.getEvents().trigger("demon_take_hit");
case TRANSFORM -> demon.getEvents().trigger("transform");
default -> logger.debug("Demon animation {state} not found");
}
prevState = state;
}
NOTE: All the events triggered in this class are captured by event listeners in DemonAnimationController.
This method takes a parameter that uses the value returned by getJumpPos()
. This method moves the Demon Boss from the original position to a new position specified by the param with a new MovementTask(). jump(Vector2 finalPos)
also triggers the relevant sound events and switches the state to SMASH
.
jumpTask = new MovementTask(finalPos);
jumpTask.create(owner);
jumpTask.start();
This method returns a value of type Vector2 for the jump(Vector2 finalPos)
to use. getJumpPos()
returns a valid position 3 units away from the current position.
private Vector2 currentPos;
currentPos = demon.getPosition();
This method checks whether the Demon Boss has completed the jump i.e. moved from the current position to the finalPos
and stops the jumpTask
. It also deals AOE damage to the surrounding Human Entities by using the applyAoeDamage(Array<Entity> targets, int damage)
and getNearbyHumans(int radius)
methods.
applyAoeDamage(getNearbyHumans(SMASH_RADIUS), SMASH_DAMAGE);
This method applies SMASH_DAMAGE
to all the targets provided by getNearbyHumans(int radius)
.
This method returns a list of nearby entities with PhysicsLayer.HUMAN. Using existing functionality from the system, the method filters through the nearby entities to get a list of entities with the PhysicsLayer of HUMAN.
Array<Entity> nearbyEntities = ServiceLocator.getEntityService().getNearbyEntities(demon, radius);
Array<Entity> nearbyHumans = new Array<>();
// iterate through nearby entities checking if they have desired properties
for (int i = 0; i < nearbyEntities.size; i++) {
Entity targetEntity = nearbyEntities.get(i);
HitboxComponent targetHitbox = targetEntity.getComponent(HitboxComponent.class);
if (targetHitbox == null) {
break;
}
// check target layer
if (!PhysicsLayer.contains(PhysicsLayer.HUMANS, targetHitbox.
getLayer())) {
break;
}
nearbyHumans.add(targetEntity);
}
return nearbyHumans;
This method changes the state to BREATH
and handles the fire breath attack. This method creates projectiles based on the values specified by the following variables: effect
, aoe
and numBalls
. Using changeBreathAttack(int numBalls, ProjectileEffects effect, boolean aoe)
, these variables can also be changed for fireBreath()
to create the desired outcome. fireBreath()
Changing Fire Breath Variables: changeBreathAttack(int numBalls, ProjectileEffects effect, boolean aoe)
This method is for changing the fire breath variables: effect
, aoe
and numBalls
.
This method changes the state to CLEAVE
and handles the cleave attack. This method will only be called if there is a HUMAN target near the Demon Boss. Using existing functionality from the system, this method get the closest entity with the PhysicsLayer of HUMAN and deals CLEAVE_DAMAGE
to that target.
Entity target = ServiceLocator.getEntityService().getClosestEntityOfLayer(demon, PhysicsLayer.HUMANS);
This method changes the state to CAST
and starts healing the Demon Boss. It is called when health drops below half. The Demon Boss's health increases by HEALTH_TO_ADD
every HEAL_TIMES
seconds.