mirror of
https://github.com/liabru/matter-js.git
synced 2025-01-12 16:08:50 -05:00
further work on compound implementation
This commit is contained in:
parent
f554d6c9a6
commit
d2f79b4689
5 changed files with 128 additions and 71 deletions
|
@ -244,21 +244,27 @@
|
||||||
|
|
||||||
Demo.reset();
|
Demo.reset();
|
||||||
|
|
||||||
var bodyA = Bodies.rectangle(100, 200, 50, 50),
|
var bodyA = Bodies.rectangle(100, 200, 50, 50, { isStatic: true }),
|
||||||
bodyB = Bodies.rectangle(200, 200, 50, 50),
|
bodyB = Bodies.rectangle(200, 200, 50, 50),
|
||||||
bodyC = Bodies.rectangle(300, 200, 50, 50),
|
bodyC = Bodies.rectangle(300, 200, 50, 50),
|
||||||
bodyD = Bodies.rectangle(400, 200, 50, 50),
|
bodyD = Bodies.rectangle(400, 200, 50, 50),
|
||||||
bodyE = Bodies.rectangle(550, 200, 50, 50),
|
bodyE = Bodies.rectangle(550, 200, 50, 50),
|
||||||
bodyF = Bodies.rectangle(700, 200, 50, 50),
|
bodyF = Bodies.rectangle(700, 200, 50, 50),
|
||||||
bodyG = Bodies.circle(400, 100, 25);
|
bodyG = Bodies.circle(400, 100, 25),
|
||||||
|
partA = Bodies.rectangle(600, 200, 120, 50),
|
||||||
|
partB = Bodies.rectangle(660, 200, 50, 190),
|
||||||
|
compound = Body.create({
|
||||||
|
parts: [partA, partB],
|
||||||
|
isStatic: true
|
||||||
|
});
|
||||||
|
|
||||||
World.add(_world, [bodyA, bodyB, bodyC, bodyD, bodyE, bodyF, bodyG]);
|
World.add(_world, [bodyA, bodyB, bodyC, bodyD, bodyE, bodyF, bodyG, compound]);
|
||||||
|
|
||||||
var counter = 0,
|
var counter = 0,
|
||||||
scaleFactor = 1.01;
|
scaleFactor = 1.01;
|
||||||
|
|
||||||
_sceneEvents.push(
|
_sceneEvents.push(
|
||||||
Events.on(_engine, 'tick', function(event) {
|
Events.on(_engine, 'beforeUpdate', function(event) {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
|
|
||||||
if (counter === 40)
|
if (counter === 40)
|
||||||
|
@ -266,6 +272,7 @@
|
||||||
|
|
||||||
if (scaleFactor > 1) {
|
if (scaleFactor > 1) {
|
||||||
Body.scale(bodyF, scaleFactor, scaleFactor);
|
Body.scale(bodyF, scaleFactor, scaleFactor);
|
||||||
|
Body.scale(compound, 0.995, 0.995);
|
||||||
|
|
||||||
// modify bodyE vertices
|
// modify bodyE vertices
|
||||||
bodyE.vertices[0].x -= 0.2;
|
bodyE.vertices[0].x -= 0.2;
|
||||||
|
@ -277,7 +284,11 @@
|
||||||
|
|
||||||
// make bodyA move up and down and rotate constantly
|
// make bodyA move up and down and rotate constantly
|
||||||
Body.setPosition(bodyA, { x: 100, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) });
|
Body.setPosition(bodyA, { x: 100, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) });
|
||||||
Body.setAngularVelocity(bodyA, 0.02);
|
Body.rotate(bodyA, 0.02);
|
||||||
|
|
||||||
|
// make compound body move up and down and rotate constantly
|
||||||
|
Body.setPosition(compound, { x: 600, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) });
|
||||||
|
Body.rotate(compound, 0.02);
|
||||||
|
|
||||||
// every 1.5 sec
|
// every 1.5 sec
|
||||||
if (counter >= 60 * 1.5) {
|
if (counter >= 60 * 1.5) {
|
||||||
|
@ -293,9 +304,10 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
var renderOptions = _engine.render.options;
|
var renderOptions = _engine.render.options;
|
||||||
renderOptions.wireframes = false;
|
|
||||||
renderOptions.showAxes = true;
|
renderOptions.showAxes = true;
|
||||||
renderOptions.showCollisions = true;
|
renderOptions.showCollisions = true;
|
||||||
|
renderOptions.showPositions = true;
|
||||||
|
renderOptions.showConvexHulls = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
Demo.compositeManipulation = function() {
|
Demo.compositeManipulation = function() {
|
||||||
|
|
157
src/body/Body.js
157
src/body/Body.js
|
@ -32,6 +32,7 @@ var Body = {};
|
||||||
id: Common.nextId(),
|
id: Common.nextId(),
|
||||||
type: 'body',
|
type: 'body',
|
||||||
label: 'Body',
|
label: 'Body',
|
||||||
|
parts: [],
|
||||||
angle: 0,
|
angle: 0,
|
||||||
vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
|
vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
|
||||||
position: { x: 0, y: 0 },
|
position: { x: 0, y: 0 },
|
||||||
|
@ -118,7 +119,7 @@ var Body = {};
|
||||||
isStatic: body.isStatic,
|
isStatic: body.isStatic,
|
||||||
isSleeping: body.isSleeping,
|
isSleeping: body.isSleeping,
|
||||||
parent: body.parent || body,
|
parent: body.parent || body,
|
||||||
parts: body.parts || [body]
|
parts: body.parts
|
||||||
});
|
});
|
||||||
|
|
||||||
Vertices.rotate(body.vertices, body.angle, body.position);
|
Vertices.rotate(body.vertices, body.angle, body.position);
|
||||||
|
@ -313,26 +314,31 @@ var Body = {};
|
||||||
* @param {bool} [autoHull=true]
|
* @param {bool} [autoHull=true]
|
||||||
*/
|
*/
|
||||||
Body.setParts = function(body, parts, autoHull) {
|
Body.setParts = function(body, parts, autoHull) {
|
||||||
autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
|
var i;
|
||||||
|
|
||||||
// ensure the body is always at index 0
|
// add all the parts, ensuring that the first part is always the parent body
|
||||||
var index = Common.indexOf(parts, body);
|
parts = parts.slice(0);
|
||||||
if (index > -1) {
|
body.parts.length = 0;
|
||||||
parts.splice(index, 1);
|
body.parts.push(body);
|
||||||
|
body.parent = body;
|
||||||
|
|
||||||
|
for (i = 0; i < parts.length; i++) {
|
||||||
|
var part = parts[i];
|
||||||
|
if (part !== body) {
|
||||||
|
part.parent = body;
|
||||||
|
body.parts.push(part);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.unshift(body);
|
if (body.parts.length === 1)
|
||||||
body.parts = parts;
|
|
||||||
|
|
||||||
if (parts.length === 1)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var i;
|
autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
|
||||||
|
|
||||||
// find the convex hull of all parts to set on the parent body
|
// find the convex hull of all parts to set on the parent body
|
||||||
if (autoHull) {
|
if (autoHull) {
|
||||||
var vertices = [];
|
var vertices = [];
|
||||||
for (i = 1; i < parts.length; i++) {
|
for (i = 0; i < parts.length; i++) {
|
||||||
vertices = vertices.concat(parts[i].vertices);
|
vertices = vertices.concat(parts[i].vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,36 +348,22 @@ var Body = {};
|
||||||
hullCentre = Vertices.centre(hull);
|
hullCentre = Vertices.centre(hull);
|
||||||
|
|
||||||
Body.setVertices(body, hull);
|
Body.setVertices(body, hull);
|
||||||
Body.setPosition(body, hullCentre);
|
Vertices.translate(body.vertices, hullCentre);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the combined properties of all parts to set on the parent body
|
// sum the properties of all compound parts of the parent body
|
||||||
var mass = 0,
|
var total = _totalProperties(body);
|
||||||
area = 0,
|
|
||||||
inertia = 0,
|
|
||||||
centroid = { x: 0, y: 0 };
|
|
||||||
|
|
||||||
for (i = 1; i < parts.length; i++) {
|
body.area = total.area;
|
||||||
var part = parts[i];
|
|
||||||
part.parent = body;
|
|
||||||
mass += part.mass;
|
|
||||||
area += part.area;
|
|
||||||
inertia += part.inertia;
|
|
||||||
Vector.add(centroid, part.position, centroid);
|
|
||||||
}
|
|
||||||
|
|
||||||
centroid = Vector.div(centroid, parts.length - 1);
|
|
||||||
|
|
||||||
body.area = area;
|
|
||||||
body.parent = body;
|
body.parent = body;
|
||||||
body.position.x = centroid.x;
|
body.position.x = total.centre.x;
|
||||||
body.position.y = centroid.y;
|
body.position.y = total.centre.y;
|
||||||
body.positionPrev.x = centroid.x;
|
body.positionPrev.x = total.centre.x;
|
||||||
body.positionPrev.y = centroid.y;
|
body.positionPrev.y = total.centre.y;
|
||||||
|
|
||||||
Body.setMass(body, mass);
|
Body.setMass(body, total.mass);
|
||||||
Body.setInertia(body, inertia);
|
Body.setInertia(body, total.inertia);
|
||||||
Body.setPosition(body, centroid);
|
Body.setPosition(body, total.centre);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -382,14 +374,16 @@ var Body = {};
|
||||||
*/
|
*/
|
||||||
Body.setPosition = function(body, position) {
|
Body.setPosition = function(body, position) {
|
||||||
var delta = Vector.sub(position, body.position);
|
var delta = Vector.sub(position, body.position);
|
||||||
|
|
||||||
body.position.x = position.x;
|
|
||||||
body.position.y = position.y;
|
|
||||||
body.positionPrev.x += delta.x;
|
body.positionPrev.x += delta.x;
|
||||||
body.positionPrev.y += delta.y;
|
body.positionPrev.y += delta.y;
|
||||||
|
|
||||||
Vertices.translate(body.vertices, delta);
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
Bounds.update(body.bounds, body.vertices, body.velocity);
|
var part = body.parts[i];
|
||||||
|
part.position.x += delta.x;
|
||||||
|
part.position.y += delta.y;
|
||||||
|
Vertices.translate(part.vertices, delta);
|
||||||
|
Bounds.update(part.bounds, part.vertices, body.velocity);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -400,13 +394,15 @@ var Body = {};
|
||||||
*/
|
*/
|
||||||
Body.setAngle = function(body, angle) {
|
Body.setAngle = function(body, angle) {
|
||||||
var delta = angle - body.angle;
|
var delta = angle - body.angle;
|
||||||
|
|
||||||
body.angle = angle;
|
|
||||||
body.anglePrev += delta;
|
body.anglePrev += delta;
|
||||||
|
|
||||||
Vertices.rotate(body.vertices, delta, body.position);
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
Axes.rotate(body.axes, delta);
|
var part = body.parts[i];
|
||||||
Bounds.update(body.bounds, body.vertices, body.velocity);
|
part.angle += delta;
|
||||||
|
Vertices.rotate(part.vertices, delta, body.position);
|
||||||
|
Axes.rotate(part.axes, delta);
|
||||||
|
Bounds.update(part.bounds, part.vertices, body.velocity);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -464,21 +460,35 @@ var Body = {};
|
||||||
* @param {vector} [point]
|
* @param {vector} [point]
|
||||||
*/
|
*/
|
||||||
Body.scale = function(body, scaleX, scaleY, point) {
|
Body.scale = function(body, scaleX, scaleY, point) {
|
||||||
// scale vertices
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
Vertices.scale(body.vertices, scaleX, scaleY, point);
|
var part = body.parts[i];
|
||||||
|
|
||||||
// update properties
|
// scale vertices
|
||||||
body.axes = Axes.fromVertices(body.vertices);
|
Vertices.scale(part.vertices, scaleX, scaleY, body.position);
|
||||||
body.area = Vertices.area(body.vertices);
|
|
||||||
Body.setMass(body, body.density * body.area);
|
|
||||||
|
|
||||||
// update inertia (requires vertices to be at origin)
|
// update properties
|
||||||
Vertices.translate(body.vertices, { x: -body.position.x, y: -body.position.y });
|
part.axes = Axes.fromVertices(part.vertices);
|
||||||
Body.setInertia(body, Vertices.inertia(body.vertices, body.mass));
|
|
||||||
Vertices.translate(body.vertices, { x: body.position.x, y: body.position.y });
|
|
||||||
|
|
||||||
// update bounds
|
if (!body.isStatic) {
|
||||||
Bounds.update(body.bounds, body.vertices, body.velocity);
|
part.area = Vertices.area(part.vertices);
|
||||||
|
Body.setMass(part, body.density * part.area);
|
||||||
|
|
||||||
|
// update inertia (requires vertices to be at origin)
|
||||||
|
Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
|
||||||
|
Body.setInertia(part, Vertices.inertia(part.vertices, part.mass));
|
||||||
|
Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
|
||||||
|
}
|
||||||
|
|
||||||
|
// update bounds
|
||||||
|
Bounds.update(part.bounds, part.vertices, body.velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!body.isStatic) {
|
||||||
|
var total = _totalProperties(body);
|
||||||
|
body.area = total.area;
|
||||||
|
Body.setMass(body, total.mass);
|
||||||
|
Body.setInertia(body, total.inertia);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -545,6 +555,35 @@ var Body = {};
|
||||||
body.torque += (offset.x * force.y - offset.y * force.x) * body.inverseInertia;
|
body.torque += (offset.x * force.y - offset.y * force.x) * body.inverseInertia;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sums of the properties of all compound parts of the parent body.
|
||||||
|
* @method _totalProperties
|
||||||
|
* @private
|
||||||
|
* @param {body} body
|
||||||
|
* @return {}
|
||||||
|
*/
|
||||||
|
var _totalProperties = function(body) {
|
||||||
|
var properties = {
|
||||||
|
mass: 0,
|
||||||
|
area: 0,
|
||||||
|
inertia: 0,
|
||||||
|
centre: { x: 0, y: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// sum the properties of all compound parts of the parent body
|
||||||
|
for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
|
||||||
|
var part = body.parts[i];
|
||||||
|
properties.mass += part.mass;
|
||||||
|
properties.area += part.area;
|
||||||
|
properties.inertia += part.inertia;
|
||||||
|
Vector.add(properties.centre, part.position, properties.centre);
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.centre = Vector.div(properties.centre, body.parts.length - 1);
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Properties Documentation
|
* Properties Documentation
|
||||||
|
|
|
@ -78,6 +78,12 @@ var Composite = {};
|
||||||
switch (obj.type) {
|
switch (obj.type) {
|
||||||
|
|
||||||
case 'body':
|
case 'body':
|
||||||
|
// skip adding compound parts
|
||||||
|
if (obj.parent !== obj) {
|
||||||
|
Common.log('Composite.add: skipped adding a compound body part (you must add its parent instead)', 'warn');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Composite.addBody(composite, obj);
|
Composite.addBody(composite, obj);
|
||||||
break;
|
break;
|
||||||
case 'constraint':
|
case 'constraint':
|
||||||
|
|
|
@ -67,8 +67,8 @@ var Sleeping = {};
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var collision = pair.collision,
|
var collision = pair.collision,
|
||||||
bodyA = collision.bodyA,
|
bodyA = collision.bodyA.parent,
|
||||||
bodyB = collision.bodyB;
|
bodyB = collision.bodyB.parent;
|
||||||
|
|
||||||
// don't wake if at least one body is static
|
// don't wake if at least one body is static
|
||||||
if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic)
|
if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic)
|
||||||
|
|
|
@ -399,7 +399,7 @@ var Render = {};
|
||||||
var sprite = part.render.sprite,
|
var sprite = part.render.sprite,
|
||||||
texture = _getTexture(render, sprite.texture);
|
texture = _getTexture(render, sprite.texture);
|
||||||
|
|
||||||
if (options.showSleeping && part.isSleeping)
|
if (options.showSleeping && body.isSleeping)
|
||||||
c.globalAlpha = 0.5;
|
c.globalAlpha = 0.5;
|
||||||
|
|
||||||
c.translate(part.position.x, part.position.y);
|
c.translate(part.position.x, part.position.y);
|
||||||
|
@ -412,7 +412,7 @@ var Render = {};
|
||||||
c.rotate(-part.angle);
|
c.rotate(-part.angle);
|
||||||
c.translate(-part.position.x, -part.position.y);
|
c.translate(-part.position.x, -part.position.y);
|
||||||
|
|
||||||
if (options.showSleeping && part.isSleeping)
|
if (options.showSleeping && body.isSleeping)
|
||||||
c.globalAlpha = 1;
|
c.globalAlpha = 1;
|
||||||
} else {
|
} else {
|
||||||
// part polygon
|
// part polygon
|
||||||
|
@ -429,7 +429,7 @@ var Render = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.wireframes) {
|
if (!options.wireframes) {
|
||||||
if (options.showSleeping && part.isSleeping) {
|
if (options.showSleeping && body.isSleeping) {
|
||||||
c.fillStyle = Common.shadeColor(part.render.fillStyle, 50);
|
c.fillStyle = Common.shadeColor(part.render.fillStyle, 50);
|
||||||
} else {
|
} else {
|
||||||
c.fillStyle = part.render.fillStyle;
|
c.fillStyle = part.render.fillStyle;
|
||||||
|
@ -442,7 +442,7 @@ var Render = {};
|
||||||
} else {
|
} else {
|
||||||
c.lineWidth = 1;
|
c.lineWidth = 1;
|
||||||
c.strokeStyle = '#bbb';
|
c.strokeStyle = '#bbb';
|
||||||
if (options.showSleeping && part.isSleeping)
|
if (options.showSleeping && body.isSleeping)
|
||||||
c.strokeStyle = 'rgba(255,255,255,0.2)';
|
c.strokeStyle = 'rgba(255,255,255,0.2)';
|
||||||
c.stroke();
|
c.stroke();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue