Skip to content

[OLD] General Mobs

meganroxburgh edited this page Oct 1, 2023 · 1 revision

Individual wiki pages have been created for each of the classes defined below, which go into more detail on how they should be used and the testing plan for each.

General mobs are a type of NPC entity which traverse across the grid, towards the towers and following set lanes. When they are in a certain range of the towers, they shoot projectiles to try and destroy the towers.

UML Diagram

370810139_1001547834381069_5651423304682729100_n

Mob Base Entity Class

The purpose of the class is to be a base structure for all mobs. It functions as a container for relevant information to all mobs and provides a consistent base to build future specialised mobs from. It holds all enemy stats such as health, speed, base attack, and all abilities including long-range and close-range attacks. It lacks functionality aside from retrieving information of a specific enemy and is only to be used as a base structure, helping to streamline enemy construction.

The BaseEnemyConfig holds all relevant information to initialise an advanced CombatStatsComponent which is responsible for handling combat-related statistics including dealing and taking damage.

BaseEnemyConfig config = configs.specialtyEnemy;
…
….addComponent(new CombatStatsComponent(conifg.fullHealth, config.baseAttack, config.drops, config.getCloseRangeAbilities, config.getLongRangeAbilities)…

specialtyEnemy is a predefined enemy type. This has minimal functionality and should only be used to define a Speciality Enemy and not be used as an enemy itself.

Weapon Interface

The Melee and Projectile classes implement the Weapon interface. The purpose of this interface is to promise the implementation of necessary functions and values to classes which can be used to attack. This interface is primarily featured in CombatStatsComponent.

public Weapon getWeapon(Entity target) {
  ArrayList<Melee> withinRange = withinRange(target);
  if (withinRange.size() > 0) {
  	return withinRange.get(pickRandom(withinRange));
  }
  return longRangeAttack();
}

The type of weapon will depend on the distance from the target and therefore cannot be promised as a singular type. Using the weapon interface ensures the returning value has required functionality for future uses of the value.

Melee Class

The Melee class is used to define an ability that will deal damage but requires a minimum distance from the target. It is implemented as a sibling to Projectiles where the CombatStatsComponent will call for a Weapon and return a Melee for close range or Projectile for long range. It is designed as a base to predefined Melee abilities and is used in PredefinedWeapons class. Its purpose is to store all relevant attributes required to attack a target.

Melee(int damage, int attackDamage, String element, int castTime, int cooldown)
 
Melee sword= new Melee(10, 4, “fire”, 1, 1);

PredefinedWeapons Class

This class is responsible for the storage of all weapons. All weapons should be defined in this class and accessed later. It is purely a container for weapon storage and does not have any other functionality, nor should it be used as anything else. When Specific mobs are built from the BaseEnemyConfig they will only contain predefined weapons from this class.

public class PredefinedWeapons {
	// Melee attacks
	public static Melee sword = new Melee(10, 4, "fire", 1, 1);
	public static Melee punch = new Melee(3, 1, "air", 1, 1);
…

CombatStatsComponent

CombatStatsComponent was expanded upon to incorporate the abilities, close-range and long-range, that enemies have. There are two initialisers for this component including the original init and a new init which requires the drops, close range and long range of the entity. There were minimal changes, majority of alterations to this file were additions. The changes made include the addition of updating the state of the entity whenever health is updated.

public void changeState() {
	if (this.health <= (this.fullHealth * 0.33)) {
    	…	
    }
}

The additional methods are:

  • getWeapon(): return a Weapon
  • withinRange(): return a list of all Melee which can attack the target (if close enough to use)
  • longRangeAttack(): pick a random long range attack if one exists
  • pickRandom(): pick a random index of the provided list
  • drop(): pick a random currency to drop

pickRandom(), withinRange() and longRangeAttack() work together to return the appropriate weapon when touchAttackComponent requests a weapon. getWeapon() receives a target Entity which will be passed to withinRange(). The withinRange() function will measure the distance between this and the target Entity’s location. For each closeRangeAttack, if the target is within range, it is added to a list of possible Melee weapons to use and it returned to getWeapon(). If none are returned then a Projectile is provided to touchAttackComponent, else a Melee is selected at random.

TouchAttackComponent

if (combatStats.getWeapon(target) != null) {
	targetStats.hit(combatStats.getWeapon(target).getDamage());

Xeno Grunt Designs and Animations

The Xeno Grunt is a basic enemy mobs which spawns in high volume down each lane, capable of shooting at the tower directly in front, or swinging at it once close enough.

This is the first basic mob to be implemented, and as such has a basic but diverse ability set, which serves as the basis for future general mob implementations.

Assets & Images

The Xeno Grunt run animations are simple 8 frame loops, read from the xeno-grunt-run.png and xeno-grunt-run-damaged.png by xenoGruntRunning.atlas and xenoGruntRunningDamaged.atlas respectively. The current xeno-grunt-run-damaged.png sprite strip will likely be changed later to match the theme. xeno-grunt-run xeno-grunt-run-damaged

Attack animations are read from the xeno-grunt-melee-attack.png and xeno-grunt-range-attack.png by xenoGruntRangedAttack.atlas and xenoGruntMeleeAttack.atlas respectively. These animations operate on different loop lengths, with the first melee attack having a 9 frame loop, the second melee attack having a 6 frame loop, and the ranged attack having a 5 frame loop. xeno-grunt-melee-attack xeno-grunt-range-attack

The death animation is read from xeno-grunt-death.png by xenoGruntDeath.atlas, and has a 5 frame loop. This sprite sheet has been made up from the separate PNGs xeno-grunt-death-falling.png and xeno-grunt-death-grounded.png. xeno-grunt-death

XenoAnimationController Class

The XenoAnimationController class listens for the events relating to the Xeno Grunts ability set, and has been set up to play the relevant animation once detected.

Mob Interactions with Towers/Projectiles

Later in the development of the game, mobs will shoot projectiles and attack tower entities. To begin to implement this feature, a ShootTask class was created, which will store all the relevant information for shooting projectiles. This task is assigned to all NPC entities in the NPCFactory class, under the createBaseNPC() function. The method detects when the player entity is within range, and is visible to the mob entity, and when it is, the shoot task is initiated. Each time the player moves into this range, the task is initiated. Currently, the implementation of the task can be seen by a print statement in the terminal. Upon integrating with the projectiles and towers, a projectile entity will be seen being shot from the mob towards a particular tower.

ShootTask Class

The ShootTask class takes in four parameters, target, priority, viewDistance and maxChaseDistance. This is similar to the pre-existing ChaseTask class, as the functionality to detect when the task should be actioned is the same here. A description of these parameters is given below:

  • target: represents the Entity which the projectile will shoot at
  • priority: is an integer value, -1 if the target is out of range and the task should not be initiated (any positive value for if the target is in range)
  • viewDistance: is a float value representing the maximum distance from the target at which the shooting can start
  • maxChaseDistance: is a float value representing the maximum distance from the target while shooting before giving up

The methods defined in this class are outlined as follows:

  • start(): defines what to do when the task is called (in this instance, print to the terminal)
  • getPriority() -> int: retrieve the current task priority based on whether the action is currently occurring or not
  • getDistanceToTarget() -> float: retrieve the current distance between the mob and the target
  • getActivePriority() -> int: retrieve the current active priority to determine whether the shoot task should continue or stop
  • getInactivePriority() -> int: retrieve the current inactive priority to determine whether to start the shoot task or to continue not performing the action
  • isTargetVisible() -> bool: returns True if the target entity is directly visible by the mob and False otherwise

NPCFactory Class

As noted, the class is added as a task to the NPCFactory class, in the createBaseNPC(Entity target) method. This creates a new AIComponent() and adds the task using .addTask(new ShootTask(target, 10, 3f, 4f)). This sets the initial parameters to be the target player entity, the priority to be 10, the viewDistance to be 3 and the maxChaseDistance to be 4.

The createXenoGrunt() function in the NPCFactory class is responsible for creating new Xeno Grunt mobs. Currently, the Xeno Grunt is created with the BaseEnemyConfig configuration, which holds information about the Xeno Grunt's combat abilities and drops.

Mob Movement & Spawning

Mobs in the game spawn on the right side of the screen and move towards the player’s defences in order to attack them. These mobs are capable of spawning in any of the game’s “lanes”, and will only attack towers within its associated lane. The specific lane each individual mob spawns in is random between game sessions.

WanderTask

Mob movement was implemented by repurposing the given WanderTask, rather than creating an entirely new class. A new private helper function getDirection() was created which returned a GridPoint at an equal y level to where the associated entity spawned, with the x coordinate being “0”, which is the leftmost column of the map. Thus, when the GridPoint was given to a MovementTask assigned to a mob, it would move directly to the left side of the map from the player’s perspective.

ForestGameArea

The spawning of the mobs was taken care of within the spawnXenoGrunts() method in ForestGameArea. Minimum and maximum bounds are assigned for mob spawning, which constrain the mob to only spawn in the rightmost map column, however at random y levels. The RandomUtils class is utilised to accomplish this. Each mob is randomly assigned to a GridPoint, where the entity spawns at the beginning of the game.

Clone this wiki locally