//################################################################################################//
//################################################################################################//
// //
// ██ ██████ ██████ ██ //
// ██ ██ ██ ██ ██ //
// █████ ██ ██ ██ █████ █████ ██ ██ //
// ██ ██ ██████ █████ ██ ██ ██ ██ ██ ██ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// █████ ██████ ██████ █████ █████ █████ //
// ██ //
// █████ //
// //
//################################################################################################//
//################################################################################################//
// CLASS CONSTRUCTOR
/**
* A rigid body. These are created via
* <a href=../classes/b2World.html#method_createBody>b2World.createBody()</a>.
*
* @module Dynamics
* @class b2Body
* @constructor
* @param {b2BodyDef} bodyDef
* @param {b2World} world
* @module Dynamics
*/
function b2Body(bodyDef, world) {
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ██████ ██ ██ //
// ██ ██ ██ //
// ██ ██ ████ █████ █████ █████ ████ █████ ██ █████ █████ //
// ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ ██ ██ ██ ██ █████ ██ ██ ██ █████ █████ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ █████ █████ █████ ██ ████ ██ █████ █████ //
// ██ //
// ██ //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
// property DECLARATIONS
/**
* The body origin transform.
*
* @public
* @property m_xf
* @type {b2Transform}
*/
this.m_xf = new b2Transform;
/*#if EXPORT_PARTICLES */
/**
* The previous transform for particle simulation. Only used by the
* <a href=../modules/Particle.html>Particle</a>
* and
* <a href=../modules/ParticleSystem.html>ParticleSystem</a> Module's.
*
* @public
* @property m_xf0
* @type {b2Transform}
*/
this.m_xf0 = new b2Transform;
/*#end EXPORT_PARTICLES */
/**
* The swept motion for continuous collision detection.
*
* @public
* @property m_sweep
* @type {b2Sweep}
*/
this.m_sweep = new b2Sweep;
/**
* Getter memory management.
*
* @private
* @property _sweep
* @type {b2Sweep}
*/
this._sweep = new b2Sweep;
/**
* @public
* @property m_linearVelocity
* @type {b2Vec2}
*/
this.m_linearVelocity = new b2Vec2;
/**
* @public
* @property m_force
* @type {b2Vec2}
*/
this.m_force = new b2Vec2;
// property INITIALISATIONS
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( bodyDef.position.isValid() );
b2Assert( bodyDef.linearVelocity.isValid() );
b2Assert( isFinite( bodyDef.angle ) );
b2Assert( isFinite( bodyDef.angularVelocity ) );
b2Assert( isFinite( bodyDef.gravityScale ) && bodyDef.gravityScale >= 0 );
b2Assert( isFinite( bodyDef.angularDamping ) && bodyDef.angularDamping >= 0 );
b2Assert( isFinite( bodyDef.linearDamping ) && bodyDef.linearDamping >= 0 );
}
/*#end EXPORT_ASSERTS */
// TODO: refactor with b2Body static class flags
/**
* @type {boolean}
*/
this.m_flag_islandFlag = false;
/**
* @type {boolean}
*/
this.m_flag_awakeFlag = false;
/**
* @type {boolean}
*/
this.m_flag_autoSleepFlag = false;
/**
* @type {boolean}
*/
this.m_flag_bulletFlag = false;
/**
* @type {boolean}
*/
this.m_flag_fixedRotationFlag = false;
/**
* @type {boolean}
*/
this.m_flag_activeFlag = false;
/**
* @type {boolean}
*/
this.m_flag_toiFlag = false;
/**
* @public
* @property m_flags
* @type {binary}
* @default 0
*/
// TODO: refactor with bitmask ops flags
this.m_flags = 0;
if ( bodyDef.bullet ) { this.m_flag_bulletFlag = true; }
if ( bodyDef.fixedRotation ) { this.m_flag_fixedRotationFlag = true; }
if ( bodyDef.allowSleep ) { this.m_flag_autoSleepFlag = true; }
if ( bodyDef.awake ) { this.m_flag_awakeFlag = true; }
if ( bodyDef.active ) { this.m_flag_activeFlag = true; }
// if (bodyDef.bullet) { this.m_flags |= b2Body.e_bulletFlag; }
// if (bodyDef.fixedRotation) { this.m_flags |= b2Body.e_fixedRotationFlag; }
// if (bodyDef.allowSleep) { this.m_flags |= b2Body.e_allowSleepFlag; }
// if (bodyDef.awake) { this.m_flags |= b2Body.e_awakeFlag; }
// if (bodyDef.active) { this.m_flags |= b2Body.e_activeFlag; }
/**
* @public
* @property m_world
* @type {b2World}
*/
this.m_world = world;
this.m_xf.p.copy( bodyDef.position );
this.m_xf.q.set( bodyDef.angle );
/*#if EXPORT_PARTICLES */
this.m_xf0.copy( this.m_xf );
/*#end EXPORT_PARTICLES */
this.m_sweep.localCenter.x = 0;
this.m_sweep.localCenter.y = 0;
this.m_sweep.c0.x = this.m_xf.p.x;
this.m_sweep.c0.y = this.m_xf.p.y;
this.m_sweep.c.x = this.m_xf.p.x;
this.m_sweep.c.y = this.m_xf.p.y;
this.m_sweep.a0 = bodyDef.angle;
this.m_sweep.a = bodyDef.angle;
this.m_sweep.alpha0 = 0;
this.m_linearVelocity.x = bodyDef.linearVelocity.x;
this.m_linearVelocity.y = bodyDef.linearVelocity.y;
/**
* The angular velocity of the body.
*
* @public
* @property m_angularVelocity
* @type {float}
* @default b2bodyDef.angularVelocity
*/
this.m_angularVelocity = bodyDef.angularVelocity;
/**
* Linear damping is use to reduce the linear velocity. The
* damping parameter can be larger than 1.0f but the damping
* effect becomes sensitive to the time step when the damping
* parameter is large.
*
* @public
* @property m_linearDamping
* @type {int}
* @default b2bodyDef.linearDamping
*/
this.m_linearDamping = bodyDef.linearDamping;
/**
* @public
* @property m_angularDamping
* @type {int}
* @default b2bodyDef.angularDamping
*/
this.m_angularDamping = bodyDef.angularDamping;
/**
* For inertia (perceived gravity) scaling.
*
* @public
* @property m_inertiaScale
* @type {float}
* @default b2bodyDef.inertiaScale
*/
this.m_gravityScale = bodyDef.gravityScale;
/**
* @public
* @property m_torque
* @type {float}
* @default 0
*/
this.m_torque = 0;
/**
*
* @public
* @property m_sleepTime
* @type {float}
* @default 0
*/
this.m_sleepTime = 0;
/**
* The body type: Static, Dynamic or Kinematic.</br></br>
*
* NOTE: The
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS framework</a>
* adds a fourth type: Tweened. TODO crosslink addPhysicsJS API
* Tweened is a Kinematic body moved by a FlashCC timeline tween.
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS</a>
* translates the timeline tween motion into linear and angular
* velocities applied appropriately to its corresponding kinematic
* <a href=../classes/b2Body.html>b2Body</a>
* in the
* <a href=../classes/b2World.html>b2World</a>
* simulation.
*
* @public
* @property m_type
* @type {int}
* @default b2bodyDef.type
*/
this.m_type = bodyDef.type;
if ( bodyDef.type === b2Body.b2_dynamicBody ) {
this.m_mass = 1.0;
this.m_invMass = 1.0;
}
else {
/**
* Body's mass.
*
* @public
* @property m_mass
* @type {float}
* @default 0.0
*/
this.m_mass = 0.0;
/**
* Body's inverse mass.
*
* @public
* @property m_invMass
* @type {float}
* @default 0.0
*/
this.m_invMass = 0.0;
}
/**
* Rotational inertia about the center of mass.
*
* @public
* @property m_I
* @type {float}
* @default 0.0
*/
this.m_I = 0.0;
/**
* Inverse rotational inertia about the center of mass.
*
* @public
* @property m_invI
* @type {float}
* @default 0.0
*/
this.m_invI = 0.0;
/**
* Application specific data.
*
* NOTE: Using the
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS framework</a>
* m_userData is managed for you extending either a
* <a href=http://www.createjs.com/docs/easeljs/classes/Container.html>createjs.container</a>
* or
* <a href=http://www.createjs.com/docs/easeljs/classes/MovieClip.html>createjs.movieClip</a>
* class.
*
* @public
* @property m_userData
* @type {*}
* @default b2bodyDef.userData
*/
this.m_userData = bodyDef.userData;
/**
* @public
* @property m_fixtureList
* @type {b2Fixture|null}
* @default null
*/
this.m_fixtureList = null;
/**
* @public
* @property m_fixtureCount
* @type {int}
* @default 0
*/
this.m_fixtureCount = 0;
/**
* @type {number}
*/
this.m_islandIndex = 0;
/*##if EXPORT_CONTROLLERS */
/**
* @public
* @property m_controllerList
* @type {b2ControllerEdge|null}
* @default null
*/
this.m_controllerList = null;
/**
* @public
* @property m_controllerCount
* @type {int}
* @default 0
*/
this.m_controllerCount = 0;
/*#end EXPORT_CONTROLLERS */
/**
* @public
* @property m_jointList
* @type {b2JointEdge|null}
* @default null
*/
this.m_jointList = null;
/**
* @public
* @property m_contactList
* @type {b2ContactEdge|null}
* @default null
*/
this.m_contactList = null;
/**
* The previous body in the world's 'bodies linked-list'.
*
* @public
* @property m_prev
* @type {b2Body|null}
* @default null
*/
this.m_prev = null;
/**
* The next body in the world's 'bodies linked-list'.
* Maybe null if 'this' body instance is the 'head' of the linked-list.
*
* @public
* @property m_next
* @type {b2Body|null}
* @default null
*/
this.m_next = null;
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ██ ██ ██ ██ //
// ██ ██ ██ //
// ██ █████ █████ █████ ████ ██ █████ █████ █████ █████ █████ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ ██ ██ ██ █████ ██ ██ ██ █████ ██ ██ ██ █████ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ ██ ██ ██ █████ ██ ██ ████ █████ ██ ██ █████ █████ //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
} p = b2Body.prototype; Box2D.b2Body = b2Body;
// STATIC CLASS PROPERTIES
// FLAGS - BODY TYPE
/**
* b2BodyDef base class default: unknown.
*
* @public
* @static @const
* @property b2_staticBody
* @type {binary}
* default -1
*/
b2Body.b2_unknown = -1;
/**
* Static: zero mass, zero velocity, may be manually moved.
*
* @public
* @static @const
* @property b2_staticBody
* @type {binary}
* default 0
*/
b2Body.b2_staticBody = 0;
/**
* Kinematic: zero mass, non-zero velocity set by user, moved by solver.
*
* @public
* @static @const
* @property b2_kinematicBody
* @type {binary}
* default 1
*/
b2Body.b2_kinematicBody = 1;
/**
* Dynamic: positive mass, non-zero velocity determined by forces, moved by solver.
*
* @public
* @static @const
* @property b2_dynamicBody
* @type {binary}
* default 2
*/
b2Body.b2_dynamicBody = 2;
/**
* @public
* @static @const
* @property b2_bulletBody
* @type {binary}
* default 2
*/
b2Body.b2_bulletBody = 3; // TODO_ERIN
// FLAGS
/**
* @public
* @static @const
* @property e_islandFlag
* @type {binary}
* default 0x0001
*/
b2Body.e_islandFlag = 0x0001;
/**
* @public
* @static @const
* @property e_awakeFlag
* @type {binary}
* default 0x0002
*/
b2Body.e_awakeFlag = 0x0002;
/**
* @public
* @static @const
* @property e_allowSleepFlag
* @type {binary}
* default 0x0004
*/
b2Body.e_allowSleepFlag = 0x0004;
/**
* @public
* @static @const
* @property e_bulletFlag
* @type {binary}
* default 0x0008
*/
b2Body.e_bulletFlag = 0x0008;
/**
* @public
* @static @const
* @property e_fixedRotationFlag
* @type {binary}
* default 0x0010
*/
b2Body.e_fixedRotationFlag = 0x0010;
/**
* @public
* @static @const
* @property e_activeFlag
* @type {binary}
* default 0x0020
*/
b2Body.e_activeFlag = 0x0020;
/**
* Object pool for memory management.
*/
b2Body._B2VEC2_POOL0 = new b2Vec2;
b2Body._B2VEC2_POOL1 = new b2Vec2;
b2Body._B2VEC2_POOL2 = new b2Vec2;
b2Body._B2MASS_DATA = new b2MassData;
b2Body._B2TRANSFORM_POOL0 = new b2Transform;
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ██ ██ ██ ██ ██ //
// ███ ███ ██ ██ ██ //
// ███████ █████ █████ █████ █████ █████ █████ //
// ██ █ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ █████ //
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ //
// ██ ██ █████ ████ ██ ██ █████ █████ █████ //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
// INSTANCE METHODS
/**
* Creates a fixture and attach it to 'this' body instance. Use this
* function if you need to set some fixture parameters, like
* friction. Otherwise you can create the fixture directly from
* a shape's Set(As)...() methods.
* If the density is non-zero, this function automatically
* updates the mass of the body. Contacts are not created until
* the next time step.
*
* Warning: This function is locked during callbacks.</br>
* NOTE: However using the
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS framework</a>
* event listeners you can do what every you want whenever you want and
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS</a>
* manages the locked world problems for you.
*
* @public
* @method createFixture
* @param {b2FixtureDef} def The fixture definition.
* @return {b2Fixture}
*/
p.createFixture = function (def) {
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) { b2Assert( !this.m_world.isLocked() ); }
/*#end EXPORT_ASSERTS */
if ( this.m_world.isLocked() ) { return null; }
var fixture = new b2Fixture();
fixture.create( this, def );
if ( this.m_flag_activeFlag ) { //TODO: this.m_flags & b2Body.e_activeFlag
var broadPhase = this.m_world.m_contactManager.m_broadPhase;
fixture.createProxies( broadPhase, this.m_xf );
}
fixture.m_next = this.m_fixtureList;
this.m_fixtureList = fixture;
++this.m_fixtureCount;
fixture.m_body = this;
// Adjust mass properties if needed.
if ( fixture.m_density > 0 ) {
this.resetMassData();
}
// Let the world know we have a new fixture. This will cause new contacts
// to be created at the beginning of the next time step.
this.m_world.m_flag_newFixture = true;
return fixture;
};
/**
* Creates a fixture from a shape and attach it to this body.
* This is a convenience function. Use
* <a href=../classes/b2FixtureDef.html>b2FixtureDef</a>
* if you need to set parameters like friction, restitution, user data, or
* filtering.
* If the density is non-zero, this function automatically
* updates the mass of the body.
*
* Warning: This function is locked during callbacks.</br>
* NOTE: However using the
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS framework</a>
* event listeners you can do what every you want whenever you want and
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS</a>
* manages the locked world problems for you.
*
* @public
* @method createFixtureShape
* @param {b2Shape} shape The shape to be cloned.
* @param {float} density The shape density (set to zero for static bodies).
* @return {b2Fixture}
*/
p.createFixtureShape = function (shape, density) {
density = density || 0;
var def = b2FixtureDef.POOL0;
def.shape = shape;
def.density = density;
return this.createFixture( def );
};
/**
* Destroy a fixture. This removes the fixture from the
* broad-phase and destroys all contacts associated with this
* fixture. This will automatically adjust the mass of the body
* if the body is dynamic and the fixture has positive density.
* All fixtures attached to a body are implicitly destroyed when
* the body is destroyed.
*
* Warning: This function is locked during callbacks.</br>
* NOTE: However using the
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS framework</a>
* event listeners you can do what every you want whenever you want and
* <a href=https://github.com/SmartArtsStudio/addPhysicsJS>addPhysicsJS</a>
* manages the locked world problems for you.
*
* @public
* @method destroyFixture
* @param {b2Fixture} fixture The fixture to be removed.
* @return {void}
*/
p.destroyFixture = function (fixture) {
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( !this.m_world.isLocked() );
}/*#*/
if ( this.m_world.isLocked() ) {
return;
}/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( fixture.m_body === this );
b2Assert( this.m_fixtureCount > 0 );
}/*#*/
// Remove the fixture from this body's singly linked list.
var node = this.m_fixtureList;
var ppF = null;
var found = false;
while (node !== null) {
if ( node === fixture ) {
if ( ppF ) {
ppF.m_next = fixture.m_next;
}
else {
this.m_fixtureList = fixture.m_next;
}
found = true;
break;
}
ppF = node;
node = node.m_next;
}
// You tried to remove a shape that is not attached to this body.
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( found );
}/*#*/
// Destroy any contacts associated with the fixture.
var edge = this.m_contactList;
while (edge) {
var c = edge.contact;
edge = edge.next;
var fixtureA = c.getFixtureA();
var fixtureB = c.getFixtureB();
if ( fixture === fixtureA || fixture === fixtureB ) {
// This destroys the contact and removes it from
// this body's contact list.
this.m_world.m_contactManager.destroy( c );
}
}
if ( this.m_flag_activeFlag ) { //TODO: m_flag_activeFlag -> this.m_flags & b2Body.e_activeFlag
var broadPhase = this.m_world.m_contactManager.m_broadPhase;
fixture.destroyProxies( broadPhase );
}
fixture.destroy();
fixture.m_body = null;
fixture.m_next = null;
--this.m_fixtureCount;
// Reset the mass data.
this.resetMassData();
};
/**
* Set the position of the body's origin and rotation.
* Manipulating a body's transform may cause non-physical
* behavior.
*
* Note: contacts are updated on the next call to
* <a href=../classes/b2World.html#method_step>b2World.step()</a>.
*
* @public
* @method setPositionAndAngle
* @param {b2Vec2} position The world position of the body's local origin.
* @param {float} angle The world rotation in radians.
* @return {void}
*/
p.setPositionAndAngle = function (position, angle) {
angle = angle || 0;
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) { b2Assert( !this.m_world.isLocked() ); }
/*#end EXPORT_ASSERTS */
if ( this.m_world.isLocked() ) { // TODO: (this.m_flags & b2World.e_locked) > 0
return;
}
var x = position.x;
var y = position.y;
if ( (this.m_xf.p.x === x) && (this.m_xf.p.y === y) && (this.m_xf.q.getAngle()) === angle ) {
return;
}
this.m_xf.q.set( angle );
this.m_xf.p.set( x, y );
/*#if EXPORT_PARTICLES */
this.m_xf0.copy( this.m_xf );
/*#end EXPORT_PARTICLES */
b2Transform.timesV2( this.m_xf, this.m_sweep.localCenter, this.m_sweep.c );
this.m_sweep.a = angle;
this.m_sweep.c0.copy( this.m_sweep.c );
this.m_sweep.a0 = angle;
var broadPhase = this.m_world.m_contactManager.m_broadPhase;
for (var f = this.m_fixtureList; f; f = f.m_next) {
f.synchronize( broadPhase, this.m_xf, this.m_xf );
}
};
/**
* Set the body transform for the body.
*
* @public
* @method setTransform
* @param {b2Transform} transform
* @return {void}
*/
// API ONLY
p.setTransform = function (transform) {
this.setPositionAndAngle(transform.position, transform.getAngle());
};
/**
* Get the body transform for the body's origin.
*
* @public
* @method getTransform
* @param {Object|b2Transform=} [out=b2Transform] reusable object.
* @return {Object|b2Transform} The world transform of the body's origin.
*/
p.getTransform = function ( out ) {
out = out || this.m_xf;
return out.copy(this.m_xf);
};
/**
* Get the world body origin position.
*
* @public
* @method getPosition
* @param {Object|b2Vec2=} [out=b2Vec2] reusable object.
* @return {Object|b2Vec2} out The world position of the body's origin.
*/
p.getPosition = function ( out ) {
out = out || this.m_xf.p;
return out.copy( this.m_xf.p );
};
/**
* @public
* @method setPosition
* @param {b2Vec2} position
* @return {void}
*/
p.setPosition = function ( position ) {
this.setPositionAndAngle( position, this.getAngle() );
};
/**
* Get the angle in radians.
*
* @public
* @method getAngle
* @return {float} The current world rotation angle in radians.
*/
p.getAngle = function () {
return this.m_sweep.a;
};
/**
* @public
* @method setAngle
* @param {float=} [angle=0.0] In radians.
* @return {void}
*/
p.setAngle = function (angle) {
angle = angle || 0.0;
this.setPositionAndAngle(this.getPosition(), angle);
};
/**
* Get the world body origin rotation.
*
* @public
* @method getRotation
* @param {Object|b2Transform=} [out=b2Transform] reusable object.
* @return {Object|b2Transform} out The current world rotation angle on a b2Transform.
*/
p.getRotation = function ( out ) {
out = out || this.m_xf.q;
return out.copy( this.m_xf.q );
};
/**
* Set the world body origin rotation.
*
* @public
* @method setRotation
* @param {float=} [rotation=0.0] In radians.
* @return {void}
*/
p.setRotation = function ( rotation ) {
rotation = rotation || 0.0;
this.setPositionAndAngle( this.getPosition(), rotation.getAngle() );
};
/**
* Get the world position of the center of mass.
*
* @public
* @method getWorldCenter
* @param {Object|b2Vec2=} [out=b2Vec2] reusable object
* @return {Object|b2Vec2} out
*/
p.getWorldCenter = function ( out ) {
out = out || this._sweep.c;
return out.copy( this.m_sweep.c );
};
/**
* Get the local position of the center of mass.
*
* @public
* @method getLocalCenter
* @param {Object|b2Vec2=} [out=b2Vec2] reusable object
* @return {Object|b2Vec2} out
*/
p.getLocalCenter = function ( out ) {
out = out || this._sweep.localCenter;
return out.copy( this.m_sweep.localCenter );
};
/**
* Set the linear velocity of the center of mass.
*
* @public
* @method setLinearVelocity
* @param {b2Vec2} velocity The new linear velocity of the center of mass.
* @return {void}
*/
p.setLinearVelocity = function (velocity) {
if (this.m_type == b2Body.b2_staticBody) { return; }
if ( b2Vec2.dot( velocity, velocity ) > 0 ) {
this.setAwake( true );
}
this.m_linearVelocity.copy( velocity );
};
/**
* Get the linear velocity of the center of mass.
*
* @public
* @method getLinearVelocity
* @param {Object|b2Vec2=} [out=b2Vec2] reusable object
* @return {Object|b2Vec2} out
*/
p.getLinearVelocity = function ( out ) {
out = out || this.m_linearVelocity;
return out.copy( this.m_linearVelocity );
};
/**
* Set the angular velocity.
*
* @public
* @method setAngularVelocity
* @param {float} omega The new angular velocity in radians/second.
* @return {void}
*/
p.setAngularVelocity = function (omega) {
omega = omega || 0;
if ( this.m_type === b2Body.b2_staticBody ) { return; }
if ( omega * omega > 0 ) {
this.setAwake( true );
}
this.m_angularVelocity = omega;
};
/**
* Get the angular velocity.
*
* @public
* @method getAngularVelocity
* @return {float} The angular velocity in radians/second.
*/
p.getAngularVelocity = function () {
return this.m_angularVelocity;
};
/**
* @public
* @method getDefinition
* @param {b2BodyDef} [bodyDef=b2BodyDef] reusable object
* @return {b2BodyDef} out
*/
//TODO: GetDefinition -> bitflags
p.getDefinition = function ( bodyDef ) {
bodyDef = bodyDef || new b2BodyDef;
bodyDef.type = this.getType();
bodyDef.allowSleep = this.m_flag_autoSleepFlag; // (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag;
bodyDef.angle = this.getAngle();
bodyDef.angularDamping = this.m_angularDamping;
bodyDef.gravityScale = this.m_gravityScale;
bodyDef.angularVelocity = this.m_angularVelocity;
bodyDef.fixedRotation = this.m_flag_fixedRotationFlag; // (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag
bodyDef.bullet = this.m_flag_bulletFlag; // (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag
bodyDef.awake = this.m_flag_awakeFlag; // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
bodyDef.linearDamping = this.m_linearDamping;
bodyDef.linearVelocity.copy( this.getLinearVelocity() );
bodyDef.position.copy( this.getPosition() );
bodyDef.userData = this.getUserData();
return bodyDef;
};
/**
* Apply a force at a world point. If the force is not applied
* at the center of mass, it will generate a torque and affect
* the angular velocity. This wakes up the body by default.
*
* @public
* @method applyForce
* @param {b2Vec2} force The world force vector, usually in Newtons (N).
* @param {b2Vec2} point The world position of the point of application.
* @param {boolean=} [wake=true] Also wake up the body.
* @return {void}
*/
p.applyForce = function ( force, point, wake ) {
wake = wake || true;
if ( this.m_type !== b2Body.b2_dynamicBody ) {
return;
}
if ( wake && !this.m_flag_awakeFlag ) { // wake && ((this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag)
this.setAwake( true );
}
// Don't accumulate a force if the body is sleeping.
if ( this.m_flag_awakeFlag ) { // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
this.m_force.x += force.x;
this.m_force.y += force.y;
this.m_torque += ((point.x - this.m_sweep.c.x) * force.y - (point.y - this.m_sweep.c.y) * force.x);
}
};
/**
* Apply a force to the center of mass. This wakes up the body by default.
*
* @public
* @method applyForce
* @param {b2Vec2} force The world force vector, usually in Newtons (N).
* @param {boolean=} [wake=true] Also wake up the body.
* @return {void}
*/
p.applyForceToCenter = function ( force, wake ) {
wake = wake || true;
if ( this.m_type !== b2Body.b2_dynamicBody ) {
return;
}
if ( wake && !this.m_flag_awakeFlag ) { // wake && ((this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag)
this.setAwake( true );
}
// Don't accumulate a force if the body is sleeping.
if ( this.m_flag_awakeFlag ) { // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
this.m_force.x += force.x;
this.m_force.y += force.y;
}
};
/**
* Apply a torque. This affects the angular velocity without
* affecting the linear velocity of the center of mass. This
* wakes up the body by default.
*
* @public
* @method applyTorque
* @param {float} [torque=0.0] About the z-axis (out of the screen), usually in N-m.
* @param {boolean=} [wake=true] Also wake up the body.
* @return {void}
*/
p.applyTorque = function ( torque, wake ) {
torque = torque || 0.0;
if (this.m_type != b2Body.b2_dynamicBody) {
return;
}
if ( wake && !this.m_flag_awakeFlag ) { // wake && ((this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag)
this.setAwake( true );
}
// Don't accumulate a force if the body is sleeping.
if ( this.m_flag_awakeFlag ) { // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
this.m_torque += torque;
}
};
/**
* Apply an impulse at a point. This immediately modifies the
* velocity. It also modifies the angular velocity if the point
* of application is not at the center of mass. This wakes up
* the body by default.
*
* @public
* @method applyImpulse
* @param {float} impulse The world impulse vector, usually in N-seconds or kg-m/s.
* @param {float} point The world position of the point of application.
* @param {boolean=} [wake=true] Also wake up the body.
* @return {void}
*/
p.applyLinearImpulse = function ( impulse, point, wake ) {
wake = wake || true;
if (this.m_type != b2Body.b2_dynamicBody) {
return;
}
if ( wake && !this.m_flag_awakeFlag ) { // wake && ((this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag)
this.setAwake( true );
}
// Don't accumulate a force if the body is sleeping.
if ( this.m_flag_awakeFlag ) { // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
this.m_linearVelocity.x += this.m_invMass * impulse.x;
this.m_linearVelocity.y += this.m_invMass * impulse.y;
this.m_angularVelocity += this.m_invI * ((point.x - this.m_sweep.c.x) * impulse.y - (point.y - this.m_sweep.c.y) * impulse.x);
}
};
/**
* Apply an impulse at a point. This immediately modifies the
* velocity. It also modifies the angular velocity if the point
* of application is not at the center of mass. This wakes up
* the body by default.
*
* @public
* @method applyImpulse
* @param {float} impulse The world impulse vector, usually in N-seconds or kg-m/s.
* @param {boolean=} [wake=true] Also wake up the body.
* @return {void}
*/
p.applyAngularImpulse = function ( impulse, wake ) {
wake = wake || true;
if (this.m_type != b2Body.b2_dynamicBody) {
return;
}
if ( wake && !this.m_flag_awakeFlag ) { // wake && ((this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag)
this.setAwake( true );
}
// Don't accumulate a force if the body is sleeping.
if ( this.m_flag_awakeFlag ) { // (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag
this.m_angularVelocity += this.m_invI * impulse;
}
};
/**
* Get the total mass of the body.
*
* @public
* @method getMass
* @return {float} The mass, usually in kilograms (kg).
*/
p.getMass = function () {
return this.m_mass;
};
/**
* Get the rotational inertia of the body about the local origin.
*
* @public
* @method getInertia
* @return {float} The rotational inertia, usually in kg-m^2.
*/
p.getInertia = function () {
return this.m_I + this.m_mass * b2Vec2.dot( this.m_sweep.localCenter, this.m_sweep.localCenter );
};
/**
* Get the mass data of the body.
*
* @public
* @method getMassData
* @param {b2MassData} massData
* @return {b2MassData} massData Containing the mass, inertia and center of the body.
*/
p.getMassData = function (massData) {
massData.mass = this.m_mass;
massData.I = this.m_I + this.m_mass * b2Vec2.dot( this.m_sweep.localCenter, this.m_sweep.localCenter );
massData.center.copy( this.m_sweep.localCenter );
return massData;
};
/**
* Set the mass properties to override the mass properties of the fixtures.
* Note that this changes the center of mass position.
* Note that creating or destroying fixtures can also alter the mass.
* This function has no effect if the body isn't dynamic.
*
* @public
* @method setMassData
* @param {b2MassData} massData The mass properties.
* @return {void}
*/
p.setMassData = function (massData) {
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( !this.m_world.isLocked() );
}/*#*/
if ( this.m_world.isLocked() ) {
return;
}
if ( this.m_type !== b2Body.b2_dynamicBody ) {
return;
}
this.m_invMass = 0;
this.m_I = 0;
this.m_invI = 0;
this.m_mass = massData.mass;
if ( this.m_mass <= 0 ) {
this.m_mass = 1;
}
this.m_invMass = 1 / this.m_mass;
if ( massData.I > 0 && !this.m_flag_fixedRotationFlag ) { // (massData.I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0)
this.m_I = massData.I - this.m_mass * b2Vec2.dot( massData.center, massData.center );
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( this.m_I > 0 );
}/*#*/
this.m_invI = 1 / this.m_I;
}
// Move center of mass.
var oldCenter = b2Body._B2VEC2_POOL0.copy( this.m_sweep.c );
this.m_sweep.localCenter.copy( massData.center );
b2Transform.timesV2( this.m_xf, this.m_sweep.localCenter, this.m_sweep.c );
this.m_sweep.c0.copy( this.m_sweep.c );
// Update center of mass velocity.
b2Vec2.vPlusCrossFV( this.m_linearVelocity, this.m_angularVelocity, b2Vec2.subtract( this.m_sweep.c, oldCenter, b2Body._B2VEC2_POOL0 ), this.m_linearVelocity );
};
/**
* This resets the mass properties to the sum of the mass
* properties of the fixtures. This normally does not need to be
* called unless you called SetMassData to override the mass and
* you later want to reset the mass.
*
* @public
* @method resetMassData
* @return {void}
*/
p.resetMassData = function () {
// Compute mass data from shapes. Each shape has its own density.
this.m_mass = 0;
this.m_invMass = 0;
this.m_I = 0;
this.m_invI = 0;
this.m_sweep.localCenter.setZero();
// Static and kinematic bodies have zero mass.
if ( this.m_type === b2Body.b2_staticBody || this.m_type === b2Body.b2_kinematicBody ) {
this.m_sweep.c0.copy( this.m_xf.p );
this.m_sweep.c.copy( this.m_xf.p );
this.m_sweep.a0 = this.m_sweep.a;
return;
}
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( this.m_type === b2Body.b2_dynamicBody );
}
/*#end EXPORT_ASSERTS */
// Accumulate mass over all fixtures.
var localCenter = b2Body._B2VEC2_POOL1.setZero();
for (var f = this.m_fixtureList; f; f = f.m_next) {
if ( f.m_density === 0 ) {
continue;
}
var massData = f.getMassData( b2Body._B2MASS_DATA );
this.m_mass += massData.mass;
localCenter.x += massData.center.x * massData.mass;
localCenter.y += massData.center.y * massData.mass;
this.m_I += massData.I;
}
// Compute center of mass.
if ( this.m_mass > 0 ) {
this.m_invMass = 1 / this.m_mass;
localCenter.x *= this.m_invMass;
localCenter.y *= this.m_invMass;
}
else {
// Force all dynamic bodies to have a positive mass.
this.m_mass = 1;
this.m_invMass = 1;
}
if ( this.m_I > 0 && !this.m_flag_fixedRotationFlag ) { // (this.m_I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0)
// Center the inertia about the center of mass.
this.m_I -= this.m_mass * b2Vec2.dot( localCenter, localCenter );
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( this.m_I > 0 );
}/*#*/
this.m_invI = 1 / this.m_I;
}
else {
this.m_I = 0;
this.m_invI = 0;
}
// Move center of mass.
var oldCenter = b2Body._B2VEC2_POOL2.copy( this.m_sweep.c );
this.m_sweep.localCenter.copy( localCenter );
b2Transform.timesV2( this.m_xf, this.m_sweep.localCenter, this.m_sweep.c );
this.m_sweep.c0.copy( this.m_sweep.c );
// Update center of mass velocity.
b2Vec2.vPlusCrossFV( this.m_linearVelocity, this.m_angularVelocity, b2Vec2.subtract( this.m_sweep.c, oldCenter, b2Body._B2VEC2_POOL0 ), this.m_linearVelocity );
};
/**
* Get the world coordinates of a point given the local coordinates.
*
* @public
* @method getWorldPoint
* @param {b2Vec2} localPoint A point on the body measured relative the the body's origin.
* @param {Object|b2Vec2=} [out=b2Vec2] Reusable object.
* @return {Object|b2Vec2} out A point expressed in world coordinates.
*/
p.getWorldPoint = function ( localPoint, out ) {
return b2Transform.timesV2( this.m_xf, localPoint, out );
};
/**
* Get the world coordinates of a vector given the local coordinates.
*
* @public
* @method getWorldVector
* @param {b2Vec2} localVector A vector fixed in the body.
* @param {Object|b2Vec2=} [out=b2Vec2] Reusable object.
* @return {Object|b2Vec2} out Expressed in world coordinates.
*/
p.getWorldVector = function ( localVector, out ) {
return b2Rot.timesV2( this.m_xf.q, localVector, out );
};
/**
* Gets a local point relative to the body's origin given a world point.
*
* @public
* @method getLocalPoint
* @param {b2Vec2} worldPoint A point in world coordinates.
* @param {Object|b2Vec2=} [out=b2Vec2] Reusable object.
* @return {Object|b2Vec2} out The corresponding local point relative to the body's origin.
*/
p.getLocalPoint = function ( worldPoint, out ) {
return b2Transform.tTimesV2( this.m_xf, worldPoint, out );
};
/**
* Gets a local vector given a world vector.
*
* @public
* @method getLocalVector
* @param {b2Vec2} worldVector A vector in world coordinates.
* @param {Object|b2Vec2=} [out=b2Vec2] Reusable object.
* @return {Object|b2Vec2} out The corresponding local vector.
*/
p.getLocalVector = function ( worldVector, out ) {
return b2Rot.invRotV2( this.m_xf.q, worldVector, out );
};
/**
* Get the world linear velocity of a world point attached to this body.
*
* @public
* @method getLinearVelocityFromWorldPoint
* @param {b2Vec2} worldPoint A point in world coordinates.
* @param {b2Vec2|Object=} [out=b2Vec2] Reusable vector object.
* @return {b2Vec2|Object} The world velocity of a point.
*/
p.getLinearVelocityFromWorldPoint = function (worldPoint, out) {
out = out || b2Body._B2VEC2_POOL0;
out.x = this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y);
out.y = this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x);
return out;
};
/**
* Get the world velocity of a local point.
*
* @public
* @method getLinearVelocityFromLocalPoint
* @param {b2Vec2} localPoint A point in local coordinates
* @param {b2Vec2|Object=} [out=b2Vec2] Reusable vector object.
* @return {b2Vec2|Object} The world velocity of a point.
*/
p.getLinearVelocityFromLocalPoint = function ( localPoint, out ) {
return this.getLinearVelocityFromWorldPoint( this.getWorldPoint( localPoint, out ), out );
};
/**
* Get the linear damping of the body.
*
* @public
* @method getLinearDamping
* @return {float}
*/
p.getLinearDamping = function () {
return this.m_linearDamping;
};
/**
* Set the linear damping of the body.
*
* @public
* @method setLinearDamping
* @param {float} [damping=0.0]
* @return {void}
*/
p.setLinearDamping = function (damping) {
damping = damping || 0.0;
this.m_linearDamping = damping;
};
/**
* @public
* @method getAngularDamping
* @return {float}
*/
p.getAngularDamping = function () {
return this.m_angularDamping;
};
/**
* Get the angular damping of the body.
*
* @public
* @method setAngularDamping
* @param {float} [angularDamping=0.0]
* @return {void}
*/
p.setAngularDamping = function (angularDamping) {
angularDamping = angularDamping || 0.0;
this.m_angularDamping = angularDamping;
};
/**
* Get the gravity scale of the body.
*
* @public
* @method getGravityScale
* @return {float}
*/
p.getGravityScale = function () {
return this.m_gravityScale;
};
/**
* Get the gravity scale of the body.
*
* @public
* @method setAngularDamping
* @param {float} scale
* @return {void}
*/
p.setAngularDamping = function ( scale ) {
this.m_gravityScale = scale;
};
/**
* Set the type of this body. This may alter the mass and velocity.
*
* @public
* @method setType
* @param {int} type
* @return {void}
*/
p.setType = function ( type ) {
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) {
b2Assert( !this.m_world.isLocked() );
}/*#*/
if ( this.m_world.isLocked() ) {
return;
}
if ( this.m_type === type ) {
return;
}
this.m_type = type;
this.resetMassData();
if ( this.m_type === b2Body.b2_staticBody ) {
this.m_linearVelocity.setZero();
this.m_angularVelocity = 0;
this.m_sweep.a0 = this.m_sweep.a;
this.m_sweep.c0.copy( this.m_sweep.c );
this.synchronizeFixtures();
}
this.setAwake( true );
this.m_force.setZero();
this.m_torque = 0;
// Delete the attached contacts.
/** b2ContactEdge */ var ce = this.m_contactList;
while (ce) {
/** b2ContactEdge */ var ce0 = ce;
ce = ce.next;
this.m_world.m_contactManager.destroy( ce0.contact );
}
this.m_contactList = null;
// Touch the proxies so that new contacts will be created (when appropriate)
/** b2BroadPhase */ var broadPhase = this.m_world.m_contactManager.m_broadPhase;
for (/** b2Fixture */ var f = this.m_fixtureList; f; f = f.m_next) {
var proxyCount = f.m_proxyCount;
for (var i = 0; i < proxyCount; ++i) {
broadPhase.touchProxy( f.m_proxies[i].proxy );
}
}
};
/**
* Get the type of this body.
*
* @public
* @method getType
* @return {int} body type
*/
p.getType = function () {
return this.m_type;
};
/**
* Should this body be treated like a bullet for continuous collision detection?
*
* @public
* @method setBullet
* @param {boolean} flag
* @return {void}
*/
p.setBullet = function ( flag ) {
// TODO SetBullet by bitmask
// if (flag) {
// this.m_flags |= b2Body.e_bulletFlag;
// }
// else {
// this.m_flags &= ~b2Body.e_bulletFlag;
// }
this.m_flag_bulletFlag = flag;
};
/**
* Is this body treated like a bullet for continuous collision detection?
*
* @public
* @method isBullet
* @return {boolean}
*/
p.isBullet = function () {
// TODO IsBullet by bitmask
// return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag;
return this.m_flag_bulletFlag;
};
/**
* You can disable sleeping on this body. If you disable sleeping,
* the body will be woken.
*
* @public
* @method setSleepingAllowed
* @return {boolean}
*/
p.setSleepingAllowed = function ( flag ) {
// TODO SetSleepingAllowed by bitmask
// if (flag) {
// this.m_flags |= b2Body.e_allowSleepFlag;
// }
// else {
// this.m_flags &= ~b2Body.e_allowSleepFlag;
// this.setAwake(true);
// }
if ( flag ) {
this.m_flag_autoSleepFlag = true;
}
else {
this.m_flag_autoSleepFlag = false;
this.setAwake( true );
}
};
/**
* Set the sleep state of the body. A sleeping body has very low CPU cost.
*
* @public
* @method setAwake
* @param {boolean} flag Set to TRUE to wake the body,
* FALSE to put it to sleep.
* @return {void}
*/
p.setAwake = function ( flag ) {
// TODO SetAwake by bitmask
// if (flag) {
// this.m_flags |= b2Body.e_awakeFlag;
// this.m_sleepTime = 0;
// }
// else {
// this.m_flags &= ~b2Body.e_awakeFlag;
// this.m_sleepTime = 0;
// this.m_linearVelocity.setZero();
// this.m_angularVelocity = 0;
// this.m_force.setZero();
// this.m_torque = 0;
// }
if ( flag ) {
if ( !this.m_flag_awakeFlag ) {
this.m_flag_awakeFlag = true;
this.m_sleepTime = 0;
}
}
else {
this.m_flag_awakeFlag = false;
this.m_sleepTime = 0;
this.m_linearVelocity.setZero();
this.m_angularVelocity = 0;
this.m_force.setZero();
this.m_torque = 0;
}
};
/**
* Get the sleeping state of this body.
*
* @public
* @method isAwake
* @return {boolean}
*/
p.isAwake = function () {
// TODO IsAwake by bitmask
// return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag;
return this.m_flag_awakeFlag;
};
/**
* Set this body to have fixed rotation. This causes the mass to
* be reset.
*
* @public
* @method setFixedRotation
* @return {boolean} true if the body is awake.
*/
p.setFixedRotation = function ( fixed ) {
// TODO SetFixedRotation by bitmask
// if (fixed) {
// this.m_flags |= b2Body.e_fixedRotationFlag;
// }
// else {
// this.m_flags &= ~b2Body.e_fixedRotationFlag;
// }
var status = this.m_flag_fixedRotationFlag;
if ( status === fixed ) {
return;
}
this.m_flag_fixedRotationFlag = fixed;
this.m_angularVelocity = 0;
this.resetMassData();
};
/**
* Does this body have fixed rotation?
*
* @public
* @method isFixedRotation
* @return {boolean}
*/
p.isFixedRotation = function () {
// TODO IsFixedRotation by bitmask
// return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag;
return this.m_flag_fixedRotationFlag;
};
/**
* Set the active state of the body.
*
* An inactive body is not simulated and cannot be collided with
* or woken up.
* If you pass a flag of true, all fixtures will be added to the
* broad-phase.
* If you pass a flag of false, all fixtures will be removed from
* the broad-phase and all contacts will be destroyed.
*
* Fixtures and joints are otherwise unaffected. You may continue
* to create/destroy fixtures and joints on inactive bodies.
* Fixtures on an inactive body are implicitly inactive and will
* not participate in collisions, ray-casts, or queries.
*
* Joints connected to an inactive body are implicitly inactive.
* An inactive body is still owned by a
* <a href=../classes/b2World.html>b2World</a>
* object and remains in the body list.
*
* @public
* @method setActive
* @param {boolean} active
* @return {void}
*/
p.setActive = function ( active ) {
/*##if EXPORT_ASSERTS */
if ( b2Settings.ASSERTS_ENABLED ) { b2Assert( !this.m_world.isLocked() ); }
/*#end EXPORT_ASSERTS */
if ( active === this.isActive() ) { return; }
var broadPhase;
if ( active ) {
this.m_flag_activeFlag = true; // this.m_flags |= b2Body.e_activeFlag;
// Create all proxies.
broadPhase = this.m_world.m_contactManager.m_broadPhase;
for (var f = this.m_fixtureList; f; f = f.m_next) {
f.createProxies( broadPhase, this.m_xf );
}
// Contacts are created the next time step.
}
else {
this.m_flag_activeFlag = false; // this.m_flags &= ~b2Body.e_activeFlag;
// Destroy all proxies.
broadPhase = this.m_world.m_contactManager.m_broadPhase;
for (var f = this.m_fixtureList; f; f = f.m_next) {
f.destroyProxies( broadPhase );
}
// Destroy the attached contacts.
var ce = this.m_contactList;
while (ce) {
var ce0 = ce;
ce = ce.next;
this.m_world.m_contactManager.destroy( ce0.contact );
}
this.m_contactList = null;
}
};
/**
* Get the active state of the body.
*
* @public
* @method isActive
* @return {boolean}
*/
p.isActive = function () {
// TODO IsActive by bitmask
// return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag;
return this.m_flag_activeFlag;
};
/**
* Is this body allowed to sleep
*
* @public
* @method isSleepingAllowed
* @return {boolean}
*/
p.isSleepingAllowed = function () {
// TODO IsSleepingAllowed by bitmask
// return (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag;
return this.m_flag_autoSleepFlag;
};
/**
* Get the list of all fixtures attached to this body.
*
* @public
* @method getFixtureList
* @return {b2Fixture}
*/
p.getFixtureList = function () {
return this.m_fixtureList;
};
/**
* Get the list of all joints attached to this body.
*
* @public
* @method getJointList
* @return {b2JointEdge}
*/
p.getJointList = function () {
return this.m_jointList;
};
/**
* Get the list of all contacts attached to this body.
*
* Warning: This list changes during the time step and you may
* miss some collisions if you don't use
* <a href=../classes/b2ContactListener.html>b2ContactListener</a>.
*
* @public
* @method getContactList
* @return {b2ContactEdge}
*/
p.getContactList = function () {
return this.m_contactList;
};
/**
* Get the next body in the world's body list.
*
* @public
* @method getNext
* @return {b2Body}
*/
p.getNext = function () {
return this.m_next;
};
/**
* Get the user data reference that was provided by the body definition.
*
* @public
* @method getUserData
* @return {*}
*/
p.getUserData = function () {
return this.m_userData;
};
/**
* Set the user data. Use this to store your application specific data.
*
* @public
* @method setUserData
* @param {*} data
* @return {void}
*/
p.setUserData = function (data) {
this.m_userData = data;
};
/**
* Get the parent world of this body.
*
* @public
* @method getWorld
* @return {b2World}
*/
p.getWorld = function () {
return this.m_world;
};
/**
* @public
* @method synchronizeFixtures
* @return {void}
*/
p.synchronizeFixtures = function () {
var xf1 = b2Body._B2TRANSFORM_POOL0;
xf1.q.setAngle( this.m_sweep.a0 );
b2Rot.timesV2( xf1.q, this.m_sweep.localCenter, xf1.p );
b2Vec2.subtract( this.m_sweep.c0, xf1.p, xf1.p );
var broadPhase = this.m_world.m_contactManager.m_broadPhase;
for (var f = this.m_fixtureList; f; f = f.m_next) {
f.synchronize( broadPhase, xf1, this.m_xf );
}
};
/**
* @public
* @method synchronizeTransform
* @return {void}
*/
p.synchronizeTransform = function () {
this.m_xf.q.setAngle( this.m_sweep.a );
b2Rot.timesV2( this.m_xf.q, this.m_sweep.localCenter, this.m_xf.p );
b2Vec2.subtract( this.m_sweep.c, this.m_xf.p, this.m_xf.p );
};
/**
* This is used to prevent connected bodies from colliding.
* It may lie, depending on the collideConnected flag.
*
* @public
* @method shouldCollide
* @param {b2Body} other <a href=../classes/b2Body.html>b2Body</a>
* @return {boolean}
*/
p.shouldCollide = function (other) {
// At least one body should be dynamic.
if ( this.m_type !== b2Body.b2_dynamicBody && other.m_type !== b2Body.b2_dynamicBody ) {
return false;
}
// Does a joint prevent collision?
for (var jn = this.m_jointList; jn; jn = jn.next) {
if ( jn.other === other ) {
if ( !jn.joint.m_collideConnected ) {
return false;
}
}
}
return true;
};
/**
* Advance to the new safe time. This doesn't sync the broad-phase.
*
* @public
* @method advance
* @param {number} alpha The original start time.
* @return {void}
*/
p.advance = function (alpha) {
// Advance to the new safe time. This doesn't sync the broad-phase.
this.m_sweep.advance( alpha );
this.m_sweep.c.copy( this.m_sweep.c0 );
this.m_sweep.a = this.m_sweep.a0;
this.m_xf.q.setAngle( this.m_sweep.a );
b2Rot.timesV2( this.m_xf.q, this.m_sweep.localCenter, this.m_xf.p );
b2Vec2.subtract( this.m_sweep.c, this.m_xf.p, this.m_xf.p );
};
/*##if EXPORT_CONTROLLERS */
/**
* See
* <a href=../classes/b2Controller.html>b2Controller</a>
* list.
*
* @public
* @method getControllerList
* @return {b2ControllerEdge}
*/
p.getControllerList = function () {
return this.m_controllerList;
};
/**
* See
* <a href=../classes/b2Controller.html>b2Controller</a>
* list.
*
* @public
* @method getControllerCount
* @return {int}
*/
p.getControllerCount = function () {
return this.m_controllerCount;
};
/*#end EXPORT_CONTROLLERS */
/**
* Splits a body into two bodies.
*
* @public
* @method split
* @param {b2QueryCallback} callback
* @return {b2Body}
*/
p.split = function (callback) {
var linearVelocity = this.getLinearVelocity().clone();
var angularVelocity = this.getAngularVelocity();
var center = this.getWorldCenter();
var body1 = this;
var body2 = this.m_world.createBody(this.getDefinition());
var prev;
for (var f = body1.m_fixtureList; f;) {
if (callback(f)) {
var next = f.m_next;
if (prev) {
prev.m_next = next;
}
else {
body1.m_fixtureList = next;
}
body1.m_fixtureCount--;
f.m_next = body2.m_fixtureList;
body2.m_fixtureList = f;
body2.m_fixtureCount++;
f.m_body = body2;
f = next;
}
else {
prev = f;
f = f.m_next;
}
}
body1.resetMassData();
body2.resetMassData();
var center1 = body1.getWorldCenter();
var center2 = body2.getWorldCenter();
var velocity1 = b2Vec2.add(
linearVelocity,
b2Vec2.numTimes(angularVelocity, b2Vec2.subtract(center1, center))
);
var velocity2 = b2Vec2.add(
linearVelocity,
b2Vec2.numTimes(angularVelocity, b2Vec2.subtract(center2, center))
);
body1.setLinearVelocity(velocity1);
body2.setLinearVelocity(velocity2);
body1.setAngularVelocity(angularVelocity);
body2.setAngularVelocity(angularVelocity);
body1.synchronizeFixtures();
body2.synchronizeFixtures();
return body2;
};
/**
* Merges two bodies into one.
*
* @public
* @method merge
* @param {b2Body} other <a href=../classes/b2Body.html>b2Body</a>
* @return {void}
*/
p.merge = function (other) {
var f;
var body1 = this;
var body2 = other;
for (f = other.m_fixtureList; f;) {
var next = f.m_next;
other.m_fixtureCount--;
f.m_next = this.m_fixtureList;
this.m_fixtureList = f;
this.m_fixtureCount++;
f.m_body = body2;
f = next;
}
body1.m_fixtureCount = 0;
var center1 = body1.getWorldCenter();
var center2 = body2.getWorldCenter();
var velocity1 = body1.getLinearVelocity().clone();
var velocity2 = body2.getLinearVelocity().clone();
var angular1 = body1.getAngularVelocity();
var angular = body2.getAngularVelocity();
body1.resetMassData();
this.synchronizeFixtures();
};