In the previous tutorial of the series, you learned about the World and Engine modules in Matter.js. The methods available in these two modules are meant to control the behavior of multiple bodies or the whole world at once. However, at some point it will become necessary to have control over the properties of individual bodies in your world.
For example, you may want to apply some force on a particular object or change its friction coefficient. In such cases, the Body module in Matter.js can be of great help. This module contains a lot of methods and properties to let you specify values for all kinds of physical attributes, from mass to coefficient of restitution. In this tutorial, you will learn about all these methods and properties and how to use them properly.
Scaling, Rotating and Translating a Body
You can rotate any rigid body in the Matter.js world by using the rotate(body, rotation)
method. The rotation is relative to the current angle of the body, and it will not impart any angular velocity to it. The rotation angle is specified in radians.
You can also scale a body by using the scale(body, scaleX, scaleY, [point])
method. The parameters scaleX
and scaleY
specify the amount of scaling in the horizontal and vertical directions respectively. Keep in mind that any such scaling will also update the physical properties of the body like its mass, area, and inertia. The fourth parameter specifies the point around which the scaling occurs. When not specified, the default value of the scaling point is assumed to be the center of the body.
It is possible to move a body by a given vector relative to its current position using the translate(body, translation)
method. The translation parameter specifies the new position of the object relative to its current position. Here is the portion of code from the demo that scales, rotates and moves the box around.
var Body = Matter.Body; var box = Bodies.rectangle(460, 120, 40, 40); $('.scale').on('click', function () { Body.scale( box, 1.5, 1.2); }); $('.rotate').on('click', function () { Body.rotate( box, Math.PI/6); }); $('.translate').on('click', function () { Body.translate( box, {x: -10, y: 20}); });
Setting Velocities and Applying Forces
You can also impart linear velocity to an object using the setVelocity(body, velocity)
method. Applying a velocity in this manner does not change the angle, applied force or position of the concerned object. The position of the object or its angle will probably change, but the library does not specifically set them to any value. Their values are determined by other forces that are acting on the object, like friction.
Just like the linear velocity, you can also change the angular velocity of an object using the setAngularVelocity(body, velocity)
method. In this case, too, the position, angle and force applied on the object remain unchanged.
One thing that you should keep in mind is that the velocity is a vector in setVelocity()
and a number in setAngularVelocity()
.
$('.linear').on('click', function () { Body.setVelocity( box, {x: 10, y: -10}); }); $('.angular').on('click', function () { Body.setAngularVelocity( box, Math.PI/6); });
In addition to imparting velocities to objects, you can also apply a force vector on them. The applyForce(body, position, force)
method can be used to apply a force
vector on a body from a given position
. This force may or may not result in the application of torque on a given body.
The following code applies a force right at the center of the body. The force vector is {x: 0, y: -0.05}
. This means that the applied force will be purely vertical and in an upward direction. You should keep in mind that vertical forces in an upward direction have a negative sign in Matter.js. Another thing worth noticing is how small the number that specifies the vertical force is. The gravitation force itself has a value of just 1 in Matter.js.
The motion of the ball after applying the forces seems natural as long as that ball does not collide with any of the walls or the floor. Normally, when things collide with something, we expect them to bounce back. The energy with which an object bounces back is determined by the coefficient of restitution.
In Matter.js, its value is set to zero by default. This means that any object which has restitution set to zero and collides with something else will not bounce back at all. A value of 1 will mean that the object will bounce back with kinetic energy equal to what it had before collision. A value like 0.5 means that the object will bounce back only with 50% of its previous kinetic energy. The value of restitution for an object can be controlled using the restitution
key.
In certain simulations, it might become necessary for you to change the friction between different bodies. This can be achieved using the friction
, frictionAir
and frictionStatic
keys.
- The
friction
key specifies the value of kinetic friction for a body. It can have a value between 0 and 1. A value of 0 implies that a body may keep moving indefinitely once it has been set in motion. The only way to stop it will be to apply some other external force. The final value of friction between two objects is determined using the formulaMath.min(bodyA.friction, bodyB.friction)
. - The
frictionStatic
key specifies the value of friction when a body is at rest. The default value for static friction is 0.5. A higher value means that a larger amount of force will be required to get the body moving. - The
frictionAir
key is used to specify the value of friction between a body and the surrounding air. A higher value means that the body will slow down very quickly when moving through the air. The effect of air friction is non-linear.
$('.red-friction').on('click', function () { circleA.friction = 0.05; circleA.frictionAir = 0.0005; circleA.restitution = 0.9; }); $('.res-friction').on('click', function () { circleA.friction = 0.1; circleA.frictionAir = 0.001; circleA.restitution = 0; });
Control the Rendering of Bodies
Up to this point, we have not specified the color, outline width or stroke style to use when rendering a body. All these properties are nested inside the render
key. The fillStyle
property accepts a string to specify the fill style rendering the body. The lineWidth
property accepts a number that defines the line width to use when creating the outline of a body.
A value of zero means that no line will be rendered at all. The strokeStyle
property can be used to specify the stroke style to use when rendering the body outline. You can prevent a body from rendering at all by setting the visible
key to false
. The opacity of the body that you want to render can be controlled using the opacity
key.
You can also use an image instead of simple colors and outlines to render a body. The parameters for rendering a body using sprites are specified using a different set of properties. The texture
property defines the path of the image that should be used as a sprite texture.
The xOffset
and yOffset
properties can be used to define the offset in the respective axes for the sprite. Similarly, you can use the xScale
and yScale
properties to define the scaling in the x-axis and y-axis for the sprite. Here is some code that replaces the light blue background of our ball with a soccer sprite from the Open Game Art website.
var ball = Bodies.circle(90, 280, 20, { render: { sprite: { texture: "path/to/soccer_ball.png", xScale: 0.4, yScale: 0.4 } } });
Changing Physical Properties
You have already seen how to specify the friction or coefficient of restitution for an object in Matter.js. There are a lot of other properties whose values can be specified in the same manner. On the other hand, there are properties which are read-only and cannot be changed by you.
You can set the position of a body in the world by using the position
key, which accepts a vector as its value. You can also specify the mass of a body using the mass
property, but then you will also have to set a value for the inverseMass
property, which is calculated using 1/mass
. A better way of controlling the mass of a body is with the help of the density
property.
Once you change the density of a body, its mass will be calculated automatically based on its area. This way you can also differentiate between different objects based on their density. For example, a body that uses a rock as its sprite should have higher density than a body of the same size that uses a soccer ball as its sprite.
Some properties like speed
, velocity
and angularVelocity
are read-only, but their values can be set using appropriate methods like setAngularVelocity()
and setVelocity()
. You can read more about different properties of the Body module in the documentation.
Conclusion
In this tutorial, you have learned about all the important methods and properties in the Body module of the Matter.js library. Knowing about these different properties and what they do can help you create more realistic simulations of real-life physics. In the next and final tutorial of the series, you will learn about the Composite module in Matter.js.
If you have any questions related to this tutorial or some tips for using the library, please share them with us.