How do I make an arm mechanism in matter.js. First I’d like to try a simplified version where a rectangle is connected to a main body with three constraints; one constraint being a revolute point constraint from where the arm section rotates. The other two constraints are long elastic constraints connecting to the main body, and the tips of the arm segment. The position of the arm would be determined by the stiffness of those constraints, so increasing the stiffness of the upper one and decreasing the stiffness of the lower one would raise the arm. The setup is shown in the figure below.
setup
In the figure, there are two squares to which the tendon constraints connect to. They are there to stop the arm section from rotating too much around the main body, since the arm and main body have the same group, so they don’t interact with each other physically. The stoppers are connected to the main body with pin constraints.
Here’s my attempt to implement this
import Matter from "matter-js";
export default function Player(x, y) {
const T = 24;
const group = Matter.Body.nextGroup(true);
const base = Matter.Bodies.rectangle(x, y, 10 * T, 10 * T);
const head = Matter.Bodies.rectangle(x, y - 10 * T, 8 * T, 10 * T, {});
const longTopStop = Matter.Bodies.rectangle(
x + (9 * T) / 2,
y - (29 * T) / 2,
T,
T
);
const long = Matter.Bodies.rectangle(
x + 11 * T,
y - (21 * T) / 2,
14 * T,
3 * T,
{ collisionFilter: { group } }
);
const longBottomStop = Matter.Bodies.rectangle(
x + (9 * T) / 2,
y - (13 * T) / 2,
T,
T
);
const mainBody = Matter.Body.create({
parts: [base, head],
collisionFilter: { group },
});
const longTopTen = Matter.Constraint.create({
bodyA: longTopStop,
bodyB: long,
pointA: { x: T / 2, y: 0 },
pointB: { x: 7 * T, y: (-3 * T) / 2 },
length: 8 * T,
stiffness: 0.5,
});
const longBottTen = Matter.Constraint.create({
bodyA: longBottomStop,
bodyB: long,
pointA: { x: T / 2, y: 0 },
pointB: { x: 7 * T, y: (3 * T) / 2 },
length: 10 * T,
stiffness: 0.5,
});
const longTopTop = Matter.Constraint.create({
bodyA: head,
bodyB: longTopStop,
pointA: { x: 4 * T, y: -5 * T },
pointB: { x: -T / 2, y: -T / 2 },
length: 0,
stiffness: 1,
});
const longTopMiddle = Matter.Constraint.create({
bodyA: head,
bodyB: longTopStop,
pointA: { x: 4 * T, y: (-9 * T) / 2 },
pointB: { x: -T / 2, y: 0 },
length: 0,
stiffness: 1,
});
const longTopBott = Matter.Constraint.create({
bodyA: head,
bodyB: longTopStop,
pointA: { x: 4 * T, y: -4 * T },
pointB: { x: -T / 2, y: T / 2 },
length: 0,
stiffness: 1,
});
const longBottTop = Matter.Constraint.create({
bodyA: head,
bodyB: longBottomStop,
pointA: { x: 4 * T, y: 3 * T },
pointB: { x: -T / 2, y: -T / 2 },
length: 0,
stiffness: 1,
});
const longBottMiddle = Matter.Constraint.create({
bodyA: head,
bodyB: longBottomStop,
pointA: { x: 4 * T, y: (7 * T) / 2 },
pointB: { x: -T / 2, y: 0 },
length: 0,
stiffness: 1,
});
const longBottBott = Matter.Constraint.create({
bodyA: head,
bodyB: longBottomStop,
pointA: { x: 4 * T, y: 4 * T },
pointB: { x: -T / 2, y: T / 2 },
length: 0,
stiffness: 1,
});
const headLongJoint = Matter.Constraint.create({
bodyA: head,
bodyB: long,
pointA: { x: 4 * T, y: -T / 2 },
pointB: { x: -7 * T, y: 0 },
length: 0,
stiffness: 1,
});
this.parts = {
mainBody,
base,
head,
longTopStop,
long,
longBottomStop,
};
this.joints = [
longTopTop,
longTopMiddle,
longTopBott,
longTopTen,
longBottTen,
longBottTop,
longBottMiddle,
longBottBott,
headLongJoint,
];
}
Player.prototype.add = function (world) {
Matter.Composite.add(world, [
this.parts.mainBody,
this.parts.longTopStop,
this.parts.long,
this.parts.longBottomStop,
...this.joints,
]);
};
The stoppers are supposed to be firmly stuck to the main body, but would drift away with only one constraint, so I added three per stopper, but they still drift. The main body seems to be constantly pushed in the opposite direction of the arm. Here’s a video of how it looks like right now with the setup below
https://files.catbox.moe/arqf5l.mp4
function Block(x, y, width, height, fillStyle) {
const options = { isStatic: true };
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.fillStyle = fillStyle;
this.body = Matter.Bodies.rectangle(x, y, width, height, options);
}
Block.prototype.add = function (world) {
Matter.Composite.add(world, this.body);
};
const engine = Matter.Engine.create({ gravity: { x: 0, y: 1 } });
const render = Matter.Render.create({
element: document.body,
engine: engine,
options: { width: innerWidth, height: innerHeight, showAngleIndicator: true },
});
const runner = Matter.Runner.create();
Matter.Render.run(render);
Matter.Runner.run(runner, engine);
Matter.Render.lookAt(render, {
min: { x: 0, y: 0 },
max: { x: innerWidth, y: innerHeight },
});
const ground = new Block(
innerWidth / 2,
(innerHeight * 9) / 10,
(innerWidth * 9) / 10,
10,
"gray"
);
const leftWall = new Block(
innerWidth / 10,
innerHeight / 2,
10,
(innerHeight * 9) / 10,
"gray"
);
const rightWall = new Block(
(innerWidth * 9) / 10,
innerHeight / 2,
10,
(innerHeight * 9) / 10,
"gray"
);
const walls = [ground, leftWall, rightWall];
const player = new Player(innerWidth / 3, innerHeight / 2);
player.add(engine.world);
walls.forEach((w) => w.add(engine.world));
How do I fix the bugs, or how do I implement an arm mechanism in matter.js by other means?