Matter.js Gravity Point
Asked Answered
W

2

6

Is it possible to create a single gravity / force point in matter.js that is at the center of x/y coordinates?

I have managed to do it with d3.js but wanted to enquire about matter.js as it has the ability to use multiple polyshapes.

http://bl.ocks.org/mbostock/1021841

Warrantor answered 11/8, 2015 at 9:30 Comment(1)
Link is dead, probably due to Heroku free tier disappearing recently. Do we have an update to that for posterity?Acutance
W
4

The illustrious answer has arisen:

not sure if there is any interest in this. I'm a fan of what you have created. In my latest project, I used matter-js but I needed elements to gravitate to a specific point, rather than into a general direction. That was very easily accomplished. I was wondering if you are interested in that feature as well, it would not break anything.

All one has to do is setting engine.world.gravity.isPoint = true and then the gravity vector is used as point, rather than a direction. One might set:

engine.world.gravity.x = 355;
engine.world.gravity.y = 125;
engine.world.gravity.isPoint = true;

and all objects will gravitate to that point.

If this is not within the scope of this engine, I understand. Either way, thanks for the great work.

Warrantor answered 11/8, 2015 at 9:31 Comment(5)
could you please make a little demo of this functionality? I was trying around for now about two hours and couldn't get it work.Isleana
>= 0.17.0, use engine.gravity. World is deprecated.Acutance
@Acutance would love to see an example as I see no reference of isPoint in the docs.Yamauchi
@ZachSaucier The merge request that was linked by this answer which implements isPoint was closed unmerged, with the final comment by the author of the MJS library pointing to a plugin, github.com/liabru/matter-attractors.Acutance
I added an answer that hopefully clarifies the situation.Acutance
A
2

You can do this with the matter-attractors plugin. Here's their basic example:

Matter.use(
  'matter-attractors' // PLUGIN_NAME
);

var Engine = Matter.Engine,
    Events = Matter.Events,
    Runner = Matter.Runner,
    Render = Matter.Render,
    World = Matter.World,
    Body = Matter.Body,
    Mouse = Matter.Mouse,
    Common = Matter.Common,
    Bodies = Matter.Bodies;

// create engine
var engine = Engine.create();

// create renderer
var render = Render.create({
  element: document.body,
  engine: engine,
  options: {
    width: Math.min(document.documentElement.clientWidth, 1024),
    height: Math.min(document.documentElement.clientHeight, 1024),
    wireframes: false
  }
});

// create runner
var runner = Runner.create();

Runner.run(runner, engine);
Render.run(render);

// create demo scene
var world = engine.world;
world.gravity.scale = 0;

// create a body with an attractor
var attractiveBody = Bodies.circle(
  render.options.width / 2,
  render.options.height / 2,
  50, 
  {
  isStatic: true,

  // example of an attractor function that 
  // returns a force vector that applies to bodyB
  plugin: {
    attractors: [
      function(bodyA, bodyB) {
        return {
          x: (bodyA.position.x - bodyB.position.x) * 1e-6,
          y: (bodyA.position.y - bodyB.position.y) * 1e-6,
        };
      }
    ]
  }
});

World.add(world, attractiveBody);

// add some bodies that to be attracted
for (var i = 0; i < 150; i += 1) {
  var body = Bodies.polygon(
    Common.random(0, render.options.width), 
    Common.random(0, render.options.height),
    Common.random(1, 5),
    Common.random() > 0.9 ? Common.random(15, 25) : Common.random(5, 10)
  );

  World.add(world, body);
}

// add mouse control
var mouse = Mouse.create(render.canvas);

Events.on(engine, 'afterUpdate', function() {
    if (!mouse.position.x) {
      return;
    }

    // smoothly move the attractor body towards the mouse
    Body.translate(attractiveBody, {
        x: (mouse.position.x - attractiveBody.position.x) * 0.25,
        y: (mouse.position.y - attractiveBody.position.y) * 0.25
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.12.0/matter.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/matter-attractors.min.js"></script>

Historical note: the "gravity point" functionality was proposed as a feature in MJS as PR #132 but it was closed, with the author of MJS (liabru) offering the matter-attractors plugin as an alternate. At the time of writing, this answer misleadingly seems to indicate that functionality from the PR was in fact merged.

Unfortunately, the attractors library is 6 years outdated at the time of writing and raises a warning when using a newer version of MJS than 0.12.0. From discussion in issue #11, it sounds like it's OK to ignore the warning and use this plugin with, for example, 0.18.0. Here's the warning:

matter-js: Plugin.use: [email protected] is for matter-js@^0.12.0 but installed on [email protected].

Behavior seemed fine on cursory glance, but I'll keep 0.12.0 in the above example to silence it anyway. If you do update to a recent version, note that Matter.World is deprecated and should be replaced with Matter.Composite and engine.gravity.

Acutance answered 15/12, 2022 at 19:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.