diff --git a/README.md b/README.md index 980711ad7..ab2722df0 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,8 @@ If you are an exceptional JavaScript developer and would like to join the Phaser ### New Features * Emitter.emitParticle now has 4 new optional arguments: `x`, `y`, `key` and `frame`. These allow you to override whatever the Emitter default values may be and emit the particle from the given coordinates and with a new texture. +* Group.resetChild is a new method that allows you to call both `child.reset` and/or `child.loadTexture` on the given child object. This is used internally by `getFirstDead` and similar, but is made public so you can use it as a group iteration callback. Note that the child must have public `reset` and `loadTexture` methods to be valid for the call. +* Group.getFirstDead, Group.getFirstAlive and Group.getFirstExists all have new optional arguments: `createIfNull`, `x`, `y`, `key` and `frame`. If the method you call cannot find a matching child (i.e. getFirstDead cannot find any dead children) then the optional `createIfNull` allows you to instantly create a new child in the group using the position and texture arguments to do so. This allows you to always get a child back from the Group and remove the need to do null checks and Group inserts from your game code. The same arguments can also be used in a different way: if `createIfNull` is false AND you provide the extra arguments AND a child is found then it will be passed to the new `Group.resetChild` method. This allows you to retrieve a child from the Group and have it reset and instantly ready for use in your game without any extra code. ### Updates diff --git a/src/core/Group.js b/src/core/Group.js index 34f4c7502..8c6d7f6b6 100644 --- a/src/core/Group.js +++ b/src/core/Group.js @@ -465,13 +465,13 @@ Phaser.Group.prototype.getAt = function (index) { /** * Creates a new Phaser.Sprite object and adds it to the top of this group. * -* Use {@link #classType} to change the type of object creaded. +* Use {@link #classType} to change the type of object created. * * @method Phaser.Group#create * @param {number} x - The x coordinate to display the newly created Sprite at. The value is in relation to the group.x point. * @param {number} y - The y coordinate to display the newly created Sprite at. The value is in relation to the group.y point. -* @param {string} key - The Game.cache key of the image that this Sprite will use. -* @param {integer|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here. +* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache Image entry, or an instance of a RenderTexture, BitmapData, Video or PIXI.Texture. +* @param {string|number} [frame] - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index. * @param {boolean} [exists=true] - The default exists state of the Sprite. * @return {DisplayObject} The child that was created: will be a {@link Phaser.Sprite} unless {@link #classType} has been changed. */ @@ -1773,47 +1773,134 @@ Phaser.Group.prototype.iterate = function (key, value, returnType, callback, cal /** * Get the first display object that exists, or doesn't exist. +* +* You can use the optional argument `createIfNull` to create a new Game Object if none matching your exists argument were found in this Group. +* +* It works by calling `Group.create` passing it the parameters given to this method, and returning the new child. +* +* If a child *was* found , `createIfNull` is `false` and you provided the additional arguments then the child +* will be reset and/or have a new texture loaded on it. This is handled by `Group.resetChild`. * * @method Phaser.Group#getFirstExists * @param {boolean} [exists=true] - If true, find the first existing child; otherwise find the first non-existing child. -* @return {any} The first child, or null if none found. +* @param {boolean} [createIfNull=false] - If `true` and no alive children are found a new one is created. +* @param {number} [x] - The x coordinate to reset the child to. The value is in relation to the group.x point. +* @param {number} [y] - The y coordinate to reset the child to. The value is in relation to the group.y point. +* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache Image entry, or an instance of a RenderTexture, BitmapData, Video or PIXI.Texture. +* @param {string|number} [frame] - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index. +* @return {DisplayObject} The first child, or `null` if none found and `createIfNull` was false. */ -Phaser.Group.prototype.getFirstExists = function (exists) { +Phaser.Group.prototype.getFirstExists = function (exists, createIfNull, x, y, key, frame) { + + if (createIfNull === undefined) { createIfNull = false; } if (typeof exists !== 'boolean') { exists = true; } - return this.iterate('exists', exists, Phaser.Group.RETURN_CHILD); + var child = this.iterate('exists', exists, Phaser.Group.RETURN_CHILD); + + return (child === null && createIfNull) ? this.create(x, y, key, frame) : this.resetChild(child, x, y, key, frame); }; /** * Get the first child that is alive (`child.alive === true`). * -* This is handy for checking if everything has been wiped out, or choosing a squad leader, etc. +* This is handy for choosing a squad leader, etc. +* +* You can use the optional argument `createIfNull` to create a new Game Object if no alive ones were found in this Group. +* +* It works by calling `Group.create` passing it the parameters given to this method, and returning the new child. +* +* If a child *was* found , `createIfNull` is `false` and you provided the additional arguments then the child +* will be reset and/or have a new texture loaded on it. This is handled by `Group.resetChild`. * * @method Phaser.Group#getFirstAlive -* @return {any} The first alive child, or null if none found. +* @param {boolean} [createIfNull=false] - If `true` and no alive children are found a new one is created. +* @param {number} [x] - The x coordinate to reset the child to. The value is in relation to the group.x point. +* @param {number} [y] - The y coordinate to reset the child to. The value is in relation to the group.y point. +* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache Image entry, or an instance of a RenderTexture, BitmapData, Video or PIXI.Texture. +* @param {string|number} [frame] - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index. +* @return {DisplayObject} The alive dead child, or `null` if none found and `createIfNull` was false. */ -Phaser.Group.prototype.getFirstAlive = function () { +Phaser.Group.prototype.getFirstAlive = function (createIfNull, x, y, key, frame) { - return this.iterate('alive', true, Phaser.Group.RETURN_CHILD); + if (createIfNull === undefined) { createIfNull = false; } + + var child = this.iterate('alive', true, Phaser.Group.RETURN_CHILD); + + return (child === null && createIfNull) ? this.create(x, y, key, frame) : this.resetChild(child, x, y, key, frame); }; /** * Get the first child that is dead (`child.alive === false`). * -* This is handy for checking if everything has been wiped out, or choosing a squad leader, etc. +* This is handy for checking if everything has been wiped out and adding to the pool as needed. +* +* You can use the optional argument `createIfNull` to create a new Game Object if no dead ones were found in this Group. +* +* It works by calling `Group.create` passing it the parameters given to this method, and returning the new child. +* +* If a child *was* found , `createIfNull` is `false` and you provided the additional arguments then the child +* will be reset and/or have a new texture loaded on it. This is handled by `Group.resetChild`. * * @method Phaser.Group#getFirstDead -* @return {any} The first dead child, or null if none found. +* @param {boolean} [createIfNull=false] - If `true` and no dead children are found a new one is created. +* @param {number} [x] - The x coordinate to reset the child to. The value is in relation to the group.x point. +* @param {number} [y] - The y coordinate to reset the child to. The value is in relation to the group.y point. +* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache Image entry, or an instance of a RenderTexture, BitmapData, Video or PIXI.Texture. +* @param {string|number} [frame] - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index. +* @return {DisplayObject} The first dead child, or `null` if none found and `createIfNull` was false. */ -Phaser.Group.prototype.getFirstDead = function () { +Phaser.Group.prototype.getFirstDead = function (createIfNull, x, y, key, frame) { - return this.iterate('alive', false, Phaser.Group.RETURN_CHILD); + if (createIfNull === undefined) { createIfNull = false; } + + var child = this.iterate('alive', false, Phaser.Group.RETURN_CHILD); + + return (child === null && createIfNull) ? this.create(x, y, key, frame) : this.resetChild(child, x, y, key, frame); + +}; + +/** +* Takes a child and if the `x` and `y` arguments are given it calls `child.reset(x, y)` on it. +* +* If the `key` and optionally the `frame` arguments are given, it calls `child.loadTexture(key, frame)` on it. +* +* The two operations are separate. For example if you just wish to load a new texture then pass `null` as the x and y values. +* +* @method Phaser.Group#resetChild +* @param {DisplayObject} child - The child to reset and/or load the texture on. +* @param {number} [x] - The x coordinate to reset the child to. The value is in relation to the group.x point. +* @param {number} [y] - The y coordinate to reset the child to. The value is in relation to the group.y point. +* @param {string|Phaser.RenderTexture|Phaser.BitmapData|Phaser.Video|PIXI.Texture} [key] - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache Image entry, or an instance of a RenderTexture, BitmapData, Video or PIXI.Texture. +* @param {string|number} [frame] - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index. +* @return {DisplayObject} The child that was reset: usually a {@link Phaser.Sprite}. +*/ +Phaser.Group.prototype.resetChild = function (child, x, y, key, frame) { + + if (child === null) + { + return null; + } + + if (x === undefined) { x = null; } + if (y === undefined) { y = null; } + + if (x !== null && y !== null) + { + child.reset(x, y); + } + + if (key !== undefined) + { + child.loadTexture(key, frame); + } + + return child; }; diff --git a/typescript/phaser.d.ts b/typescript/phaser.d.ts index 3de9d1347..08ef7f175 100644 --- a/typescript/phaser.d.ts +++ b/typescript/phaser.d.ts @@ -1,7 +1,7 @@ /// /// -// Type definitions for Phaser 2.4.4+ 2015-Aug-25 +// Type definitions for Phaser 2.4.4+ 2015-Aug-28 // Project: https://github.com/photonstorm/phaser declare class Phaser { @@ -1641,7 +1641,7 @@ declare module Phaser { checkProperty(child: any, key: string[], value: any, force?: boolean): boolean; countDead(): number; countLiving(): number; - create(x: number, y: number, key: string, frame?: any, exists?: boolean): any; + create(x: number, y: number, key?: string | Phaser.RenderTexture | Phaser.BitmapData | Phaser.Video | PIXI.Texture, frame?: string | number, exists?: boolean): any; createMultiple(quantity: number, key: string, frame?: any, exists?: boolean): void; customSort(sortHandler: Function, context?: any): void; destroy(destroyChildren?: boolean, soft?: boolean): void; @@ -1653,9 +1653,9 @@ declare module Phaser { filter(predicate: Function, checkExists?: boolean): ArraySet; getAt(index: number): PIXI.DisplayObject | number; getBottom(): any; - getFirstAlive(): any; - getFirstDead(): any; - getFirstExists(exists: boolean): any; + getFirstAlive(createIfNull?: boolean, x?: number, y?: number, key?: string | Phaser.RenderTexture | Phaser.BitmapData | Phaser.Video | PIXI.Texture, frame?: string | number): any; + getFirstDead(createIfNull?: boolean, x?: number, y?: number, key?: string | Phaser.RenderTexture | Phaser.BitmapData | Phaser.Video | PIXI.Texture, frame?: string | number): any; + getFirstExists(exists: boolean, createIfNull?: boolean, x?: number, y?: number, key?: string | Phaser.RenderTexture | Phaser.BitmapData | Phaser.Video | PIXI.Texture, frame?: string | number): any; getIndex(child: any): number; getRandom(startIndex?: number, length?: number): any; getTop(): any; @@ -1674,6 +1674,7 @@ declare module Phaser { removeBetween(startIndex: number, endIndex?: number, destroy?: boolean, silent?: boolean): void; removeFromHash(child: PIXI.DisplayObject): boolean; replace(oldChild: any, newChild: any): any; + resetChild(child: any, x?: number, y?: number, key?: string | Phaser.RenderTexture | Phaser.BitmapData | Phaser.Video | PIXI.Texture, frame?: string | number): any; resetCursor(index?: number): any; reverse(): void; sendToBack(child: any): any;