mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
3205 lines
95 KiB
JavaScript
3205 lines
95 KiB
JavaScript
gdjs.Physics2SharedData = function(runtimeScene, sharedData) {
|
|
this.gravityX = sharedData.gravityX;
|
|
this.gravityY = sharedData.gravityY;
|
|
this.scaleX =
|
|
sharedData.scaleX === 0 ? 100 : sharedData.scaleX;
|
|
this.scaleY =
|
|
sharedData.scaleY === 0 ? 100 : sharedData.scaleY;
|
|
|
|
this.invScaleX = 1 / this.scaleX;
|
|
this.invScaleY = 1 / this.scaleY;
|
|
this.timeStep = 1 / 60;
|
|
this.frameTime = 0;
|
|
this.stepped = false;
|
|
this.timeScale = 1;
|
|
this.world = new Box2D.b2World(
|
|
new Box2D.b2Vec2(this.gravityX, this.gravityY),
|
|
true
|
|
);
|
|
this.staticBody = this.world.CreateBody(new Box2D.b2BodyDef());
|
|
|
|
// Contact listener to keep track of current collisions
|
|
this.contactListener = new Box2D.JSContactListener();
|
|
this.contactListener.BeginContact = function(contactPtr) {
|
|
// Get the contact
|
|
var contact = Box2D.wrapPointer(contactPtr, Box2D.b2Contact);
|
|
// There is no body, return
|
|
if (
|
|
contact.GetFixtureA().GetBody() === null ||
|
|
contact.GetFixtureB().GetBody() === null
|
|
) {
|
|
return;
|
|
}
|
|
// Get associated behaviors
|
|
var behaviorA = contact.GetFixtureA().GetBody().gdjsAssociatedBehavior;
|
|
var behaviorB = contact.GetFixtureB().GetBody().gdjsAssociatedBehavior;
|
|
// Let each behavior know about the contact against the other
|
|
behaviorA.currentContacts.push(behaviorB);
|
|
behaviorB.currentContacts.push(behaviorA);
|
|
};
|
|
|
|
this.contactListener.EndContact = function(contactPtr) {
|
|
// Get the contact
|
|
var contact = Box2D.wrapPointer(contactPtr, Box2D.b2Contact);
|
|
// There is no body, return
|
|
if (
|
|
contact.GetFixtureA().GetBody() === null ||
|
|
contact.GetFixtureB().GetBody() === null
|
|
) {
|
|
return;
|
|
}
|
|
// Get associated behaviors
|
|
var behaviorA = contact.GetFixtureA().GetBody().gdjsAssociatedBehavior;
|
|
var behaviorB = contact.GetFixtureB().GetBody().gdjsAssociatedBehavior;
|
|
// Remove each other contact
|
|
var i = behaviorA.currentContacts.indexOf(behaviorB);
|
|
if (i !== -1) behaviorA.currentContacts.remove(i);
|
|
i = behaviorB.currentContacts.indexOf(behaviorA);
|
|
if (i !== -1) behaviorB.currentContacts.remove(i);
|
|
};
|
|
|
|
this.contactListener.PreSolve = function() {};
|
|
this.contactListener.PostSolve = function() {};
|
|
|
|
this.world.SetContactListener(this.contactListener);
|
|
|
|
this._nextJointId = 1; // Start with 1 so the user is safe from default variables value (0)
|
|
this.joints = {}; // (string)jointId -> (b2Joint)b2Joint
|
|
};
|
|
|
|
gdjs.Physics2SharedData.getSharedData = function(runtimeScene, behaviorName) {
|
|
// Create one if needed
|
|
if (!runtimeScene.physics2SharedData) {
|
|
var initialData = runtimeScene.getInitialSharedDataForBehavior(
|
|
behaviorName
|
|
);
|
|
runtimeScene.physics2SharedData = new gdjs.Physics2SharedData(
|
|
runtimeScene,
|
|
initialData
|
|
);
|
|
}
|
|
|
|
return runtimeScene.physics2SharedData;
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.step = function(deltaTime) {
|
|
this.frameTime += deltaTime;
|
|
if (this.frameTime >= this.timeStep) {
|
|
var numberOfSteps = Math.floor(this.frameTime / this.timeStep);
|
|
this.frameTime -= numberOfSteps * this.timeStep;
|
|
|
|
if (numberOfSteps > 5) numberOfSteps = 5;
|
|
|
|
for (var i = 0; i < numberOfSteps; i++) {
|
|
this.world.Step(this.timeStep * this.timeScale, 8, 10);
|
|
}
|
|
this.world.ClearForces();
|
|
}
|
|
|
|
this.stepped = true;
|
|
};
|
|
|
|
gdjs.Physics2SharedData.gdjsCallbackRuntimeSceneUnloaded = function(
|
|
runtimeScene
|
|
) {
|
|
if (
|
|
runtimeScene.physics2SharedData &&
|
|
runtimeScene.physics2SharedData.world
|
|
) {
|
|
Box2D.destroy(runtimeScene.physics2SharedData.world);
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.clearBodyJoints = function(body) {
|
|
// Iterate through all the joints
|
|
for (var jointId in this.joints) {
|
|
if (this.joints.hasOwnProperty(jointId)) {
|
|
// If the joint is attached to the body, delete it
|
|
if (
|
|
this.joints[jointId].GetBodyA() === body ||
|
|
this.joints[jointId].GetBodyB() === body
|
|
) {
|
|
this.removeJoint(jointId);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.addJoint = function(joint) {
|
|
// Add the joint to the list
|
|
this.joints[this._nextJointId.toString(10)] = joint;
|
|
// Return the current joint id and then increase it
|
|
return this._nextJointId++;
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.getJoint = function(jointId) {
|
|
// Cast to string
|
|
jointId = jointId.toString(10);
|
|
// Get the joint
|
|
if (this.joints.hasOwnProperty(jointId)) {
|
|
return this.joints[jointId];
|
|
}
|
|
// Joint not found, return null
|
|
return null;
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.getJointId = function(joint) {
|
|
// Search the joint in the list and return the ID
|
|
for (var jointId in this.joints) {
|
|
if (this.joints.hasOwnProperty(jointId)) {
|
|
if (this.joints[jointId] === joint) {
|
|
return parseInt(jointId, 10);
|
|
}
|
|
}
|
|
}
|
|
// Joint not found, return 0
|
|
return 0;
|
|
};
|
|
|
|
gdjs.Physics2SharedData.prototype.removeJoint = function(jointId) {
|
|
// Cast to string
|
|
jointId = jointId.toString(10);
|
|
// Delete the joint
|
|
if (this.joints.hasOwnProperty(jointId)) {
|
|
var joint = this.joints[jointId];
|
|
// If we delete a joint attached to a gear joint, the gear will crash, so we must delete the gear joint first
|
|
// Search in our joints list gear joints attached to this one we want to remove
|
|
// The joint can be attached to a gear joint if it's revolute or prismatic only
|
|
if (
|
|
joint.GetType() === Box2D.e_revoluteJoint ||
|
|
joint.GetType() === Box2D.e_prismaticJoint
|
|
) {
|
|
for (var jId in this.joints) {
|
|
if (this.joints.hasOwnProperty(jId)) {
|
|
// Must check pointers becuase gears store non-casted joints (b2Joint)
|
|
if (
|
|
this.joints[jId].GetType() === Box2D.e_gearJoint &&
|
|
(Box2D.getPointer(this.joints[jId].GetJoint1()) ===
|
|
Box2D.getPointer(joint) ||
|
|
Box2D.getPointer(this.joints[jId].GetJoint2()) ===
|
|
Box2D.getPointer(joint))
|
|
) {
|
|
// We could pass it a string, but lets do it right
|
|
this.removeJoint(parseInt(jId, 10));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Remove the joint
|
|
this.world.DestroyJoint(joint);
|
|
delete this.joints[jointId];
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior = function(runtimeScene, behaviorData, owner) {
|
|
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
|
|
|
|
this.bodyType = behaviorData.bodyType;
|
|
this.bullet = behaviorData.bullet;
|
|
this.fixedRotation = behaviorData.fixedRotation;
|
|
this.canSleep = behaviorData.canSleep;
|
|
this.shape = behaviorData.shape;
|
|
this.shapeDimensionA = behaviorData.shapeDimensionA;
|
|
this.shapeDimensionB = behaviorData.shapeDimensionB;
|
|
this.shapeOffsetX = behaviorData.shapeOffsetX;
|
|
this.shapeOffsetY = behaviorData.shapeOffsetY;
|
|
this.polygonOrigin = behaviorData.polygonOrigin;
|
|
this.polygon =
|
|
this.shape === 'Polygon'
|
|
? gdjs.Physics2RuntimeBehavior.getPolygon(behaviorData.vertices)
|
|
: null;
|
|
this.density = behaviorData.density;
|
|
this.friction = behaviorData.friction;
|
|
this.restitution = behaviorData.restitution;
|
|
this.linearDamping = behaviorData.linearDamping;
|
|
this.angularDamping = behaviorData.angularDamping;
|
|
this.gravityScale = behaviorData.gravityScale;
|
|
this.layers = behaviorData.layers;
|
|
this.masks = behaviorData.masks;
|
|
this.shapeScale = 1;
|
|
this.currentContacts = this.currentContacts || [];
|
|
this.currentContacts.length = 0;
|
|
|
|
this._body = null;
|
|
this._sharedData = gdjs.Physics2SharedData.getSharedData(
|
|
runtimeScene,
|
|
behaviorData.name
|
|
);
|
|
this._tempb2Vec2 = new Box2D.b2Vec2(); // Avoid creating new vectors all the time
|
|
this._tempb2Vec2Sec = new Box2D.b2Vec2(); // Sometimes two vectors are needed on the same function call
|
|
this._objectOldX = 0;
|
|
this._objectOldY = 0;
|
|
this._objectOldAngle = 0;
|
|
this._objectOldWidth = 0;
|
|
this._objectOldHeight = 0;
|
|
this._verticesBuffer = 0; // Stores a Box2D pointer of created vertices
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype = Object.create(
|
|
gdjs.RuntimeBehavior.prototype
|
|
);
|
|
gdjs.Physics2RuntimeBehavior.thisIsARuntimeBehaviorConstructor =
|
|
'Physics2::Physics2Behavior';
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.b2Vec2 = function(x, y) {
|
|
this._tempb2Vec2.set_x(x);
|
|
this._tempb2Vec2.set_y(y);
|
|
return this._tempb2Vec2;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.b2Vec2Sec = function(x, y) {
|
|
this._tempb2Vec2Sec.set_x(x);
|
|
this._tempb2Vec2Sec.set_y(y);
|
|
return this._tempb2Vec2Sec;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.onDeActivate = function() {
|
|
if (this._body !== null) {
|
|
// When a body is deleted, Box2D removes automatically its joints, leaving an invalid pointer in our joints list
|
|
this._sharedData.clearBodyJoints(this._body);
|
|
// Delete the vertices
|
|
if (this._verticesBuffer) {
|
|
Box2D._free(this._verticesBuffer);
|
|
this._verticesBuffer = 0;
|
|
}
|
|
// Delete the body
|
|
this._sharedData.world.DestroyBody(this._body);
|
|
this._body = null;
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
|
|
this.onDeActivate();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.getPolygon = function(verticesData) {
|
|
if (!verticesData) return null;
|
|
|
|
var polygon = new gdjs.Polygon();
|
|
var maxVertices = 8;
|
|
for (
|
|
var i = 0, len = verticesData.length;
|
|
i < Math.min(len, maxVertices);
|
|
i++
|
|
) {
|
|
polygon.vertices.push([verticesData[i].x, verticesData[i].y]);
|
|
}
|
|
return polygon;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.isPolygonConvex = function(polygon) {
|
|
if (!polygon.isConvex()) return false;
|
|
|
|
// Check for repeated vertices or check if all vertices are aligned (would crash Box2D)
|
|
var alignedX = true;
|
|
var alignedY = true;
|
|
for (i = 0; i < polygon.vertices.length - 1; ++i) {
|
|
for (var j = i + 1; j < polygon.vertices.length; ++j) {
|
|
if (
|
|
polygon.vertices[i][0] === polygon.vertices[j][0] &&
|
|
polygon.vertices[i][1] === polygon.vertices[j][1]
|
|
)
|
|
return false;
|
|
}
|
|
if (polygon.vertices[i][0] !== polygon.vertices[i + 1][0]) alignedX = false;
|
|
if (polygon.vertices[i][1] !== polygon.vertices[i + 1][1]) alignedY = false;
|
|
}
|
|
if (alignedX || alignedY) return false;
|
|
|
|
return true;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.createShape = function() {
|
|
// Get the scaled offset
|
|
var offsetX = this.shapeOffsetX
|
|
? this.shapeOffsetX * this.shapeScale * this._sharedData.invScaleX
|
|
: 0;
|
|
var offsetY = this.shapeOffsetY
|
|
? this.shapeOffsetY * this.shapeScale * this._sharedData.invScaleY
|
|
: 0;
|
|
// Generate the base shape
|
|
var shape;
|
|
if (this.shape === 'Circle') {
|
|
shape = new Box2D.b2CircleShape();
|
|
// Radius determined by the custom dimension
|
|
if (this.shapeDimensionA > 0) {
|
|
shape.set_m_radius(
|
|
this.shapeDimensionA * this.shapeScale * this._sharedData.invScaleX
|
|
);
|
|
}
|
|
// Average radius from width and height
|
|
else {
|
|
var radius =
|
|
(this.owner.getWidth() * this._sharedData.invScaleX +
|
|
this.owner.getHeight() * this._sharedData.invScaleY) /
|
|
4;
|
|
shape.set_m_radius(radius > 0 ? radius : 1);
|
|
}
|
|
// Set the offset
|
|
shape.set_m_p(this.b2Vec2(offsetX, offsetY));
|
|
} else if (this.shape === 'Polygon') {
|
|
shape = new Box2D.b2PolygonShape();
|
|
// Not convex, fall back to a box
|
|
if (
|
|
!this.polygon ||
|
|
!gdjs.Physics2RuntimeBehavior.isPolygonConvex(this.polygon)
|
|
) {
|
|
var width =
|
|
(this.owner.getWidth() > 0 ? this.owner.getWidth() : 1) *
|
|
this._sharedData.invScaleX;
|
|
var height =
|
|
(this.owner.getHeight() > 0 ? this.owner.getHeight() : 1) *
|
|
this._sharedData.invScaleY;
|
|
// Set the shape box
|
|
shape.SetAsBox(width / 2, height / 2, this.b2Vec2(offsetX, offsetY), 0);
|
|
} else {
|
|
var originOffsetX = 0;
|
|
var originOffsetY = 0;
|
|
if (this.polygonOrigin === 'Origin') {
|
|
originOffsetX =
|
|
(this.owner.getWidth() > 0 ? -this.owner.getWidth() / 2 : 0) +
|
|
(this.owner.getX() - this.owner.getDrawableX());
|
|
originOffsetY =
|
|
(this.owner.getHeight() > 0 ? -this.owner.getHeight() / 2 : 0) +
|
|
(this.owner.getY() - this.owner.getDrawableY());
|
|
} else if (this.polygonOrigin === 'TopLeft') {
|
|
originOffsetX =
|
|
this.owner.getWidth() > 0 ? -this.owner.getWidth() / 2 : 0;
|
|
originOffsetY =
|
|
this.owner.getHeight() > 0 ? -this.owner.getHeight() / 2 : 0;
|
|
}
|
|
// Generate vertices if not done already
|
|
if (!this._verticesBuffer) {
|
|
// Store the vertices using a memory allocation function
|
|
var buffer = Box2D._malloc(
|
|
this.polygon.vertices.length * 8,
|
|
'float',
|
|
Box2D.ALLOC_STACK
|
|
);
|
|
this._verticesBuffer = buffer;
|
|
}
|
|
// Overwrite the vertices stored in the buffer
|
|
var offset = 0;
|
|
for (var i = 0, len = this.polygon.vertices.length; i < len; i++) {
|
|
Box2D.HEAPF32[(this._verticesBuffer + offset) >> 2] =
|
|
(this.polygon.vertices[i][0] * this.shapeScale + originOffsetX) *
|
|
this._sharedData.invScaleX +
|
|
offsetX;
|
|
Box2D.HEAPF32[(this._verticesBuffer + (offset + 4)) >> 2] =
|
|
(this.polygon.vertices[i][1] * this.shapeScale + originOffsetY) *
|
|
this._sharedData.invScaleY +
|
|
offsetY;
|
|
offset += 8;
|
|
}
|
|
// Set the shape vertices
|
|
var b2Vertices = Box2D.wrapPointer(this._verticesBuffer, Box2D.b2Vec2);
|
|
shape.Set(b2Vertices, this.polygon.vertices.length);
|
|
}
|
|
} else if (this.shape === 'Edge') {
|
|
shape = new Box2D.b2EdgeShape();
|
|
// Length from the custom dimension or from the object width
|
|
var length =
|
|
(this.shapeDimensionA > 0
|
|
? this.shapeDimensionA * this.shapeScale
|
|
: this.owner.getWidth() > 0
|
|
? this.owner.getWidth()
|
|
: 1) * this._sharedData.invScaleX;
|
|
var height =
|
|
this.owner.getHeight() > 0
|
|
? this.owner.getHeight() * this._sharedData.invScaleY
|
|
: 0;
|
|
// Angle from custom dimension, otherwise is 0
|
|
var angle = this.shapeDimensionB ? gdjs.toRad(this.shapeDimensionB) : 0;
|
|
// Set the edge vertices from the length, the angle and the offset
|
|
shape.Set(
|
|
this.b2Vec2(
|
|
(-length / 2) * Math.cos(angle) + offsetX,
|
|
height / 2 - (length / 2) * Math.sin(angle) + offsetY
|
|
),
|
|
this.b2Vec2Sec(
|
|
(length / 2) * Math.cos(angle) + offsetX,
|
|
height / 2 + (length / 2) * Math.sin(angle) + offsetY
|
|
)
|
|
);
|
|
} else {
|
|
// Box
|
|
shape = new Box2D.b2PolygonShape();
|
|
// Width and height from custom dimensions or object size
|
|
var width =
|
|
(this.shapeDimensionA > 0
|
|
? this.shapeDimensionA * this.shapeScale
|
|
: this.owner.getWidth() > 0
|
|
? this.owner.getWidth()
|
|
: 1) * this._sharedData.invScaleX;
|
|
var height =
|
|
(this.shapeDimensionB > 0
|
|
? this.shapeDimensionB * this.shapeScale
|
|
: this.owner.getHeight() > 0
|
|
? this.owner.getHeight()
|
|
: 1) * this._sharedData.invScaleY;
|
|
// Set the shape box, the offset must be added here too
|
|
shape.SetAsBox(width / 2, height / 2, this.b2Vec2(offsetX, offsetY), 0);
|
|
}
|
|
|
|
// Generate filter data
|
|
var filter = new Box2D.b2Filter();
|
|
filter.set_categoryBits(this.layers);
|
|
filter.set_maskBits(this.masks);
|
|
|
|
// Generate the fixture definition
|
|
var fixDef = new Box2D.b2FixtureDef();
|
|
|
|
// Set fixture settings
|
|
fixDef.set_shape(shape);
|
|
fixDef.set_filter(filter);
|
|
if (this.density < 0) this.density = 0;
|
|
fixDef.set_density(this.density);
|
|
if (this.friction < 0) this.friction = 0;
|
|
fixDef.set_friction(this.friction);
|
|
if (this.restitution < 0) this.restitution = 0;
|
|
fixDef.set_restitution(this.restitution);
|
|
|
|
// Return the fixture
|
|
return fixDef;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.recreateShape = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Destroy the old shape
|
|
this._body.DestroyFixture(this._body.GetFixtureList());
|
|
this._body.CreateFixture(this.createShape());
|
|
// Update cached size
|
|
this._objectOldWidth = this.owner.getWidth();
|
|
this._objectOldHeight = this.owner.getHeight();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getShapeScale = function() {
|
|
return this.shapeScale;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setShapeScale = function(shapeScale) {
|
|
if (shapeScale !== this.shapeScale && shapeScale > 0) {
|
|
this.shapeScale = shapeScale;
|
|
this.recreateShape();
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getBody = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
|
|
return this._body;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.createBody = function() {
|
|
// Generate the body definition
|
|
var bodyDef = new Box2D.b2BodyDef();
|
|
|
|
// Set the initial body transformation from the GD object
|
|
bodyDef.set_position(
|
|
this.b2Vec2(
|
|
(this.owner.getDrawableX() + this.owner.getWidth() / 2) *
|
|
this._sharedData.invScaleX,
|
|
(this.owner.getDrawableY() + this.owner.getHeight() / 2) *
|
|
this._sharedData.invScaleY
|
|
)
|
|
);
|
|
bodyDef.set_angle(gdjs.toRad(this.owner.getAngle()));
|
|
|
|
// Set body settings
|
|
bodyDef.set_type(
|
|
this.bodyType === 'Static'
|
|
? Box2D.b2_staticBody
|
|
: this.bodyType === 'Kinematic'
|
|
? Box2D.b2_kinematicBody
|
|
: Box2D.b2_dynamicBody
|
|
);
|
|
bodyDef.set_bullet(this.bullet);
|
|
bodyDef.set_fixedRotation(this.fixedRotation);
|
|
bodyDef.set_allowSleep(this.canSleep);
|
|
bodyDef.set_linearDamping(this.linearDamping);
|
|
bodyDef.set_angularDamping(this.angularDamping);
|
|
bodyDef.set_gravityScale(this.gravityScale);
|
|
|
|
// Create the body
|
|
this._body = this._sharedData.world.CreateBody(bodyDef);
|
|
this._body.CreateFixture(this.createShape());
|
|
this._body.gdjsAssociatedBehavior = this;
|
|
|
|
// Update cached size
|
|
this._objectOldWidth = this.owner.getWidth();
|
|
this._objectOldHeight = this.owner.getHeight();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.doStepPreEvents = function(
|
|
runtimeScene
|
|
) {
|
|
// Create a body if there is not one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
}
|
|
|
|
// Step the world if not done this frame yet
|
|
if (!this._sharedData.stepped) {
|
|
this._sharedData.step(
|
|
runtimeScene.getTimeManager().getElapsedTime() / 1000.0
|
|
);
|
|
}
|
|
|
|
// Copy transform from body to the GD object
|
|
this.owner.setX(
|
|
this._body.GetPosition().get_x() * this._sharedData.scaleX -
|
|
this.owner.getWidth() / 2 +
|
|
this.owner.getX() -
|
|
this.owner.getDrawableX()
|
|
);
|
|
this.owner.setY(
|
|
this._body.GetPosition().get_y() * this._sharedData.scaleY -
|
|
this.owner.getHeight() / 2 +
|
|
this.owner.getY() -
|
|
this.owner.getDrawableY()
|
|
);
|
|
this.owner.setAngle(gdjs.toDegrees(this._body.GetAngle()));
|
|
|
|
// Update cached transform
|
|
this._objectOldX = this.owner.getX();
|
|
this._objectOldY = this.owner.getY();
|
|
this._objectOldAngle = this.owner.getAngle();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.doStepPostEvents = function(
|
|
runtimeScene
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
|
|
// GD object size has changed, recreate shape
|
|
// The width has changed and there is no custom dimension A (box: width, circle: radius, edge: length) or
|
|
// The height has changed, the shape is not an edge (edges doesn't have height),
|
|
// it isn't a box with custom height or a circle with custom radius
|
|
if (
|
|
(this._objectOldWidth !== this.owner.getWidth() &&
|
|
this.shapeDimensionA <= 0) ||
|
|
(this._objectOldHeight !== this.owner.getHeight() &&
|
|
this.shape !== 'Edge' &&
|
|
!(this.shape === 'Box' && this.shapeDimensionB > 0) &&
|
|
!(this.shape === 'Ciecle' && this.shapeDimensionA > 0))
|
|
) {
|
|
this.recreateShape();
|
|
}
|
|
|
|
// GD object transform has changed, update body transform
|
|
if (
|
|
this._objectOldX !== this.owner.getX() ||
|
|
this._objectOldY !== this.owner.getY() ||
|
|
this._objectOldAngle !== this.owner.getAngle()
|
|
) {
|
|
var pos = this.b2Vec2(
|
|
(this.owner.getDrawableX() + this.owner.getWidth() / 2) *
|
|
this._sharedData.invScaleX,
|
|
(this.owner.getDrawableY() + this.owner.getHeight() / 2) *
|
|
this._sharedData.invScaleY
|
|
);
|
|
this._body.SetTransform(pos, gdjs.toRad(this.owner.getAngle()));
|
|
this._body.SetAwake(true);
|
|
}
|
|
|
|
// Reset world step to update next frame
|
|
this._sharedData.stepped = false;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGravityX = function() {
|
|
return this._sharedData.gravityX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGravityY = function() {
|
|
return this._sharedData.gravityY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setGravity = function(x, y) {
|
|
// Check if there is no modification
|
|
if (this._sharedData.gravityX === x && this._sharedData.gravityY === y)
|
|
return;
|
|
// Change the gravity
|
|
this._sharedData.gravityX = x;
|
|
this._sharedData.gravityY = y;
|
|
this._sharedData.world.SetGravity(
|
|
this.b2Vec2(this._sharedData.gravityX, this._sharedData.gravityY)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getTimeScale = function() {
|
|
// Get the time scale
|
|
return this._sharedData.timeScale;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setTimeScale = function(timeScale) {
|
|
// Invalid value
|
|
if (timeScale < 0) return;
|
|
// Set the time scale
|
|
this._sharedData.timeScale = timeScale;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.setTimeScaleFromObject = function(
|
|
object,
|
|
behaviorName,
|
|
timeScale
|
|
) {
|
|
// Check if the object exist and has the behavior
|
|
if (object === null || !object.hasBehavior(behaviorName)) return;
|
|
// Set the time scale
|
|
object.getBehavior(behaviorName).setTimeScale(timeScale);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isDynamic = function() {
|
|
return this.bodyType === 'Dynamic';
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setDynamic = function() {
|
|
// Check if there is no modification
|
|
if (this.bodyType === 'Dynamic') return;
|
|
// Change body type
|
|
this.bodyType = 'Dynamic';
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update body type
|
|
this._body.SetType(Box2D.b2_dynamicBody);
|
|
this._body.SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isStatic = function() {
|
|
return this.bodyType === 'Static';
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setStatic = function() {
|
|
// Check if there is no modification
|
|
if (this.bodyType === 'Static') return;
|
|
// Change body type
|
|
this.bodyType = 'Static';
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update body type
|
|
this._body.SetType(Box2D.b2_staticBody);
|
|
this._body.SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isKinematic = function() {
|
|
return this.bodyType === 'Kinematic';
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setKinematic = function() {
|
|
// Check if there is no modification
|
|
if (this.bodyType === 'Kinematic') return;
|
|
// Change body type
|
|
this.bodyType = 'Kinematic';
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update body type
|
|
this._body.SetType(Box2D.b2_kinematicBody);
|
|
this._body.SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isBullet = function() {
|
|
return this.bullet;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setBullet = function(enable) {
|
|
// Check if there is no modification
|
|
if (this.bullet === enable) return;
|
|
// Change bullet flag
|
|
this.bullet = enable;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update body bullet flag
|
|
this._body.SetBullet(this.bullet);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.hasFixedRotation = function() {
|
|
return this.fixedRotation;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setFixedRotation = function(enable) {
|
|
this.fixedRotation = enable;
|
|
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
this._body.SetFixedRotation(this.fixedRotation);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isSleepingAllowed = function() {
|
|
return this.canSleep;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setSleepingAllowed = function(enable) {
|
|
this.canSleep = enable;
|
|
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
this._body.SetSleepingAllowed(this.canSleep);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isSleeping = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
}
|
|
// Get the body sleeping state
|
|
return !this._body.IsAwake();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getDensity = function() {
|
|
return this.density;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setDensity = function(density) {
|
|
// Non-negative values only
|
|
if (density < 0) density = 0;
|
|
// Check if there is no modification
|
|
if (this.density === density) return;
|
|
// Change density
|
|
this.density = density;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body density
|
|
this._body.GetFixtureList().SetDensity(this.density);
|
|
this._body.ResetMassData();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getFriction = function() {
|
|
return this.friction;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setFriction = function(friction) {
|
|
// Non-negative values only
|
|
if (friction < 0) friction = 0;
|
|
// Check if there is no modification
|
|
if (this.friction === friction) return;
|
|
// Change friction
|
|
this.friction = friction;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body friction
|
|
this._body.GetFixtureList().SetFriction(this.friction);
|
|
// Update contacts
|
|
var contact = this._body.GetContactList();
|
|
while (Box2D.getPointer(contact)) {
|
|
contact.get_contact().ResetFriction();
|
|
contact = contact.get_next();
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRestitution = function() {
|
|
return this.restitution;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setRestitution = function(restitution) {
|
|
// Non-negative values only
|
|
if (restitution < 0) restitution = 0;
|
|
// Check if there is no modification
|
|
if (this.restitution === restitution) return;
|
|
// Change restitution
|
|
this.restitution = restitution;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body restitution
|
|
this._body.GetFixtureList().SetRestitution(this.restitution);
|
|
// Update contacts
|
|
var contact = this._body.GetContactList();
|
|
while (Box2D.getPointer(contact)) {
|
|
contact.get_contact().ResetRestitution();
|
|
contact = contact.get_next();
|
|
}
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getLinearDamping = function() {
|
|
return this.linearDamping;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setLinearDamping = function(
|
|
linearDamping
|
|
) {
|
|
// Check if there is no modification
|
|
if (this.linearDamping === linearDamping) return;
|
|
// Change linearDamping
|
|
this.linearDamping = linearDamping;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body linear damping
|
|
this._body.SetLinearDamping(this.linearDamping);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getAngularDamping = function() {
|
|
return this.angularDamping;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setAngularDamping = function(
|
|
angularDamping
|
|
) {
|
|
// Check if there is no modification
|
|
if (this.angularDamping === angularDamping) return;
|
|
// Change angularDamping
|
|
this.angularDamping = angularDamping;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body angular damping
|
|
this._body.SetAngularDamping(this.angularDamping);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGravityScale = function() {
|
|
return this.gravityScale;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setGravityScale = function(
|
|
gravityScale
|
|
) {
|
|
// Check if there is no modification
|
|
if (this.gravityScale === gravityScale) return;
|
|
// Change the gravity scale
|
|
this.gravityScale = gravityScale;
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body gravity scale
|
|
this._body.SetGravityScale(this.gravityScale);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.layerEnabled = function(layer) {
|
|
// Layer must be an integer
|
|
layer = Math.floor(layer);
|
|
// Layer must be in range [1, 16]
|
|
if (layer < 1 || layer > 16) return false;
|
|
|
|
return !!(this.layers & (1 << (layer - 1)));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enableLayer = function(layer, enable) {
|
|
// Layer must be an integer
|
|
layer = Math.floor(layer);
|
|
// Layer must be in range [1, 16]
|
|
if (layer < 1 || layer > 16) return;
|
|
// Change the layers
|
|
if (enable) {
|
|
this.layers |= 1 << (layer - 1);
|
|
} else {
|
|
this.layers &= ~(1 << (layer - 1));
|
|
}
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body layers
|
|
var filter = this._body.GetFixtureList().GetFilterData();
|
|
filter.set_categoryBits(this.layers);
|
|
this._body.GetFixtureList().SetFilterData(filter);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.maskEnabled = function(mask) {
|
|
// Mask must be an integer
|
|
mask = Math.floor(mask);
|
|
// Mask must be in range [1, 16]
|
|
if (mask < 1 || mask > 16) return false;
|
|
|
|
return !!(this.masks & (1 << (mask - 1)));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enableMask = function(mask, enable) {
|
|
// Mask must be an integer
|
|
mask = Math.floor(mask);
|
|
// Mask must be in range [1, 16]
|
|
if (mask < 1 || mask > 16) return;
|
|
// Change the masks
|
|
if (enable) {
|
|
this.masks |= 1 << (mask - 1);
|
|
} else {
|
|
this.masks &= ~(1 << (mask - 1));
|
|
}
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return;
|
|
}
|
|
// Update the body masks
|
|
var filter = this._body.GetFixtureList().GetFilterData();
|
|
filter.set_maskBits(this.masks);
|
|
this._body.GetFixtureList().SetFilterData(filter);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getLinearVelocityX = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return 0;
|
|
}
|
|
// Get the linear velocity on X
|
|
return this._body.GetLinearVelocity().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setLinearVelocityX = function(
|
|
linearVelocityX
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Set the linear velocity on X
|
|
this._body.SetLinearVelocity(
|
|
this.b2Vec2(
|
|
linearVelocityX * this._sharedData.invScaleX,
|
|
this._body.GetLinearVelocity().get_y()
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getLinearVelocityY = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return 0;
|
|
}
|
|
// Get the linear velocity on Y
|
|
return this._body.GetLinearVelocity().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setLinearVelocityY = function(
|
|
linearVelocityY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Set the linear velocity on Y
|
|
this._body.SetLinearVelocity(
|
|
this.b2Vec2(
|
|
this._body.GetLinearVelocity().get_x(),
|
|
linearVelocityY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getLinearVelocityLength = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return 0;
|
|
}
|
|
// Get the linear velocity length
|
|
return this.b2Vec2(
|
|
this._body.GetLinearVelocity().get_x() * this._sharedData.scaleX,
|
|
this._body.GetLinearVelocity().get_y() * this._sharedData.scaleY
|
|
).Length();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getAngularVelocity = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Get the angular velocity
|
|
return gdjs.toDegrees(this._body.GetAngularVelocity());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setAngularVelocity = function(
|
|
angularVelocity
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Set the angular velocity
|
|
this._body.SetAngularVelocity(gdjs.toRad(angularVelocity));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyForce = function(
|
|
forceX,
|
|
forceY,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the force
|
|
this._body.ApplyForce(
|
|
this.b2Vec2(forceX, forceY),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyPolarForce = function(
|
|
angle,
|
|
length,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the force
|
|
angle = gdjs.toRad(angle);
|
|
this._body.ApplyForce(
|
|
this.b2Vec2(length * Math.cos(angle), length * Math.sin(angle)),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyForceTowardPosition = function(
|
|
length,
|
|
towardX,
|
|
towardY,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the force
|
|
var angle = Math.atan2(
|
|
towardY * this._sharedData.invScaleY - this._body.GetPosition().get_y(),
|
|
towardX * this._sharedData.invScaleX - this._body.GetPosition().get_x()
|
|
);
|
|
this._body.ApplyForce(
|
|
this.b2Vec2(length * Math.cos(angle), length * Math.sin(angle)),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyImpulse = function(
|
|
impulseX,
|
|
impulseY,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the impulse
|
|
this._body.ApplyLinearImpulse(
|
|
this.b2Vec2(impulseX, impulseY),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyPolarImpulse = function(
|
|
angle,
|
|
length,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) his.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the impulse
|
|
angle = gdjs.toRad(angle);
|
|
this._body.ApplyLinearImpulse(
|
|
this.b2Vec2(length * Math.cos(angle), length * Math.sin(angle)),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyImpulseTowardPosition = function(
|
|
length,
|
|
towardX,
|
|
towardY,
|
|
positionX,
|
|
positionY
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the impulse
|
|
var angle = Math.atan2(
|
|
towardY * this._sharedData.invScaleY - this._body.GetPosition().get_y(),
|
|
towardX * this._sharedData.invScaleX - this._body.GetPosition().get_x()
|
|
);
|
|
this._body.ApplyLinearImpulse(
|
|
this.b2Vec2(length * Math.cos(angle), length * Math.sin(angle)),
|
|
this.b2Vec2Sec(
|
|
positionX * this._sharedData.invScaleX,
|
|
positionY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyTorque = function(torque) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the torque
|
|
this._body.ApplyTorque(torque);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.applyAngularImpulse = function(
|
|
angularImpulse
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Wake up the object
|
|
this._body.SetAwake(true);
|
|
// Apply the angular impulse
|
|
this._body.ApplyAngularImpulse(angularImpulse);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMassCenterX = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
}
|
|
// Get the mass center on X
|
|
return this._body.GetWorldCenter().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMassCenterY = function() {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
}
|
|
// Get the mass center on Y
|
|
return this._body.GetWorldCenter().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
// Joints
|
|
gdjs.Physics2RuntimeBehavior.prototype.isJointFirstObject = function(jointId) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return false;
|
|
}
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return false;
|
|
// Check the joint object
|
|
return joint.GetBodyA() === this._body;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isJointSecondObject = function(jointId) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) {
|
|
this.createBody();
|
|
return false;
|
|
}
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return false;
|
|
// Check the joint object
|
|
return joint.GetBodyB() === this._body;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointFirstAnchorX = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the joint anchor
|
|
return joint
|
|
.GetBodyA()
|
|
.GetWorldPoint(joint.GetLocalAnchorA())
|
|
.get_x();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointFirstAnchorY = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the joint anchor
|
|
return joint
|
|
.GetBodyA()
|
|
.GetWorldPoint(joint.GetLocalAnchorA())
|
|
.get_y();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointSecondAnchorX = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the joint anchor
|
|
return joint
|
|
.GetBodyB()
|
|
.GetWorldPoint(joint.GetLocalAnchorB())
|
|
.get_x();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointSecondAnchorY = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the joint anchor
|
|
return joint
|
|
.GetBodyB()
|
|
.GetWorldPoint(joint.GetLocalAnchorB())
|
|
.get_y();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointReactionForce = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the reaction force
|
|
return joint.GetReactionForce(1 / this._sharedData.timeStep).Length();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getJointReactionTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found
|
|
if (joint === null) return 0;
|
|
// Get the reaction torque
|
|
return joint.GetReactionTorque(1 / this._sharedData.timeStep);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.removeJoint = function(jointId) {
|
|
// Just let the sharedData to manage and delete the joint
|
|
this._sharedData.removeJoint(jointId);
|
|
};
|
|
|
|
// Distance joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addDistanceJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
length,
|
|
frequency,
|
|
dampingRatio,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2DistanceJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_length(
|
|
length > 0
|
|
? length * this._sharedData.invScaleX
|
|
: this.b2Vec2(
|
|
(x2 - x1) * this._sharedData.invScaleX,
|
|
(y2 - y1) * this._sharedData.invScaleY
|
|
).Length()
|
|
);
|
|
jointDef.set_frequencyHz(frequency >= 0 ? frequency : 0);
|
|
jointDef.set_dampingRatio(dampingRatio >= 0 ? dampingRatio : 1);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2DistanceJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getDistanceJointLength = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint) return 0;
|
|
// Get the joint length
|
|
return joint.GetLength() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setDistanceJointLength = function(
|
|
jointId,
|
|
length
|
|
) {
|
|
// Invalid value
|
|
if (length <= 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint) return;
|
|
// Set the joint length
|
|
joint.SetLength(length * this._sharedData.invScaleX);
|
|
// Awake the bodies
|
|
joint.GetBodyA().SetAwake(true);
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getDistanceJointFrequency = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint) return 0;
|
|
// Get the joint frequency
|
|
return joint.GetFrequency();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setDistanceJointFrequency = function(
|
|
jointId,
|
|
frequency
|
|
) {
|
|
// Invalid value
|
|
if (frequency < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint) return;
|
|
// Set the joint frequency
|
|
joint.SetFrequency(frequency);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getDistanceJointDampingRatio = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint) return 0;
|
|
// Get the joint damping ratio
|
|
return joint.GetDampingRatio();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setDistanceJointDampingRatio = function(
|
|
jointId,
|
|
dampingRatio
|
|
) {
|
|
// Invalid value
|
|
if (dampingRatio < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_distanceJoint);
|
|
// Set the joint damping ratio
|
|
joint.SetDampingRatio(dampingRatio);
|
|
};
|
|
|
|
// Revolute joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addRevoluteJoint = function(
|
|
x,
|
|
y,
|
|
enableLimit,
|
|
referenceAngle,
|
|
lowerAngle,
|
|
upperAngle,
|
|
enableMotor,
|
|
motorSpeed,
|
|
maxMotorTorque,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2RevoluteJointDef();
|
|
jointDef.set_bodyA(this._sharedData.staticBody);
|
|
jointDef.set_localAnchorA(
|
|
this._sharedData.staticBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x * this._sharedData.invScaleX,
|
|
y * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(this._body);
|
|
jointDef.set_localAnchorB(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x * this._sharedData.invScaleX,
|
|
y * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_enableLimit(enableLimit);
|
|
jointDef.set_referenceAngle(gdjs.toRad(referenceAngle));
|
|
// Lower angle must be lower than upper angle
|
|
if (upperAngle < lowerAngle) {
|
|
var temp = lowerAngle;
|
|
lowerAngle = upperAngle;
|
|
upperAngle = temp;
|
|
}
|
|
jointDef.set_lowerAngle(gdjs.toRad(lowerAngle));
|
|
jointDef.set_upperAngle(gdjs.toRad(upperAngle));
|
|
jointDef.set_enableMotor(enableMotor);
|
|
jointDef.set_motorSpeed(gdjs.toRad(motorSpeed));
|
|
jointDef.set_maxMotorTorque(maxMotorTorque >= 0 ? maxMotorTorque : 0);
|
|
jointDef.set_collideConnected(false);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2RevoluteJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.addRevoluteJointBetweenTwoBodies = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
enableLimit,
|
|
referenceAngle,
|
|
lowerAngle,
|
|
upperAngle,
|
|
enableMotor,
|
|
motorSpeed,
|
|
maxMotorTorque,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2RevoluteJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_enableLimit(enableLimit);
|
|
jointDef.set_referenceAngle(gdjs.toRad(referenceAngle));
|
|
// Lower angle must be lower than upper angle
|
|
if (upperAngle < lowerAngle) {
|
|
var temp = lowerAngle;
|
|
lowerAngle = upperAngle;
|
|
upperAngle = temp;
|
|
}
|
|
jointDef.set_lowerAngle(gdjs.toRad(lowerAngle));
|
|
jointDef.set_upperAngle(gdjs.toRad(upperAngle));
|
|
jointDef.set_enableMotor(enableMotor);
|
|
jointDef.set_motorSpeed(gdjs.toRad(motorSpeed));
|
|
jointDef.set_maxMotorTorque(maxMotorTorque >= 0 ? maxMotorTorque : 0);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2RevoluteJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointReferenceAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint reference angle
|
|
return gdjs.toDegrees(joint.GetReferenceAngle());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint current angle
|
|
return gdjs.toDegrees(joint.GetJointAngle());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointSpeed = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint angular speed
|
|
return gdjs.toDegrees(joint.GetJointSpeed());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isRevoluteJointLimitsEnabled = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return false;
|
|
// Get the joint limits state
|
|
return joint.IsLimitEnabled();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enableRevoluteJointLimits = function(
|
|
jointId,
|
|
enable
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return;
|
|
// Set the joint limits state
|
|
joint.EnableLimit(enable);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointMinAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint lower angle
|
|
return gdjs.toDegrees(joint.GetLowerLimit());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointMaxAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint upper angle
|
|
return gdjs.toDegrees(joint.GetUpperLimit());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setRevoluteJointLimits = function(
|
|
jointId,
|
|
lowerAngle,
|
|
upperAngle
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return;
|
|
// Lower angle must be lower than upper angle
|
|
if (upperAngle < lowerAngle) {
|
|
var temp = lowerAngle;
|
|
lowerAngle = upperAngle;
|
|
upperAngle = temp;
|
|
}
|
|
// Set the joint limits
|
|
joint.SetLimits(gdjs.toRad(lowerAngle), gdjs.toRad(upperAngle));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isRevoluteJointMotorEnabled = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return false;
|
|
// Get the joint motor state
|
|
return joint.IsMotorEnabled();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enableRevoluteJointMotor = function(
|
|
jointId,
|
|
enable
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return;
|
|
// Set the joint motor state
|
|
joint.EnableMotor(enable);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointMotorSpeed = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint motor speed
|
|
return gdjs.toDegrees(joint.GetMotorSpeed());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setRevoluteJointMotorSpeed = function(
|
|
jointId,
|
|
speed
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return;
|
|
// Set the joint motor speed
|
|
joint.SetMotorSpeed(gdjs.toRad(speed));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointMaxMotorTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint max motor
|
|
return joint.GetMaxMotorTorque();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setRevoluteJointMaxMotorTorque = function(
|
|
jointId,
|
|
maxTorque
|
|
) {
|
|
// Invalid value
|
|
if (maxTorque < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return;
|
|
// Set the joint max motor
|
|
joint.SetMaxMotorTorque(maxTorque);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRevoluteJointMotorTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_revoluteJoint) return 0;
|
|
// Get the joint motor torque
|
|
return joint.GetMotorTorque(1 / this._sharedData.timeStep);
|
|
};
|
|
|
|
// Prismatic joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addPrismaticJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
axisAngle,
|
|
referenceAngle,
|
|
enableLimit,
|
|
lowerTranslation,
|
|
upperTranslation,
|
|
enableMotor,
|
|
motorSpeed,
|
|
maxMotorForce,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2PrismaticJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
axisAngle = gdjs.toRad(axisAngle) - this._body.GetAngle();
|
|
jointDef.set_localAxisA(
|
|
this.b2Vec2(Math.cos(axisAngle), Math.sin(axisAngle))
|
|
);
|
|
jointDef.set_referenceAngle(gdjs.toRad(referenceAngle));
|
|
jointDef.set_enableLimit(enableLimit);
|
|
// Lower translation must be lower than upper translation
|
|
if (upperTranslation < lowerTranslation) {
|
|
var temp = lowerTranslation;
|
|
lowerTranslation = upperTranslation;
|
|
upperTranslation = temp;
|
|
}
|
|
// The translation range must include zero
|
|
jointDef.set_lowerTranslation(
|
|
lowerTranslation < 0 ? lowerTranslation * this._sharedData.invScaleX : 0
|
|
);
|
|
jointDef.set_upperTranslation(
|
|
upperTranslation > 0 ? upperTranslation * this._sharedData.invScaleX : 0
|
|
);
|
|
jointDef.set_enableMotor(enableMotor);
|
|
jointDef.set_motorSpeed(motorSpeed * this._sharedData.invScaleX);
|
|
jointDef.set_maxMotorForce(maxMotorForce);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2PrismaticJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointAxisAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint axis angle
|
|
return gdjs.toDegrees(
|
|
Math.atan2(joint.GetLocalAxisA().get_y(), joint.GetLocalAxisA().get_x()) +
|
|
joint.GetBodyA().GetAngle()
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointReferenceAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint reference angle
|
|
return gdjs.toDegrees(joint.GetReferenceAngle());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointTranslation = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint current translation
|
|
return joint.GetJointTranslation() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointSpeed = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint speed
|
|
return joint.GetJointSpeed() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isPrismaticJointLimitsEnabled = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint)
|
|
return false;
|
|
// Get the joint limits state
|
|
return joint.IsLimitEnabled();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enablePrismaticJointLimits = function(
|
|
jointId,
|
|
enable
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return;
|
|
// Set the joint limits state
|
|
joint.EnableLimit(enable);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointMinTranslation = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint lower limit
|
|
return joint.GetLowerLimit() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointMaxTranslation = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint upper angle
|
|
return joint.GetUpperLimit() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setPrismaticJointLimits = function(
|
|
jointId,
|
|
lowerTranslation,
|
|
upperTranslation
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return;
|
|
// Lower translation must be lower than upper translation
|
|
if (upperTranslation < lowerTranslation) {
|
|
var temp = lowerTranslation;
|
|
lowerTranslation = upperTranslation;
|
|
upperTranslation = temp;
|
|
}
|
|
// The translation range must include zero
|
|
lowerTranslation = lowerTranslation < 0 ? lowerTranslation : 0;
|
|
upperTranslation = upperTranslation > 0 ? upperTranslation : 0;
|
|
// Set the joint limits
|
|
joint.SetLimits(
|
|
lowerTranslation * this._sharedData.invScaleX,
|
|
upperTranslation * this._sharedData.invScaleX
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isPrismaticJointMotorEnabled = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint)
|
|
return false;
|
|
// Get the joint motor state
|
|
return joint.IsMotorEnabled();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enablePrismaticJointMotor = function(
|
|
jointId,
|
|
enable
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return;
|
|
// Set the joint motor state
|
|
joint.EnableMotor(enable);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointMotorSpeed = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint motor speed
|
|
return joint.GetMotorSpeed() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setPrismaticJointMotorSpeed = function(
|
|
jointId,
|
|
speed
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return;
|
|
// Set the joint motor speed
|
|
joint.SetMotorSpeed(speed * this._sharedData.invScaleX);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointMaxMotorForce = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint max motor force
|
|
return joint.GetMaxMotorForce();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setPrismaticJointMaxMotorForce = function(
|
|
jointId,
|
|
maxForce
|
|
) {
|
|
// Invalid value
|
|
if (maxForce < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return;
|
|
// Set the joint max motor force
|
|
joint.SetMaxMotorForce(maxForce);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPrismaticJointMotorForce = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_prismaticJoint) return 0;
|
|
// Get the joint motor torque
|
|
return joint.GetMotorForce(1 / this._sharedData.timeStep);
|
|
};
|
|
|
|
// Pulley joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addPulleyJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
groundX1,
|
|
groundY1,
|
|
groundX2,
|
|
groundY2,
|
|
lengthA,
|
|
lengthB,
|
|
ratio,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2PulleyJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_groundAnchorA(
|
|
this.b2Vec2(
|
|
groundX1 * this._sharedData.invScaleX,
|
|
groundY1 * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
jointDef.set_groundAnchorB(
|
|
this.b2Vec2(
|
|
groundX2 * this._sharedData.invScaleX,
|
|
groundY2 * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
jointDef.set_lengthA(
|
|
lengthA > 0
|
|
? lengthA * this._sharedData.invScaleX
|
|
: this.b2Vec2(
|
|
(groundX1 - x1) * this._sharedData.invScaleX,
|
|
(groundY1 - y1) * this._sharedData.invScaleY
|
|
).Length()
|
|
);
|
|
jointDef.set_lengthB(
|
|
lengthB > 0
|
|
? lengthB * this._sharedData.invScaleX
|
|
: this.b2Vec2(
|
|
(groundX2 - x2) * this._sharedData.invScaleX,
|
|
(groundY2 - y2) * this._sharedData.invScaleY
|
|
).Length()
|
|
);
|
|
jointDef.set_ratio(ratio > 0 ? ratio : 1);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2PulleyJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointFirstGroundAnchorX = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint ground anchor
|
|
return joint.GetGroundAnchorA().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointFirstGroundAnchorY = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint ground anchor
|
|
return joint.GetGroundAnchorA().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointSecondGroundAnchorX = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint ground anchor
|
|
return joint.GetGroundAnchorB().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointSecondGroundAnchorY = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint ground anchor
|
|
return joint.GetGroundAnchorB().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointFirstLength = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint length
|
|
return joint.GetCurrentLengthA() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointSecondLength = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint length
|
|
return joint.GetCurrentLengthB() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getPulleyJointRatio = function(jointId) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_pulleyJoint) return 0;
|
|
// Get the joint ratio
|
|
return joint.GetRatio();
|
|
};
|
|
|
|
// Gear joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addGearJoint = function(
|
|
jointId1,
|
|
jointId2,
|
|
ratio,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Get the first joint
|
|
var joint1 = this._sharedData.getJoint(jointId1);
|
|
// Joint not found or has wrong type
|
|
if (
|
|
joint1 === null ||
|
|
(joint1.GetType() !== Box2D.e_revoluteJoint &&
|
|
joint1.GetType() !== Box2D.e_prismaticJoint)
|
|
)
|
|
return;
|
|
// Get the second joint
|
|
var joint2 = this._sharedData.getJoint(jointId2);
|
|
if (
|
|
joint2 === null ||
|
|
(joint2.GetType() !== Box2D.e_revoluteJoint &&
|
|
joint2.GetType() !== Box2D.e_prismaticJoint)
|
|
)
|
|
return;
|
|
// The joints are the same
|
|
if (joint1 === joint2) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2GearJointDef();
|
|
// Set gear joint bodies is not necessary at first, as the gear get the bodies from the two child joints
|
|
// But we must pass two different bodies to bypass a test inherited from b2Joint
|
|
jointDef.set_bodyA(this._sharedData.staticBody);
|
|
jointDef.set_bodyB(this._body);
|
|
jointDef.set_joint1(joint1);
|
|
jointDef.set_joint2(joint2);
|
|
jointDef.set_ratio(ratio);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2GearJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGearJointFirstJoint = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_gearJoint) return 0;
|
|
// Get the joint first joint
|
|
return this._sharedData.getJointId(joint.GetJoint1());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGearJointSecondJoint = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_gearJoint) return 0;
|
|
// Get the joint second joint
|
|
return this._sharedData.getJointId(joint.GetJoint2());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getGearJointRatio = function(jointId) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_gearJoint) return 0;
|
|
// Get the joint ratio
|
|
return joint.GetRatio();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setGearJointRatio = function(
|
|
jointId,
|
|
ratio
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_gearJoint) return;
|
|
// Set the joint ratio
|
|
joint.SetRatio(ratio);
|
|
// Awake the bodies, the gear joint picks the dynamic bodies as first and second body (second bodies from the child joints)
|
|
joint.GetBodyA().SetAwake(true);
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
// Mouse joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addMouseJoint = function(
|
|
targetX,
|
|
targetY,
|
|
maxForce,
|
|
frequency,
|
|
dampingRatio,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2MouseJointDef();
|
|
jointDef.set_bodyA(this._sharedData.staticBody);
|
|
jointDef.set_bodyB(this._body);
|
|
jointDef.set_target(
|
|
this.b2Vec2(
|
|
targetX * this._sharedData.invScaleX,
|
|
targetY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
jointDef.set_maxForce(maxForce >= 0 ? maxForce : 0);
|
|
jointDef.set_frequencyHz(frequency > 0 ? frequency : 1);
|
|
jointDef.set_dampingRatio(dampingRatio >= 0 ? dampingRatio : 0);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2MouseJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMouseJointTargetX = function(
|
|
jointId
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return 0;
|
|
// Get the joint target X
|
|
return joint.GetTarget().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMouseJointTargetY = function(
|
|
jointId
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return 0;
|
|
// Get the joint target Y
|
|
return joint.GetTarget().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMouseJointTarget = function(
|
|
jointId,
|
|
targetX,
|
|
targetY
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return;
|
|
// Set the joint target
|
|
joint.SetTarget(
|
|
this.b2Vec2(
|
|
targetX * this._sharedData.invScaleX,
|
|
targetY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
// Awake the body
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMouseJointMaxForce = function(
|
|
jointId
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return 0;
|
|
// Get the joint max force
|
|
return joint.GetMaxForce();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMouseJointMaxForce = function(
|
|
jointId,
|
|
maxForce
|
|
) {
|
|
// Invalid value
|
|
if (maxForce < 0) return;
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return;
|
|
// Set the joint max force
|
|
joint.SetMaxForce(maxForce);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMouseJointFrequency = function(
|
|
jointId
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return 0;
|
|
// Get the joint frequency
|
|
return joint.GetFrequency();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMouseJointFrequency = function(
|
|
jointId,
|
|
frequency
|
|
) {
|
|
// Invalid value
|
|
if (frequency <= 0) return;
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return;
|
|
// Set the joint frequency
|
|
joint.SetFrequency(frequency);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMouseJointDampingRatio = function(
|
|
jointId
|
|
) {
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return 0;
|
|
// Get the joint damping ratio
|
|
return joint.GetDampingRatio();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMouseJointDampingRatio = function(
|
|
jointId,
|
|
dampingRatio
|
|
) {
|
|
// Invalid value
|
|
if (dampingRatio < 0) return;
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_mouseJoint) return;
|
|
// Set the joint damping ratio
|
|
joint.SetDampingRatio(dampingRatio);
|
|
};
|
|
|
|
// Wheel joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addWheelJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
axisAngle,
|
|
frequency,
|
|
dampingRatio,
|
|
enableMotor,
|
|
motorSpeed,
|
|
maxMotorTorque,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2WheelJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
axisAngle = gdjs.toRad(axisAngle) - this._body.GetAngle();
|
|
jointDef.set_localAxisA(
|
|
this.b2Vec2(Math.cos(axisAngle), Math.sin(axisAngle))
|
|
);
|
|
jointDef.set_frequencyHz(frequency > 0 ? frequency : 1);
|
|
jointDef.set_dampingRatio(dampingRatio >= 0 ? dampingRatio : 0);
|
|
jointDef.set_enableMotor(enableMotor);
|
|
jointDef.set_motorSpeed(gdjs.toRad(motorSpeed));
|
|
jointDef.set_maxMotorTorque(maxMotorTorque);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2WheelJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointAxisAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint axis angle
|
|
return gdjs.toDegrees(
|
|
Math.atan2(joint.GetLocalAxisA().get_y(), joint.GetLocalAxisA().get_x()) +
|
|
joint.GetBodyA().GetAngle()
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointTranslation = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint current translation
|
|
return joint.GetJointTranslation() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointSpeed = function(jointId) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint speed
|
|
return gdjs.toDegrees(joint.GetJointSpeed());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.isWheelJointMotorEnabled = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return false;
|
|
// Get the joint motor state
|
|
return joint.IsMotorEnabled();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.enableWheelJointMotor = function(
|
|
jointId,
|
|
enable
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return;
|
|
// Set the joint motor state
|
|
joint.EnableMotor(enable);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointMotorSpeed = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint motor speed
|
|
return gdjs.toDegrees(joint.GetMotorSpeed());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWheelJointMotorSpeed = function(
|
|
jointId,
|
|
speed
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return;
|
|
// Set the joint motor speed
|
|
joint.SetMotorSpeed(gdjs.toRad(speed));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointMaxMotorTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint max motor torque
|
|
return joint.GetMaxMotorTorque();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWheelJointMaxMotorTorque = function(
|
|
jointId,
|
|
maxTorque
|
|
) {
|
|
// Invalid value
|
|
if (maxTorque < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return;
|
|
// Set the joint max motor torque
|
|
joint.SetMaxMotorTorque(maxTorque);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointMotorTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint motor torque
|
|
return joint.GetMotorTorque(1 / this._sharedData.timeStep);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointFrequency = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint frequency
|
|
return joint.GetSpringFrequencyHz();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWheelJointFrequency = function(
|
|
jointId,
|
|
frequency
|
|
) {
|
|
// Invalid value
|
|
if (frequency < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return;
|
|
// Set the joint frequency
|
|
joint.SetSpringFrequencyHz(frequency);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWheelJointDampingRatio = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return 0;
|
|
// Get the joint damping ratio
|
|
return joint.GetSpringDampingRatio();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWheelJointDampingRatio = function(
|
|
jointId,
|
|
dampingRatio
|
|
) {
|
|
// Invalid value
|
|
if (dampingRatio < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_wheelJoint) return;
|
|
// Set the joint damping ratio
|
|
joint.SetSpringDampingRatio(dampingRatio);
|
|
};
|
|
|
|
// Weld joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addWeldJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
referenceAngle,
|
|
frequency,
|
|
dampingRatio,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2WeldJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_referenceAngle(gdjs.toRad(referenceAngle));
|
|
jointDef.set_frequencyHz(frequency > 0 ? frequency : 1);
|
|
jointDef.set_dampingRatio(dampingRatio >= 0 ? dampingRatio : 0);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint
|
|
var joint = Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2WeldJoint
|
|
);
|
|
// b2WeldJoint.GetReferenceAngle() is not binded, store it manually
|
|
joint.referenceAngle = jointDef.get_referenceAngle();
|
|
// Store the id in the variable
|
|
variable.setNumber(this._sharedData.addJoint(joint));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWeldJointReferenceAngle = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_weldJoint) return 0;
|
|
// b2WeldJoint.GetReferenceAngle() is not binded
|
|
// return gdjs.toDegrees(joint.GetReferenceAngle());
|
|
return gdjs.toDegrees(joint.referenceAngle);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWeldJointFrequency = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_weldJoint) return 0;
|
|
// Get the joint frequency
|
|
return joint.GetFrequency();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWeldJointFrequency = function(
|
|
jointId,
|
|
frequency
|
|
) {
|
|
// Invalid value
|
|
if (frequency < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_weldJoint) return;
|
|
// Set the joint frequency
|
|
joint.SetFrequency(frequency);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getWeldJointDampingRatio = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_weldJoint) return 0;
|
|
// Get the joint damping ratio
|
|
return joint.GetDampingRatio();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setWeldJointDampingRatio = function(
|
|
jointId,
|
|
dampingRatio
|
|
) {
|
|
// Invalid value
|
|
if (dampingRatio < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_weldJoint) return;
|
|
// Set the joint damping ratio
|
|
joint.SetDampingRatio(dampingRatio);
|
|
};
|
|
|
|
// Rope joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addRopeJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
maxLength,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2RopeJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_maxLength(
|
|
maxLength > 0
|
|
? maxLength * this._sharedData.invScaleX
|
|
: this.b2Vec2(
|
|
(x2 - x1) * this._sharedData.invScaleX,
|
|
(y2 - y1) * this._sharedData.invScaleY
|
|
).Length()
|
|
);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2RopeJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getRopeJointMaxLength = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_ropeJoint) return 0;
|
|
// Get the joint maximum length
|
|
return joint.GetMaxLength() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setRopeJointMaxLength = function(
|
|
jointId,
|
|
maxLength
|
|
) {
|
|
// Invalid value
|
|
if (maxLength < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_ropeJoint) return;
|
|
// Set the joint maximum length
|
|
joint.SetMaxLength(maxLength * this._sharedData.invScaleX);
|
|
// Awake the bodies
|
|
joint.GetBodyA().SetAwake(true);
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
// Friction joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addFrictionJoint = function(
|
|
x1,
|
|
y1,
|
|
other,
|
|
x2,
|
|
y2,
|
|
maxForce,
|
|
maxTorque,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2FrictionJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_localAnchorA(
|
|
this._body.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x1 * this._sharedData.invScaleX,
|
|
y1 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_localAnchorB(
|
|
otherBody.GetLocalPoint(
|
|
this.b2Vec2(
|
|
x2 * this._sharedData.invScaleX,
|
|
y2 * this._sharedData.invScaleY
|
|
)
|
|
)
|
|
);
|
|
jointDef.set_maxForce(maxForce >= 0 ? maxForce : 0);
|
|
jointDef.set_maxTorque(maxTorque >= 0 ? maxTorque : 0);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2FrictionJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getFrictionJointMaxForce = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_frictionJoint) return 0;
|
|
// Get the joint maximum force
|
|
return joint.GetMaxForce();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setFrictionJointMaxForce = function(
|
|
jointId,
|
|
maxForce
|
|
) {
|
|
// Invalid value
|
|
if (maxForce < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_frictionJoint) return;
|
|
// Set the joint maximum force
|
|
joint.SetMaxForce(maxForce);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getFrictionJointMaxTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_frictionJoint) return 0;
|
|
// Get the joint maximum torque
|
|
return joint.GetMaxTorque();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setFrictionJointMaxTorque = function(
|
|
jointId,
|
|
maxTorque
|
|
) {
|
|
// Invalid value
|
|
if (maxTorque < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_frictionJoint) return;
|
|
// Set the joint maximum torque
|
|
joint.SetMaxTorque(maxTorque);
|
|
};
|
|
|
|
// Motor joint
|
|
gdjs.Physics2RuntimeBehavior.prototype.addMotorJoint = function(
|
|
other,
|
|
offsetX,
|
|
offsetY,
|
|
offsetAngle,
|
|
maxForce,
|
|
maxTorque,
|
|
correctionFactor,
|
|
collideConnected,
|
|
variable
|
|
) {
|
|
// If there is no body, set a new one
|
|
if (this._body === null) this.createBody();
|
|
// If there is no second object or it doesn't share the behavior, return
|
|
if (other == null || !other.hasBehavior(this.name)) return;
|
|
// Get the second body
|
|
var otherBody = other.getBehavior(this.name).getBody();
|
|
// If the first and second objects/bodies are the same, return
|
|
if (this._body === otherBody) return;
|
|
// Set joint settings
|
|
var jointDef = new Box2D.b2MotorJointDef();
|
|
jointDef.set_bodyA(this._body);
|
|
jointDef.set_bodyB(otherBody);
|
|
jointDef.set_linearOffset(
|
|
this.b2Vec2(
|
|
offsetX * this._sharedData.invScaleX,
|
|
offsetY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
jointDef.set_angularOffset(gdjs.toRad(offsetAngle));
|
|
jointDef.set_maxForce(maxForce >= 0 ? maxForce : 0);
|
|
jointDef.set_maxTorque(maxTorque >= 0 ? maxTorque : 0);
|
|
jointDef.set_correctionFactor(
|
|
correctionFactor < 0 ? 0 : correctionFactor > 1 ? 1 : correctionFactor
|
|
);
|
|
jointDef.set_collideConnected(collideConnected);
|
|
// Create the joint and get the id
|
|
var jointId = this._sharedData.addJoint(
|
|
Box2D.castObject(
|
|
this._sharedData.world.CreateJoint(jointDef),
|
|
Box2D.b2MotorJoint
|
|
)
|
|
);
|
|
// Store the id in the variable
|
|
variable.setNumber(jointId);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointOffsetX = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint offset
|
|
return joint.GetLinearOffset().get_x() * this._sharedData.scaleX;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointOffsetY = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint offset
|
|
return joint.GetLinearOffset().get_y() * this._sharedData.scaleY;
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMotorJointOffset = function(
|
|
jointId,
|
|
offsetX,
|
|
offsetY
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return;
|
|
// Set the joint offset
|
|
joint.SetLinearOffset(
|
|
this.b2Vec2(
|
|
offsetX * this._sharedData.invScaleX,
|
|
offsetY * this._sharedData.invScaleY
|
|
)
|
|
);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointAngularOffset = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint angular offset
|
|
return gdjs.toDegrees(joint.GetAngularOffset());
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMotorJointAngularOffset = function(
|
|
jointId,
|
|
offsetAngle
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return;
|
|
// Set the joint angular offset
|
|
joint.SetAngularOffset(gdjs.toRad(offsetAngle));
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointMaxForce = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint maximum force
|
|
return joint.GetMaxForce();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMotorJointMaxForce = function(
|
|
jointId,
|
|
maxForce
|
|
) {
|
|
// Invalid value
|
|
if (maxForce < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return;
|
|
// Set the joint maximum force
|
|
joint.SetMaxForce(maxForce);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointMaxTorque = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint maximum torque
|
|
return joint.GetMaxTorque();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMotorJointMaxTorque = function(
|
|
jointId,
|
|
maxTorque
|
|
) {
|
|
// Invalid value
|
|
if (maxTorque < 0) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return;
|
|
// Set the joint maximum torque
|
|
joint.SetMaxTorque(maxTorque);
|
|
// Awake the bodies
|
|
joint.GetBodyA().SetAwake(true);
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.getMotorJointCorrectionFactor = function(
|
|
jointId
|
|
) {
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return 0;
|
|
// Get the joint correction factor
|
|
return joint.GetCorrectionFactor();
|
|
};
|
|
|
|
gdjs.Physics2RuntimeBehavior.prototype.setMotorJointCorrectionFactor = function(
|
|
jointId,
|
|
correctionFactor
|
|
) {
|
|
// Invalid value
|
|
if (correctionFactor < 0 || correctionFactor > 1) return;
|
|
// Get the joint
|
|
var joint = this._sharedData.getJoint(jointId);
|
|
// Joint not found or has wrong type
|
|
if (joint === null || joint.GetType() !== Box2D.e_motorJoint) return;
|
|
// Set the joint correction factor
|
|
joint.SetCorrectionFactor(correctionFactor);
|
|
// Awake the bodies
|
|
joint.GetBodyA().SetAwake(true);
|
|
joint.GetBodyB().SetAwake(true);
|
|
};
|
|
|
|
// Collision
|
|
gdjs.Physics2RuntimeBehavior.collisionTest = function(
|
|
object1,
|
|
object2,
|
|
behaviorName
|
|
) {
|
|
// Check if the objects exist and share the behavior
|
|
if (object1 === null || !object1.hasBehavior(behaviorName)) return false;
|
|
if (object2 === null || !object2.hasBehavior(behaviorName)) return false;
|
|
// Test if the second object is in the list of contacts of the first one
|
|
var behavior1 = object1.getBehavior(behaviorName);
|
|
for (var i = 0, len = behavior1.currentContacts.length; i < len; ++i) {
|
|
if (behavior1.currentContacts[i].owner === object2) {
|
|
return true;
|
|
}
|
|
}
|
|
// No contact found
|
|
return false;
|
|
};
|