Skip to content

Dodging Component

Chia-Chuan Tsou (Jason) edited this page Oct 1, 2023 · 16 revisions

DodgingComponent Documentation

Overview

The DodgingComponent is a component that works cohesively with the MobDodgeTask and introduces a dodging mechanism based on the detection of another entity (such as a projectile). Ultimately, it adds a method to an event listener, dodgeIncomingEntity, and utilizes game's built-in raycast mechanism to detect another entity. If the entity is detected, the dodge task will trigger this event listener and will change the mob's vertical direction based on its location on the map.

For simplicity of explanation, the entity detected from now on will be referred to as a projectile since it was its intended functionality but note that the detected entity may be changed based on the target layer initialised.

Usage

To use this DodgingComponent, make sure to add the MobDodgeTask to the specified entity before adding the component itself with its desired configurations.

Entity entity = NPCFactory.createMeleeBaseNPC();
DodgingComponent dodgeComponent = new DodgingComponent(PhysicsLayer.PROJECTILE);
// Priority is 5 here, just ensure it is higher than the other tasks.
entity.getComponent(AITaskComponent.class).addTask(new MobDodgeTask(new Vector(2f, 2f), 2f, 5));
entity.addComponent(dodgeComponent);

Configuration

This component allows flexibility in configuration of the dodging mechanism, with only the detected target layer deemed essential for its initialisation.

  • targetLayer: The target layer to be detected from the raycast. i.e. PhysicsLayer.PROJECTILE.
  • rangeDetection: A float value representing the horizontal range where the entity of the targetLayer is detected, activating the dodge event. If not specified, it is initialised to be 0.25f.
  • dodgeSpeed: The vertical speed of the targeted mob entity when dodging the projectile. If not specified, it is initialised to be 1.75f.

Requirements

  1. MobDodgeTask to be added to the AITaskComponent with a higher priority level than the other MobWanderTask.
  2. Although this component utilises the MobDodgeTask, the component should still have a MobWanderTask with a lower priority level. The direction of this task should have an existing horizontal velocity that is > 0f.
  3. Should have a PhysicsMovementComponent with a set target.

Functionality

Logic

This component's logic simply detects another target layer within a certain range proximity and moves the entity upwards or downwards by providing a vertical target and velocity. This proximity detection is constructed through creating a Vector2 max range based on the initialised rangeDetection variable, and using the PhysicsService raycast boolean identifier.

  private boolean isTargetVisible(Vector2 mobPos) {
    Vector2 maxRange = new Vector2(mobPos.x - rangeDetection, mobPos.y);
    // check also the upper and lower boundaries of the mob with the offset y mob
    // detection.
    Vector2 upperYMaxRangePos = new Vector2(mobPos.x - 3, mobPos.y - Y_OFFSET_MOB_DETECTION);
    Vector2 lowerYMaxRangePos = new Vector2(mobPos.x - 3, mobPos.y + Y_OFFSET_MOB_DETECTION);

    // Raycast the upper, middle and lower detection range.
    return physics.raycast(mobPos, maxRange, targetLayer, hit)
        || physics.raycast(mobPos, upperYMaxRangePos, targetLayer, hit)
        || physics.raycast(mobPos, lowerYMaxRangePos, targetLayer, hit);
  }

The mobPos is a Vector2 value retrieved from the center position of the mob entity. The hit variable is a RaycastHit variable. For more info, confer the documentation.

Offset accomodation - Triple raycast

The reason for raycasting based on the upperYMaxRangePos and the lowerYMaxRangePos is to accomodate for the collider sizes of the mob and projectile entity with respect to the raycast. If this is not accomplished, the raycast from the center position of the mob entity may not be able to detect the projectile entity, even if the entity ends up colliding with the projectile due to collider sizes.

This Y_OFFSET_MOB_DETECTION for the triple raycasting is initialised to be 0.35f -> Can be altered if desired.

The mob's vertical direction of dodge depends on its respective location on the map. If the mob is at the upper half quadrant, the mob will dodge downwards.

private void setVerticalAngleDirection(float y) {
    entity.getComponent(PhysicsMovementComponent.class).setTarget(new Vector2(0, y));
  }
setVerticalAngleDirection(mobPos.y > 3.5 ? mobPos.y - 15 : mobPos.y + 15);

In the time of writing this documentation, vertical half map size is 3.5. Please change this accordingly if the map / lane sizes changes.

As seen, the vertical target direction of the PhysicsMovementComponent is altered by 15 accordingly. This is what makes the mobs go upward or downward.

Please note: This dodging based on map location tend to make dodging mobs migrate to the middle of the map. Further extensions of this component could include a random direction identifier, encouraging sporadic dodging mechanisms instead of predictable patterns emerging.

Event triggers based on task

In this case, we utilised a MobDodgeTask to trigger the event of dodgingIncomingEntity. This detection will activate after every set interval. In this case, the set interval is 500ms. Set interval is crucial as it prevents detection to be checked after every frame of the running game.

  /**
   * Run a frame of the task. In this extension of the update(), the
   * "dodgeIncomingEntity" event will be detected and triggered on set intervals.
   */
  @Override
  public void update() {
    super.update();
    if (timeSource.getTime() >= endTime) {
      owner.getEntity().getEvents().trigger("dodgeIncomingEntity",
          owner.getEntity().getCenterPosition());

      endTime = timeSource.getTime() + DELAY_INTERVAL; // update time
    }
  }

If this component was to be used outside of dodging mobs, please make another respective task with the same logic that has a higher priority than the other tasks.

Best Practices

Map boundaries

Please ensure map boundaries with appropriate collision layers are put in place for the respective mob entity. As such, the mob entity should not be able to go of map bounds due to its dodging mechanisms. Does not particularly apply for the current mechanism but more so for the direction-randomiser extension.

Speed

If dodge speed is to be initialised normally, ensure it is an appropriate value - especially in coherence with the range detection variable. For instance, setting the dodge speed to be a very low value with a low detection range could make the mob still collide with the projectile, ultimately rendering the component useless.

The speed should always be > 0f.

Range detection

The default range detection is 0.25f and is deemed to be an appropriate value for a dodging speed of >1.25f. Feel free to change this accordingly but going below this value may result in the mob still colliding with the projectile depending on the vertical and horizontal speed and its collider sizes. On the other hand, going above 1.25f results the projectile dodging the incoming projectile at a very far distance, defeating the purpose of the dodging aspect of the component.

That being said, feel free to experiment and use values desired that are outside the recommended range.

Testing

Visually, the mob with the MobDodgeTask and DodgingComponent dodges the incoming projectile appropriately based on its respective position on the map. JUnit confirmed the existence of this component when added and the number of invocations for the event to be triggered based on the specified distance of the two entities' locations.

Clone this wiki locally