An Introduction to Matter.js
Hello everyone. In this article I will write about Matter.js and what you can do with it. Please do keep in mind that I am a beginner in MatterJS. I hope you are going to have fun learning it with me. 🙂
Matter.js is a JavaScript library that provides a simple and easy-to-use physics engine for simulating 2D rigid body physics in web applications. In other words, it allows developers to create simulations of physical objects in a virtual environment, such as a game, animation, or interactive visualization.
The library provides a range of features and functionalities, such as collision detection and response, gravity and friction, and constraints like springs and hinges, which can be used to create complex and interactive simulations. Developers can also create custom shapes and apply various properties to them, such as density, friction, and restitution, to simulate different materials and objects.
Matter.js is designed to be lightweight and efficient, allowing for smooth and fast simulations even on low-end devices. It is also highly customizable, with a flexible API that allows developers to fine-tune the behavior of the physics engine to suit their specific needs.
Getting started with Matter.js
In order to install and use Matter.js we first need to import the library or install it via npm.
In this tutorial I will include it in the script of my webpage. To get the Matter.js library source code, head on over to GitHub.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="matter.js"></script>
</body>
</html>
Copy and paste the github example code in your page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="matter.js">
// module aliases
let Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Bodies = Matter.Bodies,
Composite = Matter.Composite;
// create an engine
let engine = Engine.create();
// create a renderer
let render = Render.create({
element: document.body,
engine: engine
});
// create two boxes and a ground
let boxA = Bodies.rectangle(400, 200, 80, 80);
let boxB = Bodies.rectangle(450, 50, 80, 80);
let ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });
// add all of the bodies to the world
Composite.add(engine.world, [boxA, boxB, ground]);
// run the renderer
Render.run(render);
// create runner
let runner = Runner.create();
// run the engine
Runner.run(runner, engine);
</script>
</body>
</html>
Let’s go step by step through each line of the code above.
Matter.Engine
creates and manages the objects and systems required
for a physics simulation to run.
The Engine is created using Matter.Engine.create()
method and contains methods
and properties, which are needed in order to control the behavior of the physics
simulation.
let engine = Engine.create();
Think of the Engine like a toolbox which has all required tools you need in order to create a simulation.
The Engine has the following properties :
- world: The world object that contains all the bodies and constraints in the simulation.
- run: A method that starts the physics simulation and updates it on each frame of the animation.
- render: A method that creates a renderer to display the simulation on a canvas or other HTML element.
- update: A method that updates the physics simulation and applies all the changes to the bodies and constraints in the world.
- delta: The time elapsed since the last frame, which is used to calculate the position and velocity of objects in the simulation.
So what is a Body in Matter.js?
Let’s see first what a rigid body means in Physics.
A rigid body is a body that doesn’t deform or change shape.
In Matter.js, a Body is a physics object that represents a rigid body in a 2D physics simulation. It can be a simple or complex shape, such as a rectangle, circle, polygon, or even a composite object made up of multiple shapes.
A Body in Matter.js has various properties that define its physical characteristics, such as:
- position: The position of the body in the simulation.
- velocity: The velocity of the body in the simulation.
- angle: The angle of the body in radians.
- angularVelocity: The angular velocity of the body in radians per second.
- mass: The mass of the body in kilograms.
- density: The density of the body in kilograms per square meter.
- friction: The friction coefficient of the body.
A Body can also have various methods attached to it, such as:
- applyForce: Applies a force to the body at a given position.
- applyTorque: Applies a torque (a rotational force) to the body.
- applyImpulse: Applies an impulse (a sudden change in velocity) to the body at a given position.
Runner is a module that provides a simple and efficient way to run a physics simulation in a loop.
Renderer is used to display 2D physics simulations.
Matter.Render.create()
- creates a new render instance and takes in
the engine and an options object as argument (canvas element we want to use
to render objects on the screen).
In the example below document.body
is the element we want to render
our objects in and the second argument is our engine instance.
let render = Render.create({
element: document.body,
engine: engine,
});
Bodies
is a module that provides a set of factory methods for creating common physics bodies with predefined shapes and properties.
// create two boxes and a ground
let boxA = Bodies.rectangle(400, 200, 80, 80);
let boxB = Bodies.rectangle(450, 50, 80, 80);
let ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });
Composite is a collection of bodies, constraints, and composites that are grouped together and treated as a single entity. For me it helps to Think about it as many little things acting as a single unit.
Remember the world contains all the bodies and constraints in our simulation:
Composite.add(engine.world, [boxA, boxB, ground]);
In the above line we’ve added our boxA,boxB
and ground
to the world and created a single composite.
Render.run()
- runs the renderer’s animation loop.
A renderer animation loop is a continuous process of updating and rendering the state of a Matter.js world in the browser canvas.
The following steps are performed by the animation loop :
- Clearing the canvas - the renderer clears the canvas to remove the previous frame’s rendering
- Updating physics engine - engine calculates the new position and orientation of each body in the world
- Rendering the updated state
Render.run(render);
Runner.run()
- runs the physics engine’s update loop, which calculates the new position and orientation of each body
Runner.run(runner, engine);
Let’s add a new body to our world:
let circle = Bodies.circle(300, 40, 25);
Then add this new body in the composite:
Composite.add(engine.world, [circle, boxA, boxB, ground]);
Let’s try to move a rectangle. Copy and paste the following code.
document.addEventListener("keydown", function (event) {
let keyCode = event.keyCode;
let position = boxA.position;
let speed = 5; // set the speed of movement
// move the body based on the key pressed
if (keyCode === 37) {
// move left
Matter.Body.translate(boxA, { x: -speed, y: 0 });
} else if (keyCode === 38) {
// move up
Matter.Body.translate(boxA, { x: 0, y: -speed });
} else if (keyCode === 39) {
// move right
Matter.Body.translate(boxA, { x: speed, y: 0 });
} else if (keyCode === 40) {
// move down
Matter.Body.translate(boxA, { x: 0, y: speed });
}
});
Spawning objects using mouse:
document.body.addEventListener("mousedown", (event) => {
const { x, y } = event;
const newBody = Bodies.rectangle(x, y, 50, 50);
World.add(engine.world, newBody);
});
In the example above we create a newBody
at mouse coordinates and
add it to the world each time on click.
Adding collisions to the game
In the example below the code checks if there is a pair of two
objects where first body is boxA
and secondBody
is the circle
Events.on(engine, "collisionStart", (event) => {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i];
if (pair.bodyA === boxA && pair.bodyB === circle) {
// Game over
alert("Game over!");
window.location.reload(true);
}
}
});
In order to convert JavaScript to typescript I did the following steps:
npm create vite <project_name>
- replaced
index.html
with my html page and changed the import tomain.ts
- installed
npm i @types/matter-js
- added type safety. (Check the typescript branch for more info.)
Overall, Matter.js is a powerful tool for creating interactive and engaging web applications that simulate real-world physics, and is widely used in game development, education, and scientific simulations.
That’s all, for now! Hope you enjoyed this tutorial and see you next time! 😉
Links
Related Posts
Finding Free and Discounted Programming Books
As an avid reader, I’m always looking for places to find my next book. If they’re free, even better. Although it’s not always so easy finding them, there are plenty available online.
Read moreGetting Started with Google Cloud
In this article, we’re going to be taking a first look at Google Cloud, a leading player in the world of cloud computing, offers services and tools designed to drive innovation and ease operations.
Read moreThe Great JavaScript Debate: To Semicolon or Not?
Since I’ve started learning this language, JavaScript has undergone some heavy changes. Most notably, it seems to be the norm to not use semicolons anymore.
Read more