diff --git a/README.md b/README.md
index acf02b0e8..0cabe3d6d 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ npm install phaser
or the minified version:
```html
-
+
```
### License
diff --git a/src/gameobjects/GameObject.js b/src/gameobjects/GameObject.js
index d939e1d61..b5b0dd308 100644
--- a/src/gameobjects/GameObject.js
+++ b/src/gameobjects/GameObject.js
@@ -342,11 +342,9 @@ var GameObject = new Class({
this.data = undefined;
}
- // TODO Keep a reference to the manager in Body, so body can remove itself, not via System
if (this.body)
{
- // sys.physicsManager.remove(this);
-
+ this.body.destroy();
this.body = undefined;
}
diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js
index 31a49b8e3..9a14a77c7 100644
--- a/src/physics/arcade/Body.js
+++ b/src/physics/arcade/Body.js
@@ -84,6 +84,18 @@ var Body = new Class({
*/
this.enable = true;
+ /**
+ * If Body.destroy is called during the main physics update loop then this flag is set.
+ * The Body is then actually destroyed during World.postUpdate.
+ * You can also toggle it yourself.
+ *
+ * @name Phaser.Physics.Arcade.Body#pendingDestroy
+ * @type {boolean}
+ * @default false
+ * @since 3.0.0
+ */
+ this.pendingDestroy = false;
+
/**
* [description]
*
@@ -1267,8 +1279,17 @@ var Body = new Class({
*/
destroy: function ()
{
- this.gameObject.body = null;
- this.gameObject = null;
+ if (!this.pendingDestroy)
+ {
+ // Will be removed the next time World.postUpdate runs, not before.
+ this.pendingDestroy = true;
+ }
+ else
+ {
+ this.world.disableBody(this);
+
+ this.world = null;
+ }
},
/**
diff --git a/src/physics/arcade/Collider.js b/src/physics/arcade/Collider.js
index 597ab07a1..39babc7e6 100644
--- a/src/physics/arcade/Collider.js
+++ b/src/physics/arcade/Collider.js
@@ -38,6 +38,15 @@ var Collider = new Class({
*/
this.world = world;
+ /**
+ * [description]
+ *
+ * @name Phaser.Physics.Arcade.Collider#name
+ * @type {string}
+ * @since 3.0.0
+ */
+ this.name = '';
+
/**
* [description]
*
@@ -103,6 +112,23 @@ var Collider = new Class({
this.callbackContext = callbackContext;
},
+ /**
+ * [description]
+ *
+ * @method Phaser.Physics.Arcade.Collider#setName
+ * @since 3.0.0
+ *
+ * @param {string} name - [description]
+ *
+ * @return {Phaser.Physics.Arcade.Collider} [description]
+ */
+ setName: function (name)
+ {
+ this.name = name;
+
+ return this;
+ },
+
/**
* [description]
*
diff --git a/src/physics/arcade/World.js b/src/physics/arcade/World.js
index 29c9dc2a6..c3eeff335 100644
--- a/src/physics/arcade/World.js
+++ b/src/physics/arcade/World.js
@@ -364,7 +364,7 @@ var World = new Class({
}
else
{
- this.disableBody(object[i]);
+ this.disableGameObjectBody(object[i]);
}
}
}
@@ -375,21 +375,21 @@ var World = new Class({
}
else
{
- this.disableBody(object);
+ this.disableGameObjectBody(object);
}
},
/**
* [description]
*
- * @method Phaser.Physics.Arcade.World#disableBody
+ * @method Phaser.Physics.Arcade.World#disableGameObjectBody
* @since 3.0.0
*
* @param {Phaser.GameObjects.GameObject} object - [description]
*
* @return {Phaser.GameObjects.GameObject} [description]
*/
- disableBody: function (object)
+ disableGameObjectBody: function (object)
{
if (object.body)
{
@@ -403,13 +403,36 @@ var World = new Class({
this.staticTree.remove(object.body);
}
- object.body.destroy();
- object.body = null;
+ object.body.enable = false;
}
return object;
},
+ /**
+ * [description]
+ *
+ * @method Phaser.Physics.Arcade.World#disableBody
+ * @since 3.0.0
+ *
+ * @param {Phaser.Physics.Arcade.Body} body - [description]
+ */
+ disableBody: function (body)
+ {
+ if (body.physicsType === CONST.DYNAMIC_BODY)
+ {
+ this.tree.remove(body);
+ this.bodies.delete(body);
+ }
+ else if (body.physicsType === CONST.STATIC_BODY)
+ {
+ this.staticBodies.delete(body);
+ this.staticTree.remove(body);
+ }
+
+ body.enable = false;
+ },
+
/**
* [description]
*
@@ -662,6 +685,8 @@ var World = new Class({
var bodies = this.bodies.entries;
var len = bodies.length;
+ var toDestroy = [];
+
for (i = 0; i < len; i++)
{
body = bodies[i];
@@ -670,6 +695,11 @@ var World = new Class({
{
body.postUpdate();
}
+
+ if (body.pendingDestroy)
+ {
+ toDestroy.push(body);
+ }
}
if (this.drawDebug)
@@ -701,6 +731,15 @@ var World = new Class({
}
}
}
+
+ for (i = 0; i < toDestroy.length; i++)
+ {
+ body = toDestroy[i];
+
+ this.emit('destroybody', this, body);
+
+ body.destroy();
+ }
},
/**
@@ -1403,13 +1442,13 @@ var World = new Class({
*/
collideSpriteVsGroup: function (sprite, group, collideCallback, processCallback, callbackContext, overlapOnly)
{
- if (group.length === 0)
+ var bodyA = sprite.body;
+
+ if (group.length === 0 || !bodyA)
{
return;
}
- var bodyA = sprite.body;
-
// Does sprite collide with anything?
var minMax = this.treeMinMax;
@@ -1608,6 +1647,13 @@ var World = new Class({
{
return;
}
+
+ var children = group1.getChildren();
+
+ for (var i = 0; i < children.length; i++)
+ {
+ this.collideSpriteVsGroup(children[i], group2, collideCallback, processCallback, callbackContext, overlapOnly);
+ }
},
/**
@@ -1629,6 +1675,12 @@ var World = new Class({
*/
destroy: function ()
{
+ this.tree.clear();
+ this.staticTree.clear();
+ this.bodies.clear();
+ this.staticBodies.clear();
+ this.colliders.destroy();
+
this.removeAllListeners();
}
diff --git a/src/physics/impact/Body.js b/src/physics/impact/Body.js
index b77d6c3fe..efdfaa389 100644
--- a/src/physics/impact/Body.js
+++ b/src/physics/impact/Body.js
@@ -572,6 +572,8 @@ var Body = new Class({
*/
destroy: function ()
{
+ this.world.remove(this);
+
this.enabled = false;
this.world = null;
diff --git a/src/physics/matter-js/components/SetBody.js b/src/physics/matter-js/components/SetBody.js
index 9ae6714e7..76ccec15e 100644
--- a/src/physics/matter-js/components/SetBody.js
+++ b/src/physics/matter-js/components/SetBody.js
@@ -112,6 +112,14 @@ var SetBody = {
this.body = body;
this.body.gameObject = this;
+ var _this = this;
+
+ this.body.destroy = function ()
+ {
+ _this.world.remove(_this.body);
+ _this.body.gameObject = null;
+ };
+
if (addToWorld)
{
this.world.add(this.body);