diff --git a/README.md b/README.md
index 86ea623..f519d1b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[brm.io/matter-js](http://brm.io/matter-js/)
-[Demos](#demos) - [Gallery](#gallery) - [Features](#features) - [Install](#install) - [Usage](#usage) - [Examples](#examples) - [Docs](#documentation) - [Wiki](https://github.com/liabru/matter-js/wiki) - [References](#references) - [License](#license)
+[Demos](#demos) - [Gallery](#gallery) - [Features](#features) - [Plugins](#plugins) - [Install](#install) - [Usage](#usage) - [Examples](#examples) - [Docs](#documentation) - [Wiki](https://github.com/liabru/matter-js/wiki) - [References](#references) - [License](#license)
[![Build Status](https://travis-ci.org/liabru/matter-js.png?branch=master)](https://travis-ci.org/liabru/matter-js)
@@ -97,6 +97,7 @@ See how others are using matter.js physics
- Constraints
- Gravity
- Sleeping and static bodies
+- Plugins
- Rounded corners (chamfering)
- Views (translate, zoom)
- Collision queries (raycasting, region tests)
@@ -129,6 +130,15 @@ Also see the [Rendering](https://github.com/liabru/matter-js/wiki/Rendering) wik
See the [examples](https://github.com/liabru/matter-js/tree/master/examples) directory which contains the source for all [demos](#demos).
There are even more examples on [codepen](http://codepen.io/collection/Fuagy/).
+### Plugins
+
+The engine can be extended through plugins, see these resources:
+
+- [Using plugins](https://github.com/liabru/matter-js/wiki/Using-plugins)
+- [Creating plugins](https://github.com/liabru/matter-js/wiki/Creating-plugins)
+- [List of plugins](https://github.com/liabru/matter-js/wiki/List-of-plugins)
+- [matter-plugin-boilerplate](https://github.com/liabru/matter-plugin-boilerplate)
+
### Documentation
See the [API Documentation](http://brm.io/matter-js/docs/) and the [wiki](https://github.com/liabru/matter-js/wiki)
diff --git a/demo/index.html b/demo/index.html
index 37074e3..880edac 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -26,13 +26,10 @@
-
-
-
+
-
diff --git a/demo/js/Demo.js b/demo/js/Demo.js
index 7c88a28..014bb6e 100644
--- a/demo/js/Demo.js
+++ b/demo/js/Demo.js
@@ -34,12 +34,6 @@
init: Example.airFriction,
sourceLink: sourceLinkRoot + '/airFriction.js'
},
- {
- name: 'Attractors',
- id: 'attractors',
- init: Example.attractors,
- sourceLink: sourceLinkRoot + '/attractors.js'
- },
{
name: 'Avalanche',
id: 'avalanche',
diff --git a/demo/lib/matter-wrap.js b/demo/lib/matter-wrap.js
new file mode 100644
index 0000000..5d16c49
--- /dev/null
+++ b/demo/lib/matter-wrap.js
@@ -0,0 +1,199 @@
+/*!
+ * matter-wrap 0.1.2 by Liam Brummitt 2017-02-12
+ * https://github.com/liabru/matter-wrap
+ * License MIT
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("Matter"));
+ else if(typeof define === 'function' && define.amd)
+ define(["Matter"], factory);
+ else if(typeof exports === 'object')
+ exports["MatterWrap"] = factory(require("Matter"));
+ else
+ root["MatterWrap"] = factory(root["Matter"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "/libs";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 1);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var Matter = __webpack_require__(0);
+
+/**
+ * A coordinate wrapping plugin for matter.js.
+ * See the readme for usage and examples.
+ * @module MatterWrap
+ */
+var MatterWrap = {
+ // plugin meta
+ name: 'matter-wrap', // PLUGIN_NAME
+ version: '0.1.0', // PLUGIN_VERSION
+ for: 'matter-js@^0.12.0',
+
+ // installs the plugin where `base` is `Matter`
+ // you should not need to call this directly.
+ install: function install(base) {
+ base.after('Engine.update', function () {
+ MatterWrap.Engine.update(this);
+ });
+ },
+
+ Engine: {
+ /**
+ * Updates the engine by wrapping bodies inside `engine.world`.
+ * This is called automatically by the plugin.
+ * @function MatterWrap.Engine.update
+ * @param {Matter.Engine} engine The engine to update.
+ * @returns {void} No return value.
+ */
+ update: function update(engine) {
+ var world = engine.world,
+ bodies = Matter.Composite.allBodies(world);
+
+ for (var i = 0; i < bodies.length; i += 1) {
+ var body = bodies[i];
+
+ if (body.plugin.wrap) {
+ MatterWrap.Body.wrap(body, body.plugin.wrap);
+ }
+ }
+ }
+ },
+
+ Body: {
+ /**
+ * Wraps the `body` position such that it always stay within the given bounds.
+ * Upon crossing a boundary the body will appear on the opposite side of the bounds,
+ * while maintaining its velocity.
+ * This is called automatically by the plugin.
+ * @function MatterAttractors.Body.wrap
+ * @param {Matter.Body} body The body to wrap.
+ * @param {Matter.Bounds} bounds The bounds to wrap the body inside.
+ * @returns {void} No return value.
+ */
+ wrap: function wrap(body, bounds) {
+ var x = null,
+ y = null;
+
+ if (typeof bounds.min.x !== 'undefined' && typeof bounds.max.x !== 'undefined') {
+ if (body.bounds.min.x > bounds.max.x) {
+ x = bounds.min.x - (body.bounds.max.x - body.position.x);
+ } else if (body.bounds.max.x < bounds.min.x) {
+ x = bounds.max.x - (body.bounds.min.x - body.position.x);
+ }
+ }
+
+ if (typeof bounds.min.y !== 'undefined' && typeof bounds.max.y !== 'undefined') {
+ if (body.bounds.min.y > bounds.max.y) {
+ y = bounds.min.y - (body.bounds.max.y - body.position.y);
+ } else if (body.bounds.max.y < bounds.min.y) {
+ y = bounds.max.y - (body.bounds.min.y - body.position.y);
+ }
+ }
+
+ if (x !== null || y !== null) {
+ Matter.Body.setPosition(body, {
+ x: x || body.position.x,
+ y: y || body.position.y
+ });
+ }
+ }
+ }
+};
+
+Matter.Plugin.register(MatterWrap);
+
+module.exports = MatterWrap;
+
+/**
+ * @namespace Matter.Body
+ * @see http://brm.io/matter-js/docs/classes/Body.html
+ */
+
+/**
+ * This plugin adds a new property `body.plugin.wrap` to instances of `Matter.Body`.
+ * This is a `Matter.Bounds` instance that specifies the wrapping region.
+ * @property {Matter.Bounds} body.plugin.wrap
+ * @memberof Matter.Body
+ */
+
+/***/ })
+/******/ ]);
+});
\ No newline at end of file
diff --git a/examples/attractors.js b/examples/attractors.js
deleted file mode 100644
index d5c019b..0000000
--- a/examples/attractors.js
+++ /dev/null
@@ -1,111 +0,0 @@
-var Example = Example || {};
-
-Matter.use(
- 'matter-gravity',
- 'matter-wrap'
-);
-
-Example.attractors = function() {
- var Engine = Matter.Engine,
- Render = Matter.Render,
- Runner = Matter.Runner,
- Body = Matter.Body,
- Common = Matter.Common,
- MouseConstraint = Matter.MouseConstraint,
- Mouse = Matter.Mouse,
- World = Matter.World,
- Bodies = Matter.Bodies;
-
- // create engine
- var engine = Engine.create(),
- world = engine.world;
-
- // create renderer
- var render = Render.create({
- element: document.body,
- engine: engine,
- options: {
- width: Math.min(document.documentElement.clientWidth, 800),
- height: Math.min(document.documentElement.clientHeight, 600)
- }
- });
-
- Render.run(render);
-
- // create runner
- var runner = Runner.create();
- Runner.run(runner, engine);
-
- // add bodies
- world.bodies = [];
- world.gravity.scale = 0;
-
- var G = 0.001;
-
- engine.timing.timeScale = 1.5;
-
- for (var i = 0; i < 150; i += 1) {
- var radius = Common.random(6, 10);
-
- var body = Bodies.circle(
- Common.random(10, render.options.width),
- Common.random(10, render.options.height),
- radius,
- {
- mass: Common.random(10, 15),
- frictionAir: 0,
- plugin: {
- gravity: G,
- wrap: {
- min: { x: 0, y: 0 },
- max: { x: render.options.width, y: render.options.height }
- }
- }
- }
- );
-
- var speed = 5;
-
- Body.setVelocity(body, {
- x: Common.random(-speed, speed),
- y: Common.random(-speed, speed)
- });
-
- World.add(world, body);
- }
-
- // add mouse control
- var mouse = Mouse.create(render.canvas),
- mouseConstraint = MouseConstraint.create(engine, {
- mouse: mouse,
- constraint: {
- stiffness: 0.2,
- render: {
- visible: false
- }
- }
- });
-
- World.add(world, mouseConstraint);
-
- // keep the mouse in sync with rendering
- render.mouse = mouse;
-
- // fit the render viewport to the scene
- Render.lookAt(render, {
- min: { x: 0, y: 0 },
- max: { x: 800, y: 600 }
- });
-
- // context for MatterTools.Demo
- return {
- engine: engine,
- runner: runner,
- render: render,
- canvas: render.canvas,
- stop: function() {
- Matter.Render.stop(render);
- Matter.Runner.stop(runner);
- }
- };
-};
\ No newline at end of file
diff --git a/examples/attractorsPlugin.js b/examples/attractorsPlugin.js
deleted file mode 100644
index aabe558..0000000
--- a/examples/attractorsPlugin.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// NOTE: this plugin will be moved to its own repo
-
-(function() {
-
- var MatterAttractors = {
- name: 'matter-attractors',
-
- version: '0.1.0',
-
- for: 'matter-js@^0.10.0',
-
- install: function(base) {
- base.after('Body.create', function() {
- MatterAttractors.Body.init(this);
- });
-
- base.after('Engine.update', function() {
- MatterAttractors.Engine.update(this);
- });
- },
-
- Body: {
- init: function(body) {
- body.attractors = body.attractors || [];
- }
- },
-
- Engine: {
- update: function(engine) {
- var world = engine.world,
- bodies = Matter.Composite.allBodies(world);
-
- for (var i = 0; i < bodies.length; i += 1) {
- var bodyA = bodies[i],
- attractors = bodyA.attractors;
-
- if (attractors && attractors.length > 0) {
- for (var j = i + 1; j < bodies.length; j += 1) {
- var bodyB = bodies[j];
-
- for (var k = 0; k < attractors.length; k += 1) {
- var attractor = attractors[k],
- forceVector = attractor;
-
- if (Matter.Common.isFunction(attractor)) {
- forceVector = attractor(bodyA, bodyB);
- }
-
- if (forceVector) {
- Matter.Body.applyForce(bodyB, bodyB.position, forceVector);
- }
- }
- }
- }
- }
- }
- }
- };
-
- Matter.Plugin.register(MatterAttractors);
-
- if (typeof window !== 'undefined') {
- window.MatterAttractors = MatterAttractors;
- }
-
-})();
diff --git a/examples/gravityPlugin.js b/examples/gravityPlugin.js
deleted file mode 100644
index 1076c52..0000000
--- a/examples/gravityPlugin.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// NOTE: this plugin will be moved to its own repo
-
-(function() {
-
- var MatterGravity = {
- name: 'matter-gravity',
-
- version: '0.1.0',
-
- for: 'matter-js@^0.10.0',
-
- uses: [
- 'matter-attractors@^0.1.0'
- ],
-
- install: function(base) {
- base.after('Body.create', function() {
- MatterGravity.Body.init(this);
- });
- },
-
- Body: {
- init: function(body) {
- if (body.plugin.gravity) {
- body.attractors.push(MatterGravity.Body.applyGravity);
- }
- },
-
- applyGravity: function(bodyA, bodyB) {
- var bToA = Matter.Vector.sub(bodyB.position, bodyA.position),
- distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001,
- normal = Matter.Vector.normalise(bToA),
- magnitude = -bodyA.plugin.gravity * (bodyA.mass * bodyB.mass / distanceSq),
- force = Matter.Vector.mult(normal, magnitude);
-
- Matter.Body.applyForce(bodyA, bodyA.position, Matter.Vector.neg(force));
- Matter.Body.applyForce(bodyB, bodyB.position, force);
- }
- }
- };
-
- Matter.Plugin.register(MatterGravity);
-
- if (typeof window !== 'undefined') {
- window.MatterGravity = MatterGravity;
- }
-
-})();
diff --git a/examples/wrapPlugin.js b/examples/wrapPlugin.js
deleted file mode 100644
index 220c70d..0000000
--- a/examples/wrapPlugin.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// NOTE: this plugin will be moved to its own repo
-
-(function() {
-
- var MatterWrap = {
- name: 'matter-wrap',
-
- version: '0.1.0',
-
- for: 'matter-js@^0.10.0',
-
- install: function(base) {
- base.after('Engine.update', function() {
- MatterWrap.Engine.update(this);
- });
- },
-
- Engine: {
- update: function(engine) {
- var world = engine.world,
- bodies = Matter.Composite.allBodies(world);
-
- for (var i = 0; i < bodies.length; i += 1) {
- var body = bodies[i];
-
- if (body.plugin.wrap) {
- MatterWrap.Body.wrap(body, body.plugin.wrap);
- }
- }
- }
- },
-
- Body: {
- wrap: function(body, bounds) {
- var x = null,
- y = null;
-
- if (typeof bounds.min.x !== 'undefined' && typeof bounds.max.x !== 'undefined') {
- if (body.bounds.min.x > bounds.max.x) {
- x = bounds.min.x - (body.bounds.max.x - body.position.x);
- } else if (body.bounds.max.x < bounds.min.x) {
- x = bounds.max.x - (body.bounds.min.x - body.position.x);
- }
- }
-
- if (typeof bounds.min.y !== 'undefined' && typeof bounds.max.y !== 'undefined') {
- if (body.bounds.min.y > bounds.max.y) {
- y = bounds.min.y - (body.bounds.max.y - body.position.y);
- } else if (body.bounds.max.y < bounds.min.y) {
- y = bounds.max.y - (body.bounds.min.y - body.position.y);
- }
- }
-
- if (x !== null || y !== null) {
- Matter.Body.setPosition(body, {
- x: x || body.position.x,
- y: y || body.position.y
- });
- }
- }
- }
- };
-
- Matter.Plugin.register(MatterWrap);
-
- if (typeof window !== 'undefined') {
- window.MatterWrap = MatterWrap;
- }
-
-})();