Magnet.js

/**
Create a magnet. A magnet is a ball that attracts or repels other bodies.

@param {world} world - Pass the Matter.js world
@param {object} attributes - Visual properties e.g. position, radius and color
@param {object} [options] - Defines the behaviour e.g. mass, bouncyness or whether it can move
@extends Ball
*/

class Magnet extends Ball {

  constructor(world, attributes, options) {
    super(world, attributes, options);
    this.attracted = [];
    this.isActive = this.attributes.attraction;
  }

  /**
   * Adds a body to the internal attracted array of the magnet.
   * @param {body} obj
   * @memberof Magnet
   */
  addAttracted(obj) {
    if (obj.length) {
      this.attracted = this.attracted.concat(obj);
    } else {
      this.attracted.push(obj);
    }
  }

  /**
   * Update the positions of all attracted boddies of the magnet.
   * @memberof Magnet
   */
  attract() {
    if (this.isActive) {
      this.attracted.forEach(obj => {
        if (obj.body) {
          obj = obj.body;
        }
        let force = {
          x: (this.body.position.x - obj.position.x),
          y: (this.body.position.y - obj.position.y)
        }
        //Matter.Body.applyForce(ball, ball.position, Matter.Vector.neg(force));
        Matter.Body.applyForce(obj, obj.position, Matter.Vector.mult(force, this.attributes.attraction));
      })
    }
  }

  /**
   * Update the positions of all attracted boddies of the magnet, while using Newton's law of gravitation.
   * @memberof Magnet
   */
  gravity() {
    if (this.isActive) {
      this.attracted.forEach(obj => {
        if (obj.body) {
          obj = obj.body;
        }
        // use Newton's law of gravitation
        let bToA = Matter.Vector.sub(obj.position, this.body.position);
        let distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001;
        let normal = Matter.Vector.normalise(bToA);
        let magnitude = -this.attributes.attraction * (this.body.mass * obj.mass / distanceSq);
        let force = Matter.Vector.mult(normal, magnitude);
        // Matter.Body.applyForce(this.body, this.body.position, Matter.Vector.neg(force));
        Matter.Body.applyForce(obj, obj.position, force);
      })
    }
  }
}