UNPKG

@awayfl/awayfl-player

Version:

Flash Player emulator for executing SWF files (published for FP versions 6 and up) in javascript

1,040 lines (1,035 loc) 40.5 kB
import { b2Math, b2Vec2, b2Transform, b2Sweep } from '../Common/Math'; import { b2Settings } from '../Common/b2Settings'; import { b2BodyDef } from './b2BodyDef'; import { b2Fixture } from './b2Fixture'; import { b2FixtureDef } from './b2FixtureDef'; import { b2World } from './b2World'; /** * A rigid body. */ var b2Body = /** @class */ (function () { //--------------- Internals Below ------------------- // Constructor /** * @private */ function b2Body(bd, world) { //b2Settings.b2Assert(world.IsLocked() == false); this.__fast__ = true; this.m_xf = new b2Transform(); // the body origin transform this.m_sweep = new b2Sweep(); // the swept motion for CCD this.m_linearVelocity = new b2Vec2(); this.m_force = new b2Vec2(); //b2Settings.b2Assert(bd.position.IsValid()); //b2Settings.b2Assert(bd.linearVelocity.IsValid()); //b2Settings.b2Assert(b2Math.b2IsValid(bd.angle)); //b2Settings.b2Assert(b2Math.b2IsValid(bd.angularVelocity)); //b2Settings.b2Assert(b2Math.b2IsValid(bd.inertiaScale) && bd.inertiaScale >= 0.0); //b2Settings.b2Assert(b2Math.b2IsValid(bd.angularDamping) && bd.angularDamping >= 0.0); //b2Settings.b2Assert(b2Math.b2IsValid(bd.linearDamping) && bd.linearDamping >= 0.0); this.m_flags = 0; if (bd.bullet) { this.m_flags |= b2Body.e_bulletFlag; } if (bd.fixedRotation) { this.m_flags |= b2Body.e_fixedRotationFlag; } if (bd.allowSleep) { this.m_flags |= b2Body.e_allowSleepFlag; } if (bd.awake) { this.m_flags |= b2Body.e_awakeFlag; } if (bd.active) { this.m_flags |= b2Body.e_activeFlag; } this.m_world = world; this.m_xf.position.SetV(bd.position); this.m_xf.R.Set(bd.angle); this.m_sweep.localCenter.SetZero(); this.m_sweep.t0 = 1.0; this.m_sweep.a0 = this.m_sweep.a = bd.angle; //this.m_sweep.c0 = this.m_sweep.c = b2Mul(this.m_xf, this.m_sweep.localCenter); //b2MulMV(this.m_xf.R, this.m_sweep.localCenter); var tMat = this.m_xf.R; var tVec = this.m_sweep.localCenter; // (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y) this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y); // (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y) this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y); //return T.position + b2Mul(T.R, v); this.m_sweep.c.x += this.m_xf.position.x; this.m_sweep.c.y += this.m_xf.position.y; //this.m_sweep.c0 = this.m_sweep.c this.m_sweep.c0.SetV(this.m_sweep.c); this.m_jointList = null; this.m_controllerList = null; this.m_contactList = null; this.m_controllerCount = 0; this.m_prev = null; this.m_next = null; this.m_linearVelocity.SetV(bd.linearVelocity); this.m_angularVelocity = bd.angularVelocity; this.m_linearDamping = bd.linearDamping; this.m_angularDamping = bd.angularDamping; this.m_force.Set(0.0, 0.0); this.m_torque = 0.0; this.m_sleepTime = 0.0; this.m_type = bd.type; if (this.m_type == b2Body.b2_dynamicBody) { this.m_mass = 1.0; this.m_invMass = 1.0; } else { this.m_mass = 0.0; this.m_invMass = 0.0; } this.m_I = 0.0; this.m_invI = 0.0; this.m_inertiaScale = bd.inertiaScale; this.m_userData = bd.userData; this.m_fixtureList = null; this.m_fixtureCount = 0; } b2Body.prototype.connectEdges = function (s1, s2, angle1) { var angle2 = Math.atan2(s2.GetDirectionVector().y, s2.GetDirectionVector().x); var coreOffset = Math.tan((angle2 - angle1) * 0.5); var core = b2Math.MulFV(coreOffset, s2.GetDirectionVector()); core = b2Math.SubtractVV(core, s2.GetNormalVector()); core = b2Math.MulFV(b2Settings.b2_toiSlop, core); core = b2Math.AddVV(core, s2.GetVertex1()); var cornerDir = b2Math.AddVV(s1.GetDirectionVector(), s2.GetDirectionVector()); cornerDir.Normalize(); var convex = b2Math.Dot(s1.GetDirectionVector(), s2.GetNormalVector()) > 0.0; s1.SetNextEdge(s2, core, cornerDir, convex); s2.SetPrevEdge(s1, core, cornerDir, convex); return angle2; }; /** * Creates a fixture and attach it to this body. Use this function if you need * to set some fixture parameters, like friction. Otherwise you can create the * fixture directly from a shape. * If the density is non-zero, this function automatically updates the mass of the body. * Contacts are not created until the next time step. * @param fixtureDef the fixture definition. * @warning This function is locked during callbacks. */ b2Body.prototype.CreateFixture = function (def) { //b2Settings.b2Assert(this.m_world.IsLocked() == false); if (this.m_world.IsLocked() == true) { return null; } // TODO: Decide on a better place to initialize edgeShapes. (b2Shape::Create() can't // return more than one shape to add to parent body... maybe it should add // shapes directly to the body instead of returning them?) /* if (def.type == b2Shape.e_edgeShape) { var edgeDef: b2EdgeChainDef = def as b2EdgeChainDef; var v1: b2Vec2; var v2: b2Vec2; var i: int; if (edgeDef.isALoop) { v1 = edgeDef.vertices[edgeDef.vertexCount-1]; i = 0; } else { v1 = edgeDef.vertices[0]; i = 1; } var s0: b2EdgeShape = null; var s1: b2EdgeShape = null; var s2: b2EdgeShape = null; var angle: number = 0.0; for (; i < edgeDef.vertexCount; i++) { v2 = edgeDef.vertices[i]; //void* mem = this.m_world->m_blockAllocator.Allocate(sizeof(b2EdgeShape)); s2 = new b2EdgeShape(v1, v2, def); s2.this.m_next = m_shapeList; m_shapeList = s2; ++m_shapeCount; s2.m_body = this; s2.CreateProxy(this.m_world.m_broadPhase, this.m_xf); s2.UpdateSweepRadius(this.m_sweep.localCenter); if (s1 == null) { s0 = s2; angle = Math.atan2(s2.GetDirectionVector().y, s2.GetDirectionVector().x); } else { angle = connectEdges(s1, s2, angle); } s1 = s2; v1 = v2; } if (edgeDef.isALoop) connectEdges(s1, s0, angle); return s0; }*/ var fixture = new b2Fixture(); fixture.Create(this, this.m_xf, def); if (this.m_flags & b2Body.e_activeFlag) { var broadPhase = this.m_world.m_contactManager.m_broadPhase; fixture.CreateProxy(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.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_flags |= b2World.e_newFixture; return fixture; }; /** * Creates a fixture from a shape and attach it to this body. * This is a convenience function. Use b2FixtureDef if you need to set parameters * like friction, restitution, user data, or filtering. * This function automatically updates the mass of the body. * @param shape the shape to be cloned. * @param density the shape density (set to zero for static bodies). * @warning This function is locked during callbacks. */ b2Body.prototype.CreateFixture2 = function (shape, density) { if (density === void 0) { density = 0.0; } var def = new b2FixtureDef(); 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. * @param fixture the fixture to be removed. * @warning This function is locked during callbacks. */ b2Body.prototype.DestroyFixture = function (fixture) { //b2Settings.b2Assert(this.m_world.IsLocked() == false); if (this.m_world.IsLocked() == true) { return; } //b2Settings.b2Assert(this.m_fixtureCount > 0); //b2Fixture** node = &this.m_fixtureList; var node = this.m_fixtureList; var ppF = null; // Fix pointer-pointer stuff var found = false; while (node != null) { if (node == fixture) { if (ppF) ppF.m_next = fixture.m_next; else this.m_fixtureList = fixture.m_next; //node = fixture.this.m_next; found = true; break; } ppF = node; node = node.m_next; } // You tried to remove a shape that is not attached to this body. //b2Settings.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 destros the contact and removes it from // this body's contact list this.m_world.m_contactManager.Destroy(c); } } if (this.m_flags & b2Body.e_activeFlag) { var broadPhase = this.m_world.m_contactManager.m_broadPhase; fixture.DestroyProxy(broadPhase); } else { //b2Assert(fixture->m_proxyId == b2BroadPhase::e_nullProxy); } 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 (radians). * This breaks any contacts and wakes the other bodies. * @param position the new world position of the body's origin (not necessarily * the center of mass). * @param angle the new world rotation angle of the body in radians. */ b2Body.prototype.SetPositionAndAngle = function (position, angle) { var f; //b2Settings.b2Assert(this.m_world.IsLocked() == false); if (this.m_world.IsLocked() == true) { return; } this.m_xf.R.Set(angle); this.m_xf.position.SetV(position); //this.m_sweep.c0 = this.m_sweep.c = b2Mul(this.m_xf, this.m_sweep.localCenter); //b2MulMV(this.m_xf.R, this.m_sweep.localCenter); var tMat = this.m_xf.R; var tVec = this.m_sweep.localCenter; // (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y) this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y); // (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y) this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y); //return T.position + b2Mul(T.R, v); this.m_sweep.c.x += this.m_xf.position.x; this.m_sweep.c.y += this.m_xf.position.y; //this.m_sweep.c0 = this.m_sweep.c this.m_sweep.c0.SetV(this.m_sweep.c); this.m_sweep.a0 = this.m_sweep.a = angle; var broadPhase = this.m_world.m_contactManager.m_broadPhase; for (f = this.m_fixtureList; f; f = f.m_next) { f.Synchronize(broadPhase, this.m_xf, this.m_xf); } this.m_world.m_contactManager.FindNewContacts(); }; /** * Set the position of the body's origin and rotation (radians). * This breaks any contacts and wakes the other bodies. * Note this is less efficient than the other overload - you should use that * if the angle is available. * @param xf the transform of position and angle to set the bdoy to. */ b2Body.prototype.SetTransform = function (xf) { this.SetPositionAndAngle(xf.position, xf.GetAngle()); }; /** * Get the body transform for the body's origin. * @return the world transform of the body's origin. */ b2Body.prototype.GetTransform = function () { return this.m_xf; }; /** * Get the world body origin position. * @return the world position of the body's origin. */ b2Body.prototype.GetPosition = function () { return this.m_xf.position; }; /** * Setthe world body origin position. * @param position the new position of the body */ b2Body.prototype.SetPosition = function (position) { this.SetPositionAndAngle(position, this.GetAngle()); }; /** * Get the angle in radians. * @return the current world rotation angle in radians. */ b2Body.prototype.GetAngle = function () { return this.m_sweep.a; }; /** * Set the world body angle * @param angle the new angle of the body. */ b2Body.prototype.SetAngle = function (angle) { this.SetPositionAndAngle(this.GetPosition(), angle); }; /** * Get the world position of the center of mass. */ b2Body.prototype.GetWorldCenter = function () { return this.m_sweep.c; }; /** * Get the local position of the center of mass. */ b2Body.prototype.GetLocalCenter = function () { return this.m_sweep.localCenter; }; /** * Set the linear velocity of the center of mass. * @param v the new linear velocity of the center of mass. */ b2Body.prototype.SetLinearVelocity = function (v) { if (this.m_type == b2Body.b2_staticBody) { return; } this.m_linearVelocity.SetV(v); }; /** * Get the linear velocity of the center of mass. * @return the linear velocity of the center of mass. */ b2Body.prototype.GetLinearVelocity = function () { return this.m_linearVelocity; }; /** * Set the angular velocity. * @param omega the new angular velocity in radians/second. */ b2Body.prototype.SetAngularVelocity = function (omega) { if (this.m_type == b2Body.b2_staticBody) { return; } this.m_angularVelocity = omega; }; /** * Get the angular velocity. * @return the angular velocity in radians/second. */ b2Body.prototype.GetAngularVelocity = function () { return this.m_angularVelocity; }; /** * Get the definition containing the body properties. * @asonly */ b2Body.prototype.GetDefinition = function () { var bd = new b2BodyDef(); bd.type = this.GetType(); bd.allowSleep = (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag; bd.angle = this.GetAngle(); bd.angularDamping = this.m_angularDamping; bd.angularVelocity = this.m_angularVelocity; bd.fixedRotation = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag; bd.bullet = (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag; bd.awake = (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag; bd.linearDamping = this.m_linearDamping; bd.linearVelocity.SetV(this.GetLinearVelocity()); bd.position = this.GetPosition(); bd.userData = this.GetUserData(); return bd; }; /** * 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. * @param force the world force vector, usually in Newtons (N). * @param point the world position of the point of application. */ b2Body.prototype.ApplyForce = function (force, point) { if (this.m_type != b2Body.b2_dynamicBody) { return; } if (this.IsAwake() == false) { this.SetAwake(true); } //this.m_force += force; this.m_force.x += force.x; this.m_force.y += force.y; //this.m_torque += b2Cross(point - this.m_sweep.c, force); this.m_torque += ((point.x - this.m_sweep.c.x) * force.y - (point.y - this.m_sweep.c.y) * force.x); }; /** * Apply a torque. This affects the angular velocity * without affecting the linear velocity of the center of mass. * This wakes up the body. * @param torque about the z-axis (out of the screen), usually in N-m. */ b2Body.prototype.ApplyTorque = function (torque) { if (this.m_type != b2Body.b2_dynamicBody) { return; } if (this.IsAwake() == false) { this.SetAwake(true); } 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. * @param impulse the world impulse vector, usually in N-seconds or kg-m/s. * @param point the world position of the point of application. */ b2Body.prototype.ApplyImpulse = function (impulse, point) { if (this.m_type != b2Body.b2_dynamicBody) { return; } if (this.IsAwake() == false) { this.SetAwake(true); } //this.m_linearVelocity += this.m_invMass * impulse; this.m_linearVelocity.x += this.m_invMass * impulse.x; this.m_linearVelocity.y += this.m_invMass * impulse.y; //this.m_angularVelocity += this.m_invI * b2Cross(point - this.m_sweep.c, impulse); this.m_angularVelocity += this.m_invI * ((point.x - this.m_sweep.c.x) * impulse.y - (point.y - this.m_sweep.c.y) * impulse.x); }; /** * Splits a body into two, preserving dynamic properties * @param callback Called once per fixture, return true to move this fixture to the new body * <code>function Callback(fixture:b2Fixture):boolean</code> * @return The newly created bodies * @asonly */ b2Body.prototype.Split = function (callback) { var linearVelocity = this.GetLinearVelocity().Copy(); //Reset mass will alter this 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; // Remove fixture if (prev) { prev.m_next = next; } else { body1.m_fixtureList = next; } body1.m_fixtureCount--; // Add fixture 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(); // Compute consistent velocites for new bodies based on cached velocity var center1 = body1.GetWorldCenter(); var center2 = body2.GetWorldCenter(); var velocity1 = b2Math.AddVV(linearVelocity, b2Math.CrossFV(angularVelocity, b2Math.SubtractVV(center1, center))); var velocity2 = b2Math.AddVV(linearVelocity, b2Math.CrossFV(angularVelocity, b2Math.SubtractVV(center2, center))); body1.SetLinearVelocity(velocity1); body2.SetLinearVelocity(velocity2); body1.SetAngularVelocity(angularVelocity); body2.SetAngularVelocity(angularVelocity); body1.SynchronizeFixtures(); body2.SynchronizeFixtures(); return body2; }; /** * Merges another body into this. Only fixtures, mass and velocity are effected, * Other properties are ignored * @asonly */ b2Body.prototype.Merge = function (other) { var f; for (f = other.m_fixtureList; f;) { var next = f.m_next; // Remove fixture other.m_fixtureCount--; // Add fixture f.m_next = this.m_fixtureList; this.m_fixtureList = f; this.m_fixtureCount++; f.m_body = body2; f = next; } body1.m_fixtureCount = 0; // Recalculate velocities var body1 = this; var body2 = other; // Compute consistent velocites for new bodies based on cached velocity var center1 = body1.GetWorldCenter(); var center2 = body2.GetWorldCenter(); var velocity1 = body1.GetLinearVelocity().Copy(); var velocity2 = body2.GetLinearVelocity().Copy(); var angular1 = body1.GetAngularVelocity(); var angular = body2.GetAngularVelocity(); // TODO body1.ResetMassData(); this.SynchronizeFixtures(); }; /** * Get the total mass of the body. * @return the mass, usually in kilograms (kg). */ b2Body.prototype.GetMass = function () { return this.m_mass; }; /** * Get the central rotational inertia of the body. * @return the rotational inertia, usually in kg-m^2. */ b2Body.prototype.GetInertia = function () { return this.m_I; }; /** * Get the mass data of the body. The rotational inertial is relative to the center of mass. */ b2Body.prototype.GetMassData = function (data) { data.mass = this.m_mass; data.I = this.m_I; data.center.SetV(this.m_sweep.localCenter); }; /** * 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. * @warning The supplied rotational inertia should be relative to the center of mass * @param data the mass properties. */ b2Body.prototype.SetMassData = function (massData) { b2Settings.b2Assert(this.m_world.IsLocked() == false); if (this.m_world.IsLocked() == true) { return; } if (this.m_type != b2Body.b2_dynamicBody) { return; } this.m_invMass = 0.0; this.m_I = 0.0; this.m_invI = 0.0; this.m_mass = massData.mass; // Compute the center of mass. if (this.m_mass <= 0.0) { this.m_mass = 1.0; } this.m_invMass = 1.0 / this.m_mass; if (massData.I > 0.0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { // Center the inertia about the center of mass this.m_I = massData.I - this.m_mass * (massData.center.x * massData.center.x + massData.center.y * massData.center.y); this.m_invI = 1.0 / this.m_I; } // Move center of mass var oldCenter = this.m_sweep.c.Copy(); this.m_sweep.localCenter.SetV(massData.center); this.m_sweep.c0.SetV(b2Math.MulX(this.m_xf, this.m_sweep.localCenter)); this.m_sweep.c.SetV(this.m_sweep.c0); // Update center of mass velocity //this.m_linearVelocity += b2Cross(this.m_angularVelocity, this.m_sweep.c - oldCenter); this.m_linearVelocity.x += this.m_angularVelocity * -(this.m_sweep.c.y - oldCenter.y); this.m_linearVelocity.y += this.m_angularVelocity * +(this.m_sweep.c.x - oldCenter.x); }; /** * 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 later you want to reset the mass. */ b2Body.prototype.ResetMassData = function () { // Compute mass data from shapes. Each shape has it's own density this.m_mass = 0.0; this.m_invMass = 0.0; this.m_I = 0.0; this.m_invI = 0.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) { return; } //b2Assert(this.m_type == b2Body.b2_dynamicBody); // Accumulate mass over all fixtures. var center = b2Vec2.Make(0, 0); for (var f = this.m_fixtureList; f; f = f.m_next) { if (f.m_density == 0.0) { continue; } var massData = f.GetMassData(); this.m_mass += massData.mass; center.x += massData.center.x * massData.mass; center.y += massData.center.y * massData.mass; this.m_I += massData.I; } // Compute the center of mass. if (this.m_mass > 0.0) { this.m_invMass = 1.0 / this.m_mass; center.x *= this.m_invMass; center.y *= this.m_invMass; } else { // Force all dynamic bodies to have a positive mass. this.m_mass = 1.0; this.m_invMass = 1.0; } if (this.m_I > 0.0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { // Center the inertia about the center of mass this.m_I -= this.m_mass * (center.x * center.x + center.y * center.y); this.m_I *= this.m_inertiaScale; b2Settings.b2Assert(this.m_I > 0); this.m_invI = 1.0 / this.m_I; } else { this.m_I = 0.0; this.m_invI = 0.0; } // Move center of mass var oldCenter = this.m_sweep.c.Copy(); this.m_sweep.localCenter.SetV(center); this.m_sweep.c0.SetV(b2Math.MulX(this.m_xf, this.m_sweep.localCenter)); this.m_sweep.c.SetV(this.m_sweep.c0); // Update center of mass velocity //this.m_linearVelocity += b2Cross(this.m_angularVelocity, this.m_sweep.c - oldCenter); this.m_linearVelocity.x += this.m_angularVelocity * -(this.m_sweep.c.y - oldCenter.y); this.m_linearVelocity.y += this.m_angularVelocity * +(this.m_sweep.c.x - oldCenter.x); }; /** * Get the world coordinates of a point given the local coordinates. * @param localPoint a point on the body measured relative the the body's origin. * @return the same point expressed in world coordinates. */ b2Body.prototype.GetWorldPoint = function (localPoint) { //return b2Math.b2MulX(this.m_xf, localPoint); var A = this.m_xf.R; var u = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y, A.col1.y * localPoint.x + A.col2.y * localPoint.y); u.x += this.m_xf.position.x; u.y += this.m_xf.position.y; return u; }; /** * Get the world coordinates of a vector given the local coordinates. * @param localVector a vector fixed in the body. * @return the same vector expressed in world coordinates. */ b2Body.prototype.GetWorldVector = function (localVector) { return b2Math.MulMV(this.m_xf.R, localVector); }; /** * Gets a local point relative to the body's origin given a world point. * @param a point in world coordinates. * @return the corresponding local point relative to the body's origin. */ b2Body.prototype.GetLocalPoint = function (worldPoint) { return b2Math.MulXT(this.m_xf, worldPoint); }; /** * Gets a local vector given a world vector. * @param a vector in world coordinates. * @return the corresponding local vector. */ b2Body.prototype.GetLocalVector = function (worldVector) { return b2Math.MulTMV(this.m_xf.R, worldVector); }; /** * Get the world linear velocity of a world point attached to this body. * @param a point in world coordinates. * @return the world velocity of a point. */ b2Body.prototype.GetLinearVelocityFromWorldPoint = function (worldPoint) { //return this.m_linearVelocity + b2Cross(this.m_angularVelocity, worldPoint - this.m_sweep.c); return new b2Vec2(this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y), this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x)); }; /** * Get the world velocity of a local point. * @param a point in local coordinates. * @return the world velocity of a point. */ b2Body.prototype.GetLinearVelocityFromLocalPoint = function (localPoint) { //return GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint)); var A = this.m_xf.R; var worldPoint = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y, A.col1.y * localPoint.x + A.col2.y * localPoint.y); worldPoint.x += this.m_xf.position.x; worldPoint.y += this.m_xf.position.y; return new b2Vec2(this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y), this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x)); }; /** * Get the linear damping of the body. */ b2Body.prototype.GetLinearDamping = function () { return this.m_linearDamping; }; /** * Set the linear damping of the body. */ b2Body.prototype.SetLinearDamping = function (linearDamping) { this.m_linearDamping = linearDamping; }; /** * Get the angular damping of the body */ b2Body.prototype.GetAngularDamping = function () { return this.m_angularDamping; }; /** * Set the angular damping of the body. */ b2Body.prototype.SetAngularDamping = function (angularDamping) { this.m_angularDamping = angularDamping; }; /** * Set the type of this body. This may alter the mass and velocity * @param type - enum stored as a static member of b2Body */ b2Body.prototype.SetType = function (type /** uint */) { 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.0; } this.SetAwake(true); this.m_force.SetZero(); this.m_torque = 0.0; // Since the body type changed, we need to flag contacts for filtering. for (var ce = this.m_contactList; ce; ce = ce.next) { ce.contact.FlagForFiltering(); } }; /** * Get the type of this body. * @return type enum as a uint */ b2Body.prototype.GetType = function () { return this.m_type; }; /** * Should this body be treated like a bullet for continuous collision detection? */ b2Body.prototype.SetBullet = function (flag) { if (flag) { this.m_flags |= b2Body.e_bulletFlag; } else { this.m_flags &= ~b2Body.e_bulletFlag; } }; /** * Is this body treated like a bullet for continuous collision detection? */ b2Body.prototype.IsBullet = function () { return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag; }; /** * Is this body allowed to sleep * @param flag */ b2Body.prototype.SetSleepingAllowed = function (flag) { if (flag) { this.m_flags |= b2Body.e_allowSleepFlag; } else { this.m_flags &= ~b2Body.e_allowSleepFlag; this.SetAwake(true); } }; /** * Set the sleep state of the body. A sleeping body has vety low CPU cost. * @param flag - set to true to put body to sleep, false to wake it */ b2Body.prototype.SetAwake = function (flag) { if (flag) { this.m_flags |= b2Body.e_awakeFlag; this.m_sleepTime = 0.0; } else { this.m_flags &= ~b2Body.e_awakeFlag; this.m_sleepTime = 0.0; this.m_linearVelocity.SetZero(); this.m_angularVelocity = 0.0; this.m_force.SetZero(); this.m_torque = 0.0; } }; /** * Get the sleeping state of this body. * @return true if body is sleeping */ b2Body.prototype.IsAwake = function () { return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag; }; /** * Set this body to have fixed rotation. This causes the mass to be reset. * @param fixed - true means no rotation */ b2Body.prototype.SetFixedRotation = function (fixed) { if (fixed) { this.m_flags |= b2Body.e_fixedRotationFlag; } else { this.m_flags &= ~b2Body.e_fixedRotationFlag; } this.ResetMassData(); }; /** * Does this body have fixed rotation? * @return true means fixed rotation */ b2Body.prototype.IsFixedRotation = function () { return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_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 b2World object and remains * in the body list. */ b2Body.prototype.SetActive = function (flag) { if (flag == this.IsActive()) { return; } var broadPhase; var f; if (flag) { this.m_flags |= b2Body.e_activeFlag; // Create all proxies. broadPhase = this.m_world.m_contactManager.m_broadPhase; for (f = this.m_fixtureList; f; f = f.m_next) { f.CreateProxy(broadPhase, this.m_xf); } // Contacts are created the next time step. } else { this.m_flags &= ~b2Body.e_activeFlag; // Destroy all proxies. broadPhase = this.m_world.m_contactManager.m_broadPhase; for (f = this.m_fixtureList; f; f = f.m_next) { f.DestroyProxy(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. * @return true if active. */ b2Body.prototype.IsActive = function () { return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag; }; /** * Is this body allowed to sleep? */ b2Body.prototype.IsSleepingAllowed = function () { return (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag; }; /** * Get the list of all fixtures attached to this body. */ b2Body.prototype.GetFixtureList = function () { return this.m_fixtureList; }; /** * Get the list of all joints attached to this body. */ b2Body.prototype.GetJointList = function () { return this.m_jointList; }; /** * Get the list of all controllers attached to this body. */ b2Body.prototype.GetControllerList = function () { return this.m_controllerList; }; /** * Get a list of all contacts attached to this body. */ b2Body.prototype.GetContactList = function () { return this.m_contactList; }; /** * Get the next body in the world's body list. */ b2Body.prototype.GetNext = function () { return this.m_next; }; /** * Get the user data pointer that was provided in the body definition. */ b2Body.prototype.GetUserData = function () { return this.m_userData; }; /** * Set the user data. Use this to store your application specific data. */ b2Body.prototype.SetUserData = function (data) { this.m_userData = data; }; /** * Get the parent world of this body. */ b2Body.prototype.GetWorld = function () { return this.m_world; }; // b2Body.prototype.SynchronizeFixtures = function () { var xf1 = b2Body.s_xf1; xf1.R.Set(this.m_sweep.a0); //xf1.position = this.m_sweep.c0 - b2Mul(xf1.R, this.m_sweep.localCenter); var tMat = xf1.R; var tVec = this.m_sweep.localCenter; xf1.position.x = this.m_sweep.c0.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y); xf1.position.y = this.m_sweep.c0.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y); var f; var broadPhase = this.m_world.m_contactManager.m_broadPhase; for (f = this.m_fixtureList; f; f = f.m_next) { f.Synchronize(broadPhase, xf1, this.m_xf); } }; b2Body.prototype.SynchronizeTransform = function () { this.m_xf.R.Set(this.m_sweep.a); //this.m_xf.position = this.m_sweep.c - b2Mul(this.m_xf.R, this.m_sweep.localCenter); var tMat = this.m_xf.R; var tVec = this.m_sweep.localCenter; this.m_xf.position.x = this.m_sweep.c.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y); this.m_xf.position.y = this.m_sweep.c.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y); }; // This is used to prevent connected bodies from colliding. // It may lie, depending on the collideConnected flag. b2Body.prototype.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 == false) { return false; } } return true; }; b2Body.prototype.Advance = function (t) { // Advance to the new safe time. this.m_sweep.Advance(t); this.m_sweep.c.SetV(this.m_sweep.c0); this.m_sweep.a = this.m_sweep.a0; this.SynchronizeTransform(); }; // Destructor //~b2Body(); // b2Body.s_xf1 = new b2Transform(); // m_flags //enum //{ b2Body.e_islandFlag = 0x0001; b2Body.e_awakeFlag = 0x0002; b2Body.e_allowSleepFlag = 0x0004; b2Body.e_bulletFlag = 0x0008; b2Body.e_fixedRotationFlag = 0x0010; b2Body.e_activeFlag = 0x0020; //}; // this.m_type //enum //{ /// The body type. /// static: zero mass, zero velocity, may be manually moved /// kinematic: zero mass, non-zero velocity set by user, moved by solver /// dynamic: positive mass, non-zero velocity determined by forces, moved by solver b2Body.b2_staticBody = 0; b2Body.b2_kinematicBody = 1; b2Body.b2_dynamicBody = 2; return b2Body; }()); export { b2Body };