qa_foo Posted September 12, 2016 Share Posted September 12, 2016 This is has been asked a few times on the forum but there never seems to be a clear answer. Looking at the 'update' code for group, it doesn't take 'exists' into consideration so update keeps getting called for all children. Having a non-existing entity 'spin' when it's not used is unnecessary and risky (performance, invalid state). How do people normally deal with it? Some options to avoid this could be to check 'exists' at the top of each update and return when it's false, or maybe it's possible to override Group and add this behaviour to update, or check for 'active/inactive' states in update. There must be a good reason it's been implemented this way but I'm not sure what it is. Thanks. Link to comment Share on other sites More sharing options...
ForgeableSum Posted September 12, 2016 Share Posted September 12, 2016 Use forEachExists for that: http://phaser.io/docs/2.4.4/Phaser.Group.html#forEachExists Link to comment Share on other sites More sharing options...
qa_foo Posted September 12, 2016 Author Share Posted September 12, 2016 I probably should explain what I'm doing. I've extended the sprite class and have overridden the update method, and then added it to the tree with exsits = false for pooling/re-use at create time. I could do a 'forEach' within the state.update() but the stage.update() will call all the update() methods in the tree (exists or not) after state.update(), unless I'm not understanding things correctly. Maybe extending Phaser.Sprite and overriding update() is not the done thing. Thanks for the help. Link to comment Share on other sites More sharing options...
nazimboudeffa Posted September 12, 2016 Share Posted September 12, 2016 does it mean to use the example above in the update and not in the create http://phaser.io/examples/v2/groups/add-a-sprite-to-group if so let me know if an pen on code pen in necessary to continue in this way or a jsfiddle (it works better with codepen i think) Link to comment Share on other sites More sharing options...
Tom Atom Posted September 12, 2016 Share Posted September 12, 2016 3 hours ago, qa_foo said: I probably should explain what I'm doing. I've extended the sprite class and have overridden the update method, and then added it to the tree with exsits = false for pooling/re-use at create time. I could do a 'forEach' within the state.update() but the stage.update() will call all the update() methods in the tree (exists or not) after state.update(), unless I'm not understanding things correctly. Maybe extending Phaser.Sprite and overriding update() is not the done thing. Thanks for the help. Extending sprite is perfectly OK. You are right, that update is called (as well as postUpdate). Only preUpdate is exited early if exists = false. For pooling you can completely remove child from scene tree (with remove methods) and store it in some ... pool. When needed, you can take it from pool and add (with any of add methods) into scene tree again. Below is my generic Pool class (in TypeScript) I use in my games. When constructing, pool is created with X items of type T - by default it can grow if no new items are in pool. Then take item from pool with item = createItem() and return it with destroyItem(item) namespace Utils { export class Pool<T> { private _classType: any; private _newFunction: Function = null; private _count: number = 0; private _pool: T[] = []; private _canGrow: boolean = true; private _maxPoolSize: number = 0; // ------------------------------------------------------------------------- constructor(aClassType: any, aCount: number, aNewFunction = null) { this._classType = aClassType; this._newFunction = aNewFunction; for (var i = 0; i < aCount; i++) { // create new item var item = this.newItem(); // store into stack of free items this._pool[this._count++] = item; } } // ------------------------------------------------------------------------- public createItem(): T { if (this._count === 0) { console.log("size = " + ++this._maxPoolSize); return this._canGrow ? this.newItem() : null; } else { return this._pool[--this._count]; } } // ------------------------------------------------------------------------- public destroyItem(aItem: T): void { this._pool[this._count++] = aItem; } // ------------------------------------------------------------------------- public set newFunction(aNewFunction: Function) { this._newFunction = aNewFunction; } // ------------------------------------------------------------------------- protected newItem(/* arg1: {new() : T}*/): T { if (this._newFunction !== null) { return this._newFunction(); } else { return new this._classType; } } // ------------------------------------------------------------------------- public set canGrow(aCanGrow: boolean) { this._canGrow = aCanGrow; } } } Link to comment Share on other sites More sharing options...
rich Posted September 12, 2016 Share Posted September 12, 2016 Just to explain: The reason 'update' is called, no matter what, is because the function is entirely empty, and does nothing. It's there for overriding by you, to do whatever you want it to do. So if you don't want it processed if the sprite doesn't exist, that check should be made at the start of the function. There are many cases where you may not require that though, so it's left up to you to decide. Link to comment Share on other sites More sharing options...
samme Posted September 13, 2016 Share Posted September 13, 2016 You can override Group::update: Phaser.Group.prototype.update = function() { var child, i; i = this.children.length; while (i--) { child = this.children[i]; if (child.exists) { child.update(); } } }; Link to comment Share on other sites More sharing options...
qa_foo Posted September 13, 2016 Author Share Posted September 13, 2016 Thanks for all the great replies, that's given me a few options and made sure I was on the right track. Link to comment Share on other sites More sharing options...
Recommended Posts