2

This is what I'm trying to work on right now, from the matter.js library. I want to use two events to trigger two HTML messages by grabbing the ball on the left side of the cradle that will say "Hey you grabbed the cradle" and then when you let go, it would say "Wow, look at that!".

// Matter.js - http://brm.io/matter-js/

// Matter module aliases
var Engine = Matter.Engine,
    World = Matter.World,
    Body = Matter.Body,
    Composites = Matter.Composites,
    MouseConstraint = Matter.MouseConstraint;

// create a Matter.js engine
var engine = Engine.create(document.body, {
  render: {
    options: {
      showAngleIndicator: true,
      showVelocity: true,
      wireframes: false
    }
  }
});

// add a mouse controlled constraint
var mouseConstraint = MouseConstraint.create(engine);
World.add(engine.world, mouseConstraint);

// add a Newton's Cradle (using the Composites factory method!)
var cradle = Composites.newtonsCradle(280, 150, 5, 30, 200);
World.add(engine.world, cradle);

// offset the first body in the cradle so it will swing
Body.translate(cradle.bodies[0], { x: 0, y: 0 });

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

Where I am currently at with trying to make it happen is at:

cradle.mouseConstraint=function(){alert("hi")};

For more information, here is the Codepen: http://codepen.io/liabru/pen/abFml

ggorlen
  • 44,755
  • 7
  • 76
  • 106
farmanp
  • 21
  • 2

1 Answers1

0

There are many ways to do this.

One approach is to test mouseConstraint.body to see if the mouse is holding the body you want to track capture and release on. If this condition is true, then use a boolean to determine if the body is already being dragged or carried by the mouse.

If the boolean is true, the body is already being dragged, otherwise it's the beginning of a new drag and you can flash a message.

When the body isn't on the mouse and the boolean is true, the body has just been released; set the boolean to false so the next interaction can be detected.

In the below minimal example, we want to track interaction with the circle but not with the square. I'm using console.log() but you can replace that with whatever HTML message you want to show/hide.

const engine = Matter.Engine.create();
const render = Matter.Render.create({
  element: document.body,
  engine: engine,
});
const bodies = [
  Matter.Bodies.rectangle(400, 100, 810, 60, {isStatic: true}),
  Matter.Bodies.rectangle(200, 0, 50, 50),
  Matter.Bodies.circle(300, 0, 25),
];
const carryableBody = bodies.at(-1); // make the circle carryable
let carrying = false;
const mouseConstraint = Matter.MouseConstraint.create(
  engine, {element: document.body}
);
const runner = Matter.Runner.create();
Matter.Events.on(runner, "tick", event => {
  if (mouseConstraint.body === carryableBody && !carrying) {
    console.log("begin carrying body");
    carrying = true;
  }
  else if (!mouseConstraint.body && carrying) {
    console.log("release carried body");
    carrying = false;
  }
});
Matter.Composite.add(engine.world, [...bodies, mouseConstraint]);
Matter.Runner.start(runner, engine);
Matter.Render.run(render);
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.js"></script>

You can use collision filters and/or arrays to generalize the above pattern to multiple bodies if you want.

ggorlen
  • 44,755
  • 7
  • 76
  • 106