diff --git a/README.md b/README.md index 054ea74a0..074802b41 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ New features: * Buttons now properly use their upFrame if set. * InputHandler now has snapOffsetX and snapOffsetY properties so your snap grid doesn't have to be 0,0 aligned (thanks srmeier) * Loader.progressFloat contains the actual non-rounded progress value, where-as Loader.progress contains a rounded value. Use progressFloat if you've > 100 files to load. +* Groups can now be added to other Groups as children via group.add() and group.addAt() +* Groups now have an 'alive' property, which can be useful when iterating through child groups with functions like forEachAlive. New Examples: @@ -99,6 +101,7 @@ New Examples: * Animation - Group Creation, showing how to create animations across all Group children in one call. * Particles - Rain by Jens Anders Bakke. * Particles - Snow by Jens Anders Bakke. +* Groups - Nested Groups - showing how to embed one Group into another Group. Updates: diff --git a/examples/groups/extending a group.js b/examples/groups/extending a group.js index cd5fb8964..343c9ce3e 100644 --- a/examples/groups/extending a group.js +++ b/examples/groups/extending a group.js @@ -1,49 +1,45 @@ -window.onload = function() { +// Here is a custom group +// It will automatically create 30 sprites of the given image when created. - // Here is a custom group - // It will automatically create 30 sprites of the given image when created. +MonsterGroup = function (game, image, action) { - MonsterGroup = function (game, image, action) { + Phaser.Group.call(this, game); - Phaser.Group.call(this, game); + for (var i = 0; i < 30; i++) + { + var sprite = this.create(game.world.randomX, game.world.randomY, image); - for (var i = 0; i < 30; i++) + if (action == 'bounce') { - var sprite = this.create(game.world.randomX, game.world.randomY, image); - - if (action == 'bounce') - { - game.add.tween(sprite).to({ y: sprite.y - 100 }, 2000, Phaser.Easing.Elastic.Out, true, 0, 1000, true); - } - else if (action == 'slide') - { - game.add.tween(sprite).to({ x: sprite.x + 200 }, 4000, Phaser.Easing.Elastic.Out, true, 0, 1000, true); - } - + game.add.tween(sprite).to({ y: sprite.y - 100 }, 2000, Phaser.Easing.Elastic.Out, true, 0, 1000, true); + } + else if (action == 'slide') + { + game.add.tween(sprite).to({ x: sprite.x + 200 }, 4000, Phaser.Easing.Elastic.Out, true, 0, 1000, true); } - }; - - MonsterGroup.prototype = Object.create(Phaser.Group.prototype); - MonsterGroup.prototype.constructor = MonsterGroup; - - var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create }); - - var customGroup1; - var customGroup2; - - function preload() { - - game.load.image('ufo', 'assets/sprites/ufo.png'); - game.load.image('baddie', 'assets/sprites/space-baddie.png'); - } - function create() { +}; - customGroup1 = new MonsterGroup(game, 'ufo', 'bounce'); - customGroup2 = new MonsterGroup(game, 'baddie', 'slide'); +MonsterGroup.prototype = Object.create(Phaser.Group.prototype); +MonsterGroup.prototype.constructor = MonsterGroup; - } +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create }); -}(); +var customGroup1; +var customGroup2; + +function preload() { + + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + +} + +function create() { + + customGroup1 = new MonsterGroup(game, 'ufo', 'bounce'); + customGroup2 = new MonsterGroup(game, 'baddie', 'slide'); + +} diff --git a/examples/groups/nested groups.js b/examples/groups/nested groups.js new file mode 100644 index 000000000..c204b9f51 --- /dev/null +++ b/examples/groups/nested groups.js @@ -0,0 +1,40 @@ + +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); + +function preload() { + + game.load.image('ball', 'assets/sprites/pangball.png'); + game.load.image('arrow', 'assets/sprites/asteroids_ship.png'); + +} + +var ballsGroup; +var shipsGroup; + +function create() { + + ballsGroup = game.add.group(); + shipsGroup = game.add.group(); + + for (var i = 0; i < 20; i++) + { + // Create some randomly placed sprites in both Groups + ballsGroup.create(game.rnd.integerInRange(0, 128), game.world.randomY, 'ball'); + shipsGroup.create(game.rnd.integerInRange(0, 128), game.world.randomY, 'arrow'); + } + + // Now make the ships group a child of the balls group - so anything that happens to the balls group + // will happen to the ships group too + ballsGroup.add(shipsGroup); + +} + +function update() { + + ballsGroup.x += 0.1; + + // Because shipsGroup is a child of ballsGroup it has already been moved 0.1px by the line above + // So the following line of code will make it appear to move twice as fast as ballsGroup + shipsGroup.x += 0.1; + +} diff --git a/examples/wip/group extends.js b/examples/wip/group extends.js new file mode 100644 index 000000000..4e5a5be45 --- /dev/null +++ b/examples/wip/group extends.js @@ -0,0 +1,47 @@ + +// Here is a custom group with a property 'key' +// This isn't required, it's just an example of a custom group level property. Only 'game' is required. +MonsterGroup = function (game, key) { + + Phaser.Group.call(this, game); + + this.key = key; + +}; + +MonsterGroup.prototype = Object.create(Phaser.Group.prototype); +MonsterGroup.prototype.constructor = MonsterGroup; + +/** + * Generate some monsters on request, all spaced out evenly + */ +MonsterGroup.prototype.make = function(qty, x, y) { + + for (var i = 0; i < qty; i++) + { + this.create(x, y, this.key); + x += 64; + } + +} + +// Boilerplate code below + +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create }); + +function preload() { + + game.load.image('bunny', 'assets/sprites/bunny.png'); + game.load.image('ball', 'assets/sprites/shinyball.png'); + +} + +function create() { + + var monsters = new MonsterGroup(game, 'bunny'); + var balls = new MonsterGroup(game, 'ball'); + + monsters.make(6, 100, 100); + balls.make(10, 64, 500); + +} diff --git a/examples/wip/nested groups.js b/examples/wip/nested groups.js new file mode 100644 index 000000000..cf5902df2 --- /dev/null +++ b/examples/wip/nested groups.js @@ -0,0 +1,41 @@ + +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); + +function preload() { + + game.load.image('ball', 'assets/sprites/pangball.png'); + game.load.image('arrow', 'assets/sprites/asteroids_ship.png'); + +} + +var ballsGroup; +var shipsGroup; + +function create() { + + ballsGroup = game.add.group(); + shipsGroup = game.add.group(); + + for (var i = 0; i < 20; i++) + { + // Create some randomly placed sprites in both Groups + ballsGroup.create(game.rnd.integerInRange(0, 128), game.world.randomY, 'ball'); + shipsGroup.create(game.rnd.integerInRange(0, 128), game.world.randomY, 'arrow'); + } + + // Now make the ships group a child of the balls group - so anything that happens to the balls group + // will happen to the ships group too + ballsGroup.add(shipsGroup); + +} + +function update() { + + ballsGroup.x += 0.1; + + // Because shipsGroup is a child of ballsGroup it has already been moved 0.1px by the line above + // So the following line of code will make it appear to move twice as fast as ballsGroup + shipsGroup.x += 0.1; + +} + diff --git a/src/core/Group.js b/src/core/Group.js index 51b12c90f..c8d1601a0 100644 --- a/src/core/Group.js +++ b/src/core/Group.js @@ -71,12 +71,23 @@ Phaser.Group = function (game, parent, name, useStage) { */ this.type = Phaser.GROUP; + /** + * @property {boolean} alive - The alive property is useful for Groups that are children of other Groups and need to be included/excluded in checks like forEachAlive. + * @default + */ + this.alive = true; + /** * @property {boolean} exists - If exists is true the the Group is updated, otherwise it is skipped. * @default */ this.exists = true; + /** + * @property {Phaser.Group} group - The parent Group of this Group, if a child of another. + */ + this.group = null; + // Replaces the PIXI.Point with a slightly more flexible one. this._container.scale = new Phaser.Point(1, 1); @@ -141,16 +152,27 @@ Phaser.Group.prototype = { if (child.group !== this) { - child.group = this; - - if (child.events) + if (child.type && child.type === Phaser.GROUP) { - child.events.onAddedToGroup.dispatch(child, this); + child.group = this; + + this._container.addChild(child._container); + + child._container.updateTransform(); } + else + { + child.group = this; - this._container.addChild(child); + if (child.events) + { + child.events.onAddedToGroup.dispatch(child, this); + } - child.updateTransform(); + this._container.addChild(child); + + child.updateTransform(); + } if (this.cursor === null) { @@ -175,16 +197,27 @@ Phaser.Group.prototype = { if (child.group !== this) { - child.group = this; - - if (child.events) + if (child.type && child.type === Phaser.GROUP) { - child.events.onAddedToGroup.dispatch(child, this); + child.group = this; + + this._container.addChildAt(child._container, index); + + child._container.updateTransform(); } + else + { + child.group = this; - this._container.addChildAt(child, index); + if (child.events) + { + child.events.onAddedToGroup.dispatch(child, this); + } - child.updateTransform(); + this._container.addChildAt(child, index); + + child.updateTransform(); + } if (this.cursor === null) {