phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
154 lines (136 loc) • 5.16 kB
JavaScript
var Matter = require('../../CustomMain');
/**
* An attractors plugin for matter.js.
* See the readme for usage and examples.
* @module MatterAttractors
*/
var MatterAttractors =
{
name: 'matter-attractors',
version: '0.1.7',
for: 'matter-js@^0.19.0',
silent: true,
// installs the plugin where `base` is `Matter`
// you should not need to call this directly.
install: function (base)
{
base.after('Body.create', function ()
{
MatterAttractors.Body.init(this);
});
base.before('Engine.update', function (engine)
{
MatterAttractors.Engine.update(engine);
});
},
Body:
{
/**
* Initialises the `body` to support attractors.
* This is called automatically by the plugin.
* @function MatterAttractors.Body.init
* @param {Matter.Body} body The body to init.
* @returns {void} No return value.
*/
init: function (body)
{
body.plugin.attractors = body.plugin.attractors || [];
}
},
Engine:
{
/**
* Applies all attractors for all bodies in the `engine`.
* This is called automatically by the plugin.
* @function MatterAttractors.Engine.update
* @param {Matter.Engine} engine The engine to update.
* @returns {void} No return value.
*/
update: function (engine)
{
var bodies = Matter.Composite.allBodies(engine.world);
for (var i = 0; i < bodies.length; i++)
{
var bodyA = bodies[i];
var attractors = bodyA.plugin.attractors;
if (attractors && attractors.length > 0)
{
for (var j = 0; j < bodies.length; j++)
{
var bodyB = bodies[j];
if (i !== j)
{
for (var k = 0; k < attractors.length; k++)
{
var attractor = attractors[k];
var forceVector = attractor;
if (Matter.Common.isFunction(attractor))
{
forceVector = attractor(bodyA, bodyB);
}
if (forceVector)
{
Matter.Body.applyForce(bodyB, bodyB.position, forceVector);
}
}
}
}
}
}
}
},
/**
* 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);
var distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001;
var normal = Matter.Vector.normalise(bToA);
var magnitude = -MatterAttractors.Attractors.gravityConstant * (bodyA.mass * bodyB.mass / distanceSq);
var 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);
}
}
};
module.exports = MatterAttractors;
/**
* @namespace Matter.Body
* @see http://brm.io/matter-js/docs/classes/Body.html
*/
/**
* This plugin adds a new property `body.plugin.attractors` to instances of `Matter.Body`.
* This is an array of callback functions that will be called automatically
* for every pair of bodies, on every engine update.
* @property {Function[]} body.plugin.attractors
* @memberof Matter.Body
*/
/**
* An attractor function calculates the force to be applied
* to `bodyB`, it should either:
* - return the force vector to be applied to `bodyB`
* - or apply the force to the body(s) itself
* @callback AttractorFunction
* @param {Matter.Body} bodyA
* @param {Matter.Body} bodyB
* @returns {(Vector|undefined)} a force vector (optional)
*/