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);