-
Notifications
You must be signed in to change notification settings - Fork 407
Behaviors
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.
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:
// ...
// 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:
// ...
// connect to a world
connect: function( world ){
if ( this.options.checkAll ){
world.subscribe( 'integrate:velocities', this.checkAll, this );
} else {
world.subscribe( 'collisions: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( 'collisions:candidates', this.check );
}
}
// ...
Use the constant-acceleration
behavior to add a constant acceleration to all bodies in the world. Accepts the following configuration parameters (and defaults):
// the acceleration vector
acc: { x : 0, y: 0.0004 }
Use the newtonian
behavior to create an inverse square attraction between all bodies in the world. Accepts the following configuration parameters (and defaults):
// the strength of the attraction (negative for repulsion)
strength: 1
Use the rigid-constraint-manager
behavior to manage verlet distance constraints between bodies in the world.
NB: requires a verlet compatible integrator to be used by the world.
Accepts the following configuration parameters (and defaults):
// set a default target length
targetLength: 20
Initialize:
var rcm = Physics.behavior('rigid-constraint-manager');
world.add( rcm );
To add a constraint between two bodies:
var targetLength = 20;
// store the constraint data for later
var constraint = rcm.constrain( bodyA, bodyB, targetLength );
To remove a constraint:
rcm.remove( constraint );
// or to remove all constraints...
rcm.drop();
Use the edge-collision-detection
to detect collisions of bodies with the edges of a bounding box (AABB).
NB: this is only the detection of collisions with edges. To have a collision response, use it with the
body-collision-response
behavior.
For more about collisions, see the Collision documentation.
Accepts the following configuration parameters (and defaults):
// the AABB for the edges
aabb: null,
// the restitution of the edges (bounciness)
restitution: 0.99,
// the coefficient of friction of the edges
cof: 1.0
Use the body-collision-detection
behavior to detect collision between bodies.
NB: this is only the detection of collisions between bodies. To have a collision response, use it with the
body-collision-response
behavior.
For more about collisions, see the Collision documentation.
Accepts the following configuration parameters (and defaults):
// force check every pair of bodies in the world
checkAll: false
Collision detection is computationally expensive, this behavior is best used as a "narrow phase" collision detection, and paired with the sweep-prune
behavior for a "broad phase" collision detection.
Use the sweep-prune
behavior for an optimized broad phase collision detection between bodies.
NB: this is meant to be used in tandem with
body-collision-detection
, andbody-impulse-response
(if collision response is desired).
For more about collisions, see the Collision documentation.
No configuration.
Use the body-impulse-response
for an impulse response between detected colliding bodies.
NB: this is meant to be used in tandem with
body-collision-detection
, and optionallysweep-prune
.
For more about collisions, see the Collision documentation.
No configuration.