Jump to content

[Solved] How to use Matter-js attractors gravity helper function


Recommended Posts

Hi everyone,

I'm working on a game prototype involving planet gravitational physics. I got inspired by this example in the Phaser 3 official example archives, feature the following code :

    var sun = this.matter.add.image(400, 200, 'sun', null, {
        shape: {
            type: 'circle',
            radius: 64
        plugin: {
            attractors: [
                function (bodyA, bodyB) {
                    return {
                        x: (bodyA.position.x - bodyB.position.x) * 0.000001,
                        y: (bodyA.position.y - bodyB.position.y) * 0.000001

Now, I'd like a more Newtonian function for attraction, and it appears Matter-js got already one ready in MatterAttractors.js, featuring the following :

   * Defines some useful common attractor functions that can be used
   * by pushing them to your body's `body.plugin.attractors` array.
   * @namespace MatterAttractors.Attractors
   * @property {number} gravityConstant The gravitational constant used by the gravity attractor.
  Attractors: {
    gravityConstant: 0.001,

     * An attractor function that applies Newton's law of gravitation.
     * Use this by pushing `MatterAttractors.Attractors.gravity` to your body's `body.plugin.attractors` array.
     * The gravitational constant defaults to `0.001` which you can change
     * at `MatterAttractors.Attractors.gravityConstant`.
     * @function MatterAttractors.Attractors.gravity
     * @param {Matter.Body} bodyA The first body.
     * @param {Matter.Body} bodyB The second body.
     * @returns {void} No return value.
    gravity: function(bodyA, bodyB) {
      // use Newton's law of gravitation
      var bToA = Matter.Vector.sub(bodyB.position, bodyA.position),
        distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001,
        normal = Matter.Vector.normalise(bToA),
        magnitude = -MatterAttractors.Attractors.gravityConstant * (bodyA.mass * bodyB.mass / distanceSq),
        force = Matter.Vector.mult(normal, magnitude);

      // to apply forces to both bodies
      Matter.Body.applyForce(bodyA, bodyA.position, Matter.Vector.neg(force));
      Matter.Body.applyForce(bodyB, bodyB.position, force);


My main problem at this point is that I don't know how to call that gravity function as the callback function for the attractor plugin of my object.

Also, I'm pretty new to using Phaser and Javascript is not a language I used much before (but I picked it for technical reasons). I'm learning a lot and it's quite well written. But I'm basically lost whenever it's about giving a list of options to an object, such as shape or plugin.attractors, or even the config var that set up the engine, because I don't know what are the *valid* options available, or their valid values. And when I use invalid options, I don't get much feedback in term of error messages, it just doesn't work.

I've tried many things to try to "reach" that function but it never worked. At best my object isn't rendered, at worst I got an error "undefined" element. Oh and I also got a case where my object was rendered but not doing any attraction what so ever. 

I'd appreciate some help to keep me coding. Thank you. :)

Link to comment
Share on other sites

  • 11 months later...

I'm down the exact same path you where a year ago, @Neomak

I managed to got what you have without any errors now, but I haven't got an gravity at all. The Phaser 3 example with simplified gravity works nice but with your code I don't see any effect. 

My game config:

const config = {
    type: Phaser.AUTO,
    parent: "phaser-example",
    width: 400,
    height: 700,
    physics:  {
        default: 'matter',
        matter: {
            gravity: {
                x: 0,
                y: 0
	    plugins: {
                attractors: true
	    debug: true
    scene: [ BootScene,

If i remove the gravity-part I get weird warping anti-gravity..

My attractor planet code: 

export default class Planet extends Phaser.Physics.Matter.Image {
    constructor(scene, x, y) {
        super(scene.matter.world, x, y, 'planet', null, {
            shape: {
                type: 'circle',
                radius: 150
            plugin: {
	    	attractors: [Phaser.Physics.Matter.Matter.Plugin.resolve("matter-attractors").Attractors.gravity]

Here tried with a looot of mass and also tried all masses default.

Any help would be much appriciated. 

Edited by Reicher
Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...