Skip to content
This repository has been archived by the owner on Dec 15, 2019. It is now read-only.

Behaviors

wellcaffeinated edited this page Nov 18, 2014 · 13 revisions

Behaviors follow the Factory Pattern. Please read about the factory pattern to learn about creation, declaration, and extending behaviors.

See also: API Reference on Behaviors

Behaviors (or Behaviours) are the "how" of a physics simulation. They are rules applied to the world that act on bodies during every timestep to simulate specific physical laws. A world without any behaviors will act as an infinite, frictionless vacuum. (No behaviors are included in the core library, they are available as extensions)

The most familiar example of a behavior is adding "gravity" to a simulation. What is most often meant by "gravity" is a constant acceleration in the downward (positive "y") direction. Because of the frequent need for this, a "constant-acceleration" behavior is available as an extension.

Example:

// add some gravity
var gravity = Physics.behavior('constant-acceleration', {
    acc: { x : 0, y: 0.0004 } // this is the default
});
world.add( gravity );
// later... flip the world upside down!
gravity.setAcceleration({ x: 0, y: -0.0004 });

Some behaviors act as "detectors", which don't modify bodies directly. Instead they detect specific events and announce them to the world's pubsub system so other behaviors can take appropriate actions. One example of this is collision detection and response. There are separate behaviors for collision detection, collision response, and even so-called "sweep and prune" optimization algorithms.

Applying behaviors to a sub-set of bodies

By default, behaviors will apply to every body added to the world.

Most behaviors have a .applyTo() method that can be used to control which bodies the behavior is applied to. The method accepts an array of bodies.

Example:

var boxes = [];
// add bodies to the boxes array...

// only apply gravity to the bodies in the boxes array
var accel = Physics.behavior('constant-acceleration')
    .applyTo( boxes );

world.add( accel );

Hint: Queries can help collect sub-sets of bodies easily!

Creating a custom Behavior

The most basic form of a behavior simply involves creating a .behave() method. If a behavior includes a .behave() method, it will automatically get subscribed to the world's integrate:positions event. The integrate:positions event is the last stage of integration, and a good time to apply accelerations to bodies.

The .behave() method is speed-critical, and therefore, usage of Scratchpads is strongly recommended if creating temporary objects.

The .behave() method will be passed an event object which includes: .bodies array containing the world's bodies, and .dt a number representing the timestep size. The behave method should call this.getTargets() to get the specific bodies this behavior is applied to (which may or may not be all bodies in the world). The constant-acceleration behavior is a good example of this basic implementation:

(full source)

// ...
// Apply an acceleration to each body in the world
behave: function( data ){

    var bodies = this.getTargets();

    for ( var i = 0, l = bodies.length; i < l; ++i ){
        
        bodies[ i ].accelerate( this._acc );
    }
}
// ...

In more complex situations, it may be necessary to subscribe to a different part of the integration phase, or subscribe multiple callbacks. To do this, it is necessary to override the methods .connect() and .disconnect() where subscribing/unsubscribing can be completely controlled.

The body-collision-detection behavior is a good example of this. The subscription depends on configuration options:

(full source)

// ...
// connect to a world
connect: function( world ){

    if ( this.options.checkAll ){

        world.on( 'integrate:velocities', this.checkAll, this );

    } else {

        world.on( 'collisions:candidates', this.check, this );
    }
},
// disconnect from a world (cleanup)
disconnect: function( world ){

    if ( this.options.checkAll ){

        world.off( 'integrate:velocities', this.checkAll, this );

    } else {

        world.off( 'collisions:candidates', this.check, this );
    }
}
// ...

Specific Behaviors

References for all behaviors can be found in the API Docs under Behaviors.