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

Behaviors

Jasper edited this page Sep 6, 2013 · 13 revisions

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

Note: Because some english speaking countries (like Canada and the Great Britain) spell the word with a "u" (behaviour), an alias has been created so that .behavior() and .behaviour() are both valid.

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.

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 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 = data.bodies;

    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.subscribe( 'integrate:velocities', this.checkAll, this );

    } else {

        world.subscribe( PUBSUB_CANDIDATES, this.check, this );
    }
},
// disconnect from a world (cleanup)
disconnect: function( world ){

    if ( this.options.checkAll ){

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

    } else {

        world.unsubscribe( PUBSUB_CANDIDATES, this.check );
    }
},
//...
Clone this wiki locally