updated February 26, 2020

Create real world in browser with JavaScript physics engine Matter.js

MatterJS JavaScript library makes adding real world simulation on a web page quite simple: you just create rigid objects with the properties like position, size, friction value and start the MatterJS engine and see how the objects behave like in real world: move, slide, collide, jump.

Simple example: ball rolls from the slope

HTML

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.14.2/matter.js"></script>
  </head>
  <body onload="init()"></body>
</html>

JavaScript

function init() {
  // create engine
  const engine = Matter.Engine.create();
  
  // create render
  const render = Matter.Render.create({
    element: document.body,
    engine: engine
  });

  // create bodies
  const circle = Matter.Bodies.circle(150, 100, 20);
  const ground = Matter.Bodies.rectangle(400, 500, 780, 20, {isStatic: true});
  const slope = Matter.Bodies.trapezoid(100, 470, 200, 55, 0.8, {isStatic: true});

  // add the bodies to the world
  Matter.World.add(engine.world, [circle, ground, slope]);

  // run the engine
  Matter.Engine.run(engine);

  // run the renderer
  Matter.Render.run(render);
}

What's done in the code

  1. Create engine, render. The world is rendered in rectange of 800 * 600 pixels size by default, or its size is set in the render options.
  2. Create circle: 1st, 2nd arguments are the center position, third is radius. It is movable object by default that falls under the gravity force, rolls, could be pushed by other objects.
  3. Create rectangle and trapezoid static objects that don't change their position under gravity or if interact with other objects.
    The rectangle, trapezoid function 1st, 2ns arguments are the center position, as for circle. Other arguments are size-related arguments, except the last properties argument that specifies that the objects are static.
  4. Add all the created objects, or bodies, to the world.
  5. Run engine and render.

Some enhancements

  1. Change body friction: the default value is 0.1 so we can reduce it to increase the roll distance: let's set it to 0.01 after the circle is created:
    circle.friction = 0.01;
  2. Reduce air friction: let's divide it by 2:
    circle.frictionAir /= 2;
  3. Change ground color to green:
    const ground = Matter.Bodies.rectangle(400, 500, 780, 20, 
            {isStatic: true, render: {fillStyle: 'green'}});
    It requires render option to enable colors:
      // create render
      const render = Matter.Render.create({
        element: document.body,
        engine: engine,
        options: {wireframes: false}
      });
            

More complex and fun: Crazy roller game

You could create even games with Matter.js with user input and graphics. Me and my colleague Mirsabayu Prasetyo, who provided the graphics and helped with the level design, created Dr. One Adventure.

You spin the ball with arrow keys and move it to the finish flag through different obstacles.

The source on GitHub