planck
Version:
2D JavaScript/TypeScript physics engine for cross-platform HTML5 game development
105 lines (82 loc) • 2.44 kB
text/typescript
/*
* Copyright (c) Erin Catto
* Licensed under the MIT license
*/
// This test shows how a rope joint can be used to stabilize a chain of
// bodies with a heavy payload. Notice that the rope joint just prevents
// excessive stretching and has no other effect.
// By disabling the rope joint you can see that the Box2D solver has trouble
// supporting heavy bodies with light bodies. Try playing around with the
// densities, time step, and iterations to see how they affect stability.
// This test also shows how to use contact filtering. Filtering is configured
// so that the payload does not collide with the chain.
import { World, Edge, Box, RevoluteJoint, RopeJoint, Testbed, BodyDef } from "planck";
const world = new World({
gravity: { x: 0, y: -10 },
});
const testbed = Testbed.mount();
testbed.info("X: Toggle the rope joint");
testbed.start(world);
const ground = world.createBody({
type: "static",
});
ground.createFixture({
shape: new Edge({ x: -40.0, y: 0.0 }, { x: 40.0, y: 0.0 }),
density: 0.0,
});
const N = 10;
const y = 15.0;
let shape = new Box(0.5, 0.125);
let prevBody = ground;
for (let i = 0; i < N; ++i) {
const fixDef = {
density: 20.0,
friction: 0.2,
filterCategoryBits: 0x0001,
filterMaskBits: 0xffff & ~0x0002,
};
const bodyDef = {
type: "dynamic" as const,
position: { x: 0.5 + 1.0 * i, y: y },
angularDamping: 0,
};
const jointDef = {
collideConnected: false,
};
if (i === N - 1) {
shape = new Box(1.5, 1.5);
fixDef.density = 100.0;
fixDef.filterCategoryBits = 0x0002;
bodyDef.position = { x: 1.0 * i, y: y };
bodyDef.angularDamping = 0.4;
}
const body = world.createBody(bodyDef);
body.createFixture({
shape: shape,
...fixDef,
});
const anchor = { x: i, y: y };
world.createJoint(new RevoluteJoint(jointDef, prevBody, body, anchor));
prevBody = body;
}
const ropeJointDef = {
maxLength: N - 1.0 + 0.01,
localAnchorA: { x: 0.0, y: y },
localAnchorB: { x: 0, y: 0 },
};
let rope = world.createJoint(new RopeJoint(ropeJointDef, ground, prevBody));
testbed.keydown = function (code, char) {
if (char === "X") {
if (rope) {
world.destroyJoint(rope);
rope = null;
} else {
rope = world.createJoint(new RopeJoint(ropeJointDef, ground, prevBody));
}
}
updateStatus();
};
function updateStatus() {
testbed.status("Rope", !!rope);
}
updateStatus();