Skip to content

Enemy NPCs Programming Guide

LJ edited this page Oct 17, 2024 · 8 revisions

Enemy NPC Documentation

A list of enemy NPCs implemented in the game, as well as their respective stats, specific implementations and other details can be found below.

Enemies are spawned into the ForestGameArea, which consists of 3 different regions: Land, Water, and Air. Enemies only spawn in their appropriate region, meaning all land animals such as bears and monkeys only spawn in the land area, all water animals such as the eel and frog only spawn in the water area, and all air animals such as the pigeon and macaw only spawn in the air region. A supplier is used to generate entities of the selected enemy type and spawns them randomly within the specified area. The number of enemies spawned is determined in the configuration settings. This method of generation ensures that enemies are spawned in a way that is challenging for the player while keeping the game novel. The amount of enemies are determined by the spawn configurations:

    public int NUM_FROGS;
    public int NUM_MONKEYS;
    public int NUM_BEARS; ...

The numbers for each enemy type are defined in the entitySpawn json file:

  "NUM_FROGS" : 4,
  "NUM_MONKEYS" : 5,
  "NUM_BEARS" : 4, ... 

Feature Components

NPC Design

The NPC enemy design will be consistent using pixel art for enemies which aligning with the game's aesthetic and style guidelines. Unique and recognisable enemy character sprites will be used, collaborating with the design committee and studio to ensure consistency with the game's vision.

Player Interaction

Enemy NPCs remain invisible and dormant until the player enters a designated proximity radius, at which point they spawn and give chase. Upon reaching a specific distance from the player, they engage the player in battle (developed in conjunction with the combat feature team). An enemy cut screen displaying the enemy's stats - attack and health, is displayed before combat is engaged.

Details about each sub-feature functionality can be found below:

Statistics

As mentioned earlier, each enemy has slightly different statistics, and as the game progresses, the general strength of enemies will increase. Enemies have four base statistics:

  • Health: an enemy endures more hits.
  • baseAttack: an enemy deals more damage with each attack.
  • baseDefense: an enemy has a higher success rate when blocking an attack.
  • Speed: an enemy attacks faster and is more likely to parry attacks.
  • Experience: an enemy has an associated experience value that is transferred to the player upon defeat.

On each enemy spawn, these statistics (except for speed) will be altered by around 10%. So for example, if an enemies baseAttack is 50 then the actual in game value will be between 45 and 55. Note that these values will always be a round integer.

Generally, these statistics will be reflected in the type of enemy animal. For example, a chicken has low health, attack and defense but is moderately fast. Whereas a bear has high health and attack, moderate defense and fairly low speed.

As mentioned earlier the general strength of enemies is increased as the game progresses, but within each kingdom (forest, aquatic and aerial) there is also a gradient in animal strength. There will be 4-5 enemy types in each kingdom and there will be varying overall strength between them. In the forest, for example, the chicken is the weakest overall animal, then the monkey, frog and the bear is the strongest. Note that 'strength' here is defined as the sum of all the enemy base stats.

The speed stat is implemented so that a speed of 0.5 is defined as 50 in the enemyNPCs.json file. This is because speed is defined as an int value, but we need to define some speed as a float value, such as 0.5.

To see how these statistics will function in battle, refer to the Combat Wiki.
To see the specific statistic for each enemy NPC, refer to the Enemy NPC Statistics Wiki

Enemy NPC Implementation

Types of enemies:

private enum EnemyType {
    FROG,
    CHICKEN,
    MONKEY,
    BEAR;
  }

Example implementation of Base Enemy to create a new enemy NPC of Monkey type:

Entity monkey = createBaseEnemy(playerEntity, EnemyType.MONKEY);

Create Base Enemy Function:

private static Entity createBaseEnemy(Entity target, EnemyType type) {
    AITaskComponent aiComponent = new AITaskComponent();

    if (type == EnemyType.MONKEY) {
      aiComponent.addTask(new SpecialWanderTask(new Vector2(2f, 2f), 2f));
      aiComponent.addTask(new RunTask(target, 10, 3f));
    } else {
      aiComponent.addTask(new WanderTask(new Vector2(2f, 2f), 2f));
      aiComponent.addTask(new ChaseTask(target, 10, 3f, 4f));
    }

    Entity npc =
        new Entity()
            .addComponent(new PhysicsComponent())
            .addComponent(new PhysicsMovementComponent())
            .addComponent(new ColliderComponent())
            .addComponent(new HitboxComponent().setLayer(PhysicsLayer.NPC))
            .addComponent(new TouchAttackComponent(PhysicsLayer.PLAYER))
            .addComponent(aiComponent);

    PhysicsUtils.setScaledCollider(npc, 0.9f, 0.4f);
    return npc;
  }

UML Diagram

image

Sequence Diagram

Sequence Diagram (EnemyNPCs)

Clone this wiki locally