Matter.js How can I make a box that is correctly landing?

Viewed 309

I created two rectangle as follows through Matter.js

enter image description here

I am trying to move the "a" box over the "b" box.

I think I should write applyForce at this time, how can I calculate the appropriate X, Y Force values to put in the factor?

The code below is a code that is made up of the rough approximation value. How can I calculate it with being adaptable?

var Engine = Matter.Engine,
  Render = Matter.Render,
  Bodies = Matter.Bodies,
  Body = Matter.Body,
  Composite = Matter.Composite,
  Runner = Matter.Runner;

var canvas = document.createElement('canvas'),
  context = canvas.getContext('2d');
var bodies = [];
canvas.width = 500;
canvas.height = 200;
var count = 0;
document.body.appendChild(canvas);
var engine = Engine.create();
var render = Render.create({
    canvas: canvas,
  engine: engine,
  options: {
    width: canvas.width,
    height: canvas.height,
    showAngleIndicator: true,
    showCollisions: true,
    showVelocity: true
  }
})
var world = engine.world

Render.run(render)
var runner = Runner.create();
Runner.run(runner, engine)

Composite.add(world, Bodies.rectangle(250, 180, 500, 20, { isStatic: true }));
// random position
var b = Bodies.rectangle(200, 80, 50, 25, { isStatic: true });
Composite.add(world, b);

var a = Bodies.rectangle(50, 50, 30, 30);
Composite.add(world, a);

setTimeout(function() {
    // how to calculate it???
    Body.applyForce(a, a.position, {x: 0.012, y: -0.032});
}, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>

1 Answers

I don't think there are many matter.js experts here:
https://stackoverflow.com/questions/tagged/matter.js?tab=Newest
looking at questions tagged with that, there are just a few and a lot of them have no answers...

And the owner of the project: https://github.com/liabru has not been very active lately, so your only option is to reverse engineer what is going on there, good thing the code is open source.

Now to your question

If I understood correctly, you hardcoded the force:
Body.applyForce(a, a.position, {x: 0.012, y: -0.032})
and you are looking for a way to calculate those values instead of just hardcodeing it.

I was playing with that code to see how it behaves, after increasing the size of box "A" and applying the same force, it does not make it over to box "B", so there is a hidden weight/mass component that is not clearly defined here, and evidently that is associated with the size of those boxes.

var Bodies = Matter.Bodies
var Body = Matter.Body
var Composite = Matter.Composite

var canvas = document.createElement('canvas')
canvas.width = canvas.height = 200;
var context = canvas.getContext('2d')
document.body.appendChild(canvas)

var engine = Matter.Engine.create()
var runner = Matter.Runner.create()
Matter.Render.run(Matter.Render.create({
  canvas: canvas,
  engine: engine,
  options: {
    width: canvas.width,
    height: canvas.height,
    showAngleIndicator: true,
    showVelocity: true
  }
}))
Matter.Runner.run(runner, engine)

Composite.add(engine.world, Bodies.rectangle(250, 180, 500, 20, { isStatic: true }))
Composite.add(engine.world, Bodies.rectangle(200, 80, 50, 25, { isStatic: true }))
var a = Bodies.rectangle(50, 130, 40, 40)
Composite.add(engine.world, a)

setTimeout(function() {
  Body.applyForce(a, a.position, { x: 0.012, y: -0.032 })
}, 2000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>

Newton's Second Law:

The net force equals mass times acceleration
F = M * A

Acceleration and Velocity

Final velocity equals initial velocity plus acceleration times elapsed time
Vf = Vi + A * T


Matter.js is a 2D physics engine, to create a realistic experience it must have those in the code, you need to determine how/where they are setting those (mass, acceleration & velocity) and start breaking down this problem.

Expect a lot of reading, and if you don't remember your physics projectile motion class, you are up for a good refreshing.

Start answering simple questions, just try to calculate something like:

  • How is the mass calculated for the box ?
  • How much force on the x to move 100px ?
  • How much force on the y to jump 100px ?

Once you have those correctly, you can start combining jumps and moves


There is a bit of documentation on the techniques used by the engine here: https://github.com/liabru/matter-js/wiki/References

Looking in the code looks like this is where the magic happens:
https://github.com/liabru/matter-js/blob/master/src/body/Body.js#L642-L644

// update velocity with Verlet integration
body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;

I was doing a bit of digging on the code here is what I got:
https://heldersepu.github.io/hs-scripts/HTML/matter-js.html

Here I'm calculating the height of the jump given the force,
the calculation goes like this:

var force = 1 // change this to the value you need
var frictionAir = 0.99
var gravityScale = 0.001
var deltaTimeSquared = Math.pow((1000 / 60), 2)
var gravity = a.mass * gravityScale
var netForce = force + gravity

var velocity = (netForce / a.mass) * deltaTimeSquared
var height = 0
do {
  height += velocity
  velocity = velocity * frictionAir + (gravity / a.mass) * deltaTimeSquared
} while (velocity < -0.05)

console.log(height) // this is the height of the jump

I got all that from reading and debugging matter-js


Full disclosure

I never worked with Matter.js before, this is my first experience with it...
This is a complex question, my objective here was not spend hours (possibly days) to give you the final formula/function to calculate what you need, but instead to show you how to can tackle this problem that way next time you come across something similar you know where to start.

Related