= Steer Behaviors
:revnumber: 2.0
:revdate: 2020/07/23


Steer behaviors allows you to control the locomotion of "`characters`", this can reduce drastically the time needed to develop a game since for almost every game we need to set how these "`characters`" will be moving around the scene.

[cols="2",caption=]
.YouTube
|===

a|.Steer behaviors in action
image:ai/steer/hqdefault.jpg[youtu.be/yyzTntsGV00,width="",height="",link=https://youtu.be/yyzTntsGV00]
a|

|===


Be sure that you have checked the demos: They can be downloaded here: link:http://jmesteer.bdevel.org[jmesteer.bdevel.org]


== First steps

The steer behaviors AI is integrated with MonkeyBrains so before start coding be sure that you have checked the xref:ai/monkey_brains.adoc[monkey brains documentation].

Be sure to create a reference to MonkeyBrains from your project.

Finally, do not forget to import the `com.jme3.ai.agents.behaviors.npc.steering` package.


== Overview

*Available behaviours:*

*  Move
*  Seek
*  Arrive
*  Flee
*  Pursuit
*  Leader follow
*  Evade
*  Cohesion
*  Alignment
*  Obstacle Avoidance
*  Unaligned obstacle avoidance
*  Hide
*  Slow
*  Queuing
*  Containment
*  Path follow
*  Wall approach
*  Wander Area
*  Simple Wander
*  Relative wander
*  Sphere wander
*  Box explore
*  Separation

All the behaviours extend from the `AbstractSteeringBehavior` class.


== Adding a steer behavior

Create instances from the steer behavior classes, They are located in the `com.jme3.ai.agents.behaviors.npc.steering` package.

If we want to add more than one steer behavior, we need to create a container:
[WARNING]
====
If you add more than one steer behavior to a `SimpleMainBehavior` it will cause problems in the rotation of the agents.
====

[cols="2", options="header"]
|===

a| Container
a| Purpose

a| CompoundSteeringBehavior
a| Contains and merges several `AbstractSteeringBehavior` instances

a| BalancedCompoundSteeringBehavior
<a| Each force generated inside this container is reduced in relation with a proportion factor: "`Partial Force`" / "`Total`" container force

|===

Once we know which container fits better for our agent, We create a new instance and add all the behaviors that we need:

[source,java]
----

SimpleMainBehaviour mainBehavior = new SimpleMainBehavior(myAgent);
    CompoundSteeringBehavior steer = new CompoundSteeringBehavior(myAgent);
    //BalancedCompoundSteeringBehavior steer = new BalancedCompoundSteeringBehavior(myAgent);
    steer.addSteerBehavior(steerBehavior1);
    steer.addSteerBehavior(steerBehavior2);
mainBehaviour.addBehavior(steer);
myAgent.setMainBehavior(mainBehavior);

----


[NOTE]
====
Note that you can have nested containers, like is shown in the following example:
====


[source,java]
----

SimpleMainBehaviour mainBehavior = new SimpleMainBehavior(myAgent);
    CompoundSteeringBehavior steer = new CompoundSteeringBehavior(myAgent);
        BalancedCompoundSteeringBehavior nestedSteer = new BalancedCompoundSteeringBehavior(myAgent);
        nestedSteer.addSteerBehavior(steerBehavior1);
    steer.addSteerBehavior(nestedSteer);
    steer.addSteerBehavior(steerBehavior2);
mainBehavior.addBehavior(steer);
myAgent.setMainBehavior(mainBehavior);

----


== Prioritizing behaviors

You can assign priority layers: The steering controller first checks the higher layer to see if all the behaviors returns a value higher than `minLengthToInvalidSteer`, if so it uses that layer. Otherwise, it moves on to the second layer, and so on.

To assign priority layers add behaviors with the following function:

....
  addSteerBehavior (AbstractSteeringBehavior behavior, int priority, float minLengthToInvalidSteer)
....


[TIP]
====
To optimize the process speed add the behaviors with the lowest priority first.
====


[NOTE]
====
The layer and the min length to consider the behavior invalid are 0 by default.
====



== Setting up forces

If a behavior extends from the `AbstractStrengthSteeringBehavior` class, you can manage how the produced forces will work.

Use `setupStrengthControl(float scalar)` to increase/decrease the steer force produced by a behavior or `setupStrengthControl(Plane plane)` If you want to work with 2D behaviors.

Example:

[source,java]
----

    Plane horizontalPlane = new Plane(new Vector3f(0,1,0), 0);

    steerBehavior1.setupStrengthControl(0.5f); //Force reduced a 50%
    steerBehavior2.setupStrengthControl(horizontalPlane); //Force contained in the XZ plane
    steerContainer.setupStrengthControl(horizontalPlane, 2f); //Contained in the XZ plane and increased a 100%

----


== Implementing your own steer behavior

To benefit from all the features, you have to create a new class that extends from `AbstractStrengthSteeringBehavior`.

The responsible for the agent's acceleration is the vector returned in the `calculateRawSteering()` method:

[source,java]
----

    @Override
    protected Vector3f calculateRawSteering() {
        Vector3f steerForce = Vector3f.ZERO;

        //calculations

        return steerForce;
    }

----

In addition, you can change a brake factor which will reduce the resultant velocity for the agent:

[source,java]
----

    @Override
    protected Vector3f calculateRawSteering(){
        this.setBrakingFactor(0.5f); //The agent's velocity will be reduced a 50%
        return Vector3f.ZERO;
    }

----


[WARNING]
====
The braking force must be a float contained in the [0,1] interval
====


[NOTE]
====
0 means the maximum braking force and 1 No braking force
====



=== Strict arguments

To ensure that the behavior will work as you had planned it to work It's recommended to create your own link:http://docs.oracle.com/javase/7/docs/api/java/lang/IllegalArgumentException.html[IllegalArgumentException] class. To do this, create your own container class extending from `com.jme3.ai.agents.behaviors.npc.steering.SteeringExceptions`; Each exception inside the container class extends from `SteeringBehaviorException`. Furthermore, It will help users to recognize better which is the origin of any problem.

Example:

[source,java]
----

    public class CustomSteeringExceptions extends SteeringExceptions  {

        public static class CustomRuntimeException extends SteeringBehaviorException {
            public CustomRuntimeException(String msg) { super(msg); }
        }

        // ... other exceptions ...
    }

----

[source,java]
----

    public SteerBehaviorConstructor(Agent agent, int value, Spatial spatial) {
        super(agent, spatial);
        if(value > 5) throw new CustomSteeringExceptions.customRuntimeException ("Value must be lower than 5");
        this.value = value;
    }

----


== Useful links

java steer behaviors project: link:http://jmesteer.bdevel.org/[jmesteer.bdevel.org]
