Search code examples
javascriptmatter.js

How to have circle roll when pushed using MatterJS?


I have a simple animation where I have a static rectangle slowly moving horizontally so that it pushes a circle across the 'floor'.

How can I make the circle roll instead of slide?

I tried adding friction to the circle and the floor, and removing friction from the pushing rectangle, but it makes no difference.

var container = document.getElementById('container');
var w = 1000;
var h = 500;

const Engine = Matter.Engine;
const Render = Matter.Render;
const World = Matter.World;
const Bodies = Matter.Bodies;
const MouseConstraint = Matter.MouseConstraint;
const Bounds = Matter.Bounds;
const Events = Matter.Events;
const Body = Matter.Body;

const engine = Engine.create();

const render = Render.create({
  element: container,
  engine: engine,
  options: {
    width: w,
    height: h,
    wireframes: true,
    showAngleIndicator: true,
    background: 'transparent',
  }
});

var boxX = 10;
var boxY = 390;
const ball = Bodies.circle(100, 400, 80, {
  friction: 100
});
const box = Bodies.rectangle(boxX, boxY, 20, 20, {
  friction: 0,
  isStatic: true
});
const floor = Bodies.rectangle(500, 480, 1000, 20, {
  isStatic: true
});

World.add(engine.world, [
  ball,
  box,
  floor
]);

engine.gravity.y = 3;

Matter.Runner.run(engine);
Render.run(render);

move();

function move() {
  boxX += 1;
  Matter.Body.setPosition(box, {
    x: boxX,
    y: boxY
  }, [updateVelocity = true]);
  window.requestAnimationFrame(move);
};
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js" integrity="sha512-0z8URjGET6GWnS1xcgiLBZBzoaS8BNlKayfZyQNKz4IRp+s7CKXx0yz7Eco2+TcwoeMBa5KMwmTX7Kus7Fa5Uw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>


Solution

  • After some experimentation I found that you need to add slop to the floor body to allow the circle to have enough grip to roll.

    const floor = Bodies.rectangle( 500 , 480, 1000, 20, { friction: 1, slop: 1, isStatic: true } );