The article is based on MatterJs ^0.17.1
In the previous chapter, we introduced the physical environment of matterJs. With the environment, we need to place objects in the environment to enrich the world. Today, we’re going to look at how objects exist and move in the physical environment.
1. Introduction to objects in matterJs
Objects in matterJs fall into two categories:
- Body – rigid Body
- Composite — Composite
Only these two forms of objects are supported in the physical environment of matterJs. A rigid body is a single object body, and a composite is a combination of a rigid body, constraint, or composite. Rigid bodies provide the most basic physical objects with a fixed shape. Complex makes it possible for us to compose the irregular objects we need at will, and provides the possibility of realizing the diversity of the physical world.
In matterJs, the World is also a complex, with all the methods of the complex.
World.create = Composite.create;
World.add = Composite.add;
World.remove = Composite.remove;
World.clear = Composite.clear;
World.addComposite = Composite.addComposite;
World.addBody = Composite.addBody;
World.addConstraint = Composite.addConstraint;
Copy the code
Rigid body factories provide several basic shapes:
- A rectangle rectangle
- Trapezoid trapezoidal
- Circle the round
- Polygon polygon
- FromVertices Extensible graphics
The composite factory Composites provides several kinds of complexes:
- Stack stack
- Chain chain
- Mesh grid
- Pyramid cone
- NewtonsCradle Newton swing ball
- The car the car
- The softBody software
Two, the independent Body of rigid Body -Body
In Chapter 1, we wrote about a ball in free fall, and the ball in it is a circular physical rigid body. First, let’s look at what properties the next rigid body has:
The property name | The default value | introduce |
---|---|---|
id | 0 | Each rigid body has a unique ID that increments during creation |
type | ‘body’ | type |
label | ‘Body’ | Logo, you can name it yourself |
parts | [] | Components of the rigidbody, usually array elements are the rigidbody itself |
plugin | {} | The plug-in |
angle | 0 | The Angle, this is in radians |
vertices | Vertices.fromPath(‘L 0 0 L 40 0 L 40 40 L 0 40’) | Compute vertices and specify a rigid body shape |
position | { x: 0, y: 0 } | Position, with the center of gravity as the calculation point |
force | { x: 0, y: 0 } | The force component on the x, y vector |
torque | 0 | Torque, M = F times L |
speed | 0 | speed |
angularSpeed | 0 | The angular velocity |
velocity | { x: 0, y: 0 } | Physical velocity, displacement in the x and y components |
angularVelocity | 0 | Physical angular velocity |
isStatic | false | Whether static rigid body |
isSleeping | false | Whether the rigid body sleeps |
density | 0.001 | The density of rigid body |
restitution | 0 | Attenuation coefficient of force (elasticity) |
friction | 0.1 | The frictional force |
frictionStatic | 0.5 | Static sliding friction |
frictionAir | 0.01 | Air resistance |
collisionFilter | { category: 0x0001, mask: 0xFFFFFFFF, group: 0 } | Collision filter |
bounds | null | Rigid body boundary, with maximum and minimum values |
circleRadius | 0 | The circular radius |
timeScale | 1 | Time scaling coefficient, 0 frozen, greater than 1 accelerated less than 1 slow |
positionPrev | null | The last rigid body position |
anglePrev | null | The rigid body Angle from last time |
axes | null | shaft |
area | 0 | The area of a 2D plane shape |
mass | 0 | The quality of rigid body |
inertia | 0 | inertia |
events | null | The event |
Density = body. Mass/body. Area. Angle = radian * Math.pi / 180. Restitution can specify the height of elastic rigid body. The larger the value of the rigid body, the greater the force required to move. CollisionFilter The vertices filter rule, which is covered in a separate section. This provides an idea for us to customize the rigid body. The force size controls the movement direction of the rigid body.
Next, let’s look at what we can do with the methods provided by the rigid body:
1, Body. NextGroup
NextGroup = (isNonColliding) => {}
- IsNonColliding Whether the colliding identifier is allowed
Returns a decrement or increment index. If isNonColliding is true, a decrement index is generated and the rigidbodies cannot collide. If isNonColliding is false, an increment index is generated and the rigidbodies can collide. Take 🌰 for example: when we set group = body.nextgroup (true), the circle will not collide with our ground, as it does when set to false.
var group = Body.nextGroup(true);
/** Create a circular rigid body */
var _circle = Bodies.circle(200.10.20, {
isStatic: false.collisionFilter: {
group: group
}
});
Composite.add(world, [
Bodies.rectangle(400.400.800.10, {
isStatic: true.collisionFilter: {
group: group
}
}),
_circle
]);
Copy the code
So how does matterJs determine collisions?
if(filterA.group === filterB.group && filterA.group ! = =0)
return filterA.group > 0;
Copy the code
So it’s a collision.
2, Body. NextCategory
NextCategory = ()=>{} Parameter: none Category value range is [1, 2^31]. Collisions between specified rigid bodies can be realized by specifying collision groups. This method is simply used to generate the category specified by the collisionFilter attribute. Use category and mask together to determine grouping collisions.
For example, 🌰: When the _circle category is the same as the Rectangle mask, the two can collide. In the following example, categoryA and categoryB have different values.
var categoryA = Body.nextCategory(),
categoryB = Body.nextCategory();
/** Create a circular rigid body */
var _circle = Bodies.circle(200.10.20, {
isStatic: false.collisionFilter: {
category: categoryA
}
});
Composite.add(world, [
Bodies.rectangle(400.400.800.10, {
isStatic: true.collisionFilter: {
category: categoryB,
mask: categoryB //categoryB
}
}),
_circle
]);
Copy the code
How does matterJs determine grouping collisions?
return(filterA.mask & filterB.category) ! = =0&& (filterB.mask & filterA.category) ! = =0;
Copy the code
3, the Body. The set
Function: Body. Set = (Body, Settings, value) => {} parameter:
- Body set to the rigidbody
- Settings Specifies the value of the property or key-value pair to be set
- The value in
settings
Is a string value
When matterJs sets a property, it calls a series of methods to set the corresponding value. So what are the properties that can be set? Here are some values that can be set:
switch (property) {
case 'isStatic':
Body.setStatic(body, value);
break;
case 'isSleeping':
Sleeping.set(body, value);
break;
case 'mass':
Body.setMass(body, value);
break;
case 'density':
Body.setDensity(body, value);
break;
case 'inertia':
Body.setInertia(body, value);
break;
case 'vertices':
Body.setVertices(body, value);
break;
case 'position':
Body.setPosition(body, value);
break;
case 'angle':
Body.setAngle(body, value);
break;
case 'velocity':
Body.setVelocity(body, value);
break;
case 'angularVelocity':
Body.setAngularVelocity(body, value);
break;
case 'parts':
Body.setParts(body, value);
break;
case 'centre':
Body.setCentre(body, value);
break;
default:
body[property] = value;
}
Copy the code
As you can see, the default properties that are not rigid bodies can also be set.
4, the Body. The rotate
Rotate = (Body, rotation, point) => {}
- Body Rotating rigid body
- Rotation The Angle of rotation
- Which point is rotated relative to
To rotate by a certain Angle relative to a given position, and to rotate by a given Angle. If no point is passed, only the rigid body rotates. If a point is passed, the rigid body rotates by the rotation relative to the point, and the rigid body also rotates by the rotation.
For example 🌰: The rectangle is rotated 30 * math. PI / 180 radians relative to {x: 200,y: 100}.
/** Create a rigid body */
var _rect = Bodies.rectangle(100.100.50.50, {
isStatic: true}); Composite.add(world, _rect); Body.rotate(_rect,30 * Math.PI / 180, {
x: 200.y: 100
});
Copy the code
If the rotation is 0, the object does not move or rotate even if the point is passed in.
Let’s see how matterJs handles this.
if(! point) { Body.setAngle(body, body.angle + rotation); }else {
var cos = Math.cos(rotation),
sin = Math.sin(rotation),
dx = body.position.x - point.x,
dy = body.position.y - point.y;
Body.setPosition(body, {
x: point.x + (dx * cos - dy * sin),
y: point.y + (dx * sin + dy * cos)
});
Body.setAngle(body, body.angle + rotation);
}
Copy the code
As you can see, we set position first and then Angle.
5, the Body scale
Function: Body. Scale = (Body, scaleX, scaleY, point) => {}
- The body of rigid body
- ScaleX Scale factor in the X direction
- ScaleY Scale factor in the Y direction
- Point Scaling center, anchor point
If no scaling center is given, the default is the center of the rigid body (center of gravity). For example 🌰: the following rectangle is scaled by 50% with respect to {x: 200,y: 100} point x.
var _rect = Bodies.rectangle(100.100.50.50, {
isStatic: true}); Composite.add(world, _rect); Body.scale(_rect,0.5.0.5, {x: 200.y: 100});
Copy the code
As you can see, scaling redefines the vertex rules of the rigid body and changes its mass, inertia and other properties.
// scale vertices
Vertices.scale(part.vertices, scaleX, scaleY, point);
// update properties
part.axes = Axes.fromVertices(part.vertices);
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, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));
Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
Copy the code
6, the Body. The update
Update = (Body, deltaTime, timeScale, correction) => correction
- The body of rigid body
- DeltaTime Time interval frame interval of each update, 16.67ms
- TimeScale timeScale coefficient 0 frozen, greater than 1 accelerated less than 1 slow
- Correction The correction factor. Default is 1
We don’t call this method actively. It will be called in Engine. Update. Mainly used to update the rigid body position, Angle, velocity and other physical information and geometric transformation.
7, Body. ApplyForce
Function: Body. ApplyForce = (Body, position, force) => {}
- The body of rigid body
- Position Vector at which force is applied
- Force Vector of applied force
Force is divided into components in the x and y directions.
For example 🌰: if we apply a force {x: 0.1, y: 0.1} to the rigid body _rect, the body will move along an oblique line at an Angle of 45 degrees.
var _rect = Bodies.rectangle(100.100.50.50, {
isStatic: false.mass: 1
});
Composite.add(world, _rect);
Body.applyForce(_rect,{x: 0.y: 0}, {x: 0.1.y: 0.1});
Copy the code
Notice that the rigid body or the complex on which we apply force, its isStatic cannot be true, cannot be a static rigid body. Static rigid bodies are not subjected to force. When a rigid body is subjected to a force, a moment is created.
How does the applyForce method work?
body.force.x += force.x;
body.force.y += force.y;
var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
body.torque += offset.x * force.y - offset.y * force.x;
Copy the code
At this point, we have covered the main properties and methods of the rigid body. Single rigidbodies in matterJs have a set of properties and methods that we can manipulate to create interesting scenarios. So how do we get some special shapes? Matterjs gives us a factory method for Bodies to generate various shapes.
Three, rigid body production workshop -Bodies
We have described the properties and methods that a single rigid body needs. With the core technology, we are about to start the production of formal products. Bodies provide us with several common moulds (shapes). All shapes are generated using body.create ().
1, the rectangle
Rectangle = (x, y, width, height, options) => {}
- X — x position
- Y — y position
- Width the width of the
- Height height
- The options to configure
Shape method of rectangle:
Vertices.fromPath('L 0 0 L ' + width + ' 0 L ' + width + ' ' + height + ' L 0 ' + height)
Copy the code
Here’s an example 🌰:
/** Create rectangle **/
var _rect = Bodies.rectangle(100.100.50.50, {
isStatic: false}); Composite.add(world, _rect);Copy the code
2, trapezoidal
Trapezoid = (x, y, width, height, slope, options) => {} parameter:
- .
- Slope slope
The form method of trapezoid:
if (slope < 0.5) {
verticesPath = 'L 0 0 L ' + x1 + ' ' + (-height) + ' L ' + x2 + ' ' + (-height) + ' L ' + x3 + '0';
} else {
verticesPath = 'L 0 0 L ' + x2 + ' ' + (-height) + ' L ' + x3 + '0';
}
var trapezoid = {
label: 'Trapezoid Body'.position: { x: x, y: y },
vertices: Vertices.fromPath(verticesPath)
};
Copy the code
Here’s an example 🌰:
/** Create a trapezoid
var _trapezoid = Bodies.trapezoid(100.100.50.50.0.2, {
isStatic: true}); Composite.add(world, _trapezoid);Copy the code
3, round
Function: Bodies. Circle = (x, y, radius, options, maxSides) => {} parameters:
- .
- The radius radius
- MaxSides maximum edge
How does a circle have shape? It’s actually a formalized method of using polygons.
Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options))
Copy the code
A circle in matterJs is actually a polygon with a minimum of 10 sides and a default of 25.
Here’s an example 🌰:
/** Create a circle **/
var _cricle = Bodies.circle(50.50.50, {
isStatic: true,},80);
Composite.add(world, _cricle);
Copy the code
Here’s the interesting part: matterJs intends to make a real circle.
// TODO: true circle bodies
Copy the code
4. Polygons
Function: Bodies. Polygon = (x, y, sides, radius, options) => {} parameters:
- .
- Sides number of edges
- The radius radius
How are polygons present?
for (var i = 0; i < sides; i += 1) {
var angle = offset + (i * theta),
xx = Math.cos(angle) * radius,
yy = Math.sin(angle) * radius;
path += 'L ' + xx.toFixed(3) + ' ' + yy.toFixed(3) + ' ';
}
var polygon = {
label: 'Polygon Body'.position: { x: x, y: y },
vertices: Vertices.fromPath(path)
};
Copy the code
If the number of sides is less than 3, the circle is drawn. For example 🌰: draws a triangle.
/** Create a polygon **/
var _polygon = Bodies.polygon(50.50.3.20, {
isStatic: true}); Composite.add(world, _polygon);Copy the code
Custom shapes
Function: Bodies.fromVertices = (x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea, RemoveDuplicatePoints) => {} parameter:
- .
- VertexSets One or more arrays of vertices
- FlagInternal Specifies whether an internal flag is displayed
- RemoveCollinear 0.01 simplifies the threshold of the same side
- MinimumArea 10 Threshold at which small portions are removed
- RemoveDuplicatePoints 0.01 Threshold when simplifying nearby points
FlagInternal = true; no internal flag
Formal method interested can read the source code.
For example 🌰: Let’s draw a five-pointed star.
/** Custom shape **/
Common.setDecomp(decomp);
var star = Vertices.fromPath('50 0 63 38 100 38 69 59 82 100 50 75 18 100 31 59 0 38 37 38');
var _custom = Bodies.fromVertices(200.200, star,{
isStatic: true
},true.0.1.10);
Composite.add(world, _custom);
Copy the code
Decomp is a plugin for drawing custom shapes. I’m just using script reference here. Use a series of points to form a closed shape.
Four,
This section describes the rigid body in matterJs, including its properties and methods. Note that each rigid body has its own unique ID. It has both similar and dissimilar properties. We can draw some rigid Bodies with shapes using the Bodies factory method:
- rectangular
- trapezoidal
- polygon
- circular
- Some custom shapes
We can also do a few things to the rigidbody:
- Setting the base properties
- Setting collision rules
- Apply force to move the rigid body
Meanwhile, we need to pay attention to:
- A static rigid body is free from any physical action
- You can set rigid body updates to achieve certain effects, such as freezing, constant speed, and to prevent stalling.
We will continue this in the next chaptermatterJs
How to create a complex complex. And how to use complexes to build complex physical worlds.
This article is shallow, please don’t hesitate your comments and likes ~ note: this article is the author’s painstaking work, reprint must declare