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 :

  1. Clearing the canvas - the renderer clears the canvas to remove the previous frame’s rendering
  2. Updating physics engine - engine calculates the new position and orientation of each body in the world
  3. 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:

  1. npm create vite <project_name>
  2. replaced index.html with my html page and changed the import to main.ts
  3. installed npm i @types/matter-js
  4. 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! 😉

About Robert

My name is Robert. I am self taught programmer who loves mingling with different technologies and learning different concepts as I find this field of work highly motivating. I mainly use MERN stack but I'm also on my way to learning T3 and Arduino.You can see some of the demos of the apps I've built in my youtube channel, although I am not actively working on it at the moment.


Follow Robert @ YouTube | GitHub | LinkedIn

comments powered by Disqus

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 more

Getting 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 more

The 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