Kent Wood Posted December 10, 2016 Share Posted December 10, 2016 Hello everyone i was wonder is there a way to make the AnimationManager instance shareable. so that when i create a new instance of my sprite,i don't need to add animations once a Sprite instance create . //this is the current way class Player extends Phaser.Sprite { contractor(game) { super(game,0,0,'player'); this.animations.add('walk',[0,1,2,3]); this.animations.add('run',[4,5,6,7]); } } that's a waste of memory,and if i create a lot sprite instances same time,a big JAM would happen so, i wanna this way var animationManager=new Phaser.AnimationManager(); //add animations animationManager.add('walk',[0,1,2,3]); animationManager.add('run',[4,5,6,7]); //then i create 2 players var playerA=new Player(game) playerA.animations=animationManager; var playerB=new Player(game) playerB.animations=animationManager; //////////////even thought that animationManger instance shoud be a static variable and declare inside of the Player class/////////////// class Player extends Phaser.Sprite { static animationManager; contractor(game) { super(game,0,0,'player'); if(Player.animationManager==null) { //register animations here } this.animations=Player.animationManager; } } Link to comment Share on other sites More sharing options...
drhayes Posted December 12, 2016 Share Posted December 12, 2016 Did you run the profiler to see if this was a problem? How many sprites are you creating that you saw the problem? How many animations do these sprites have? The reason I ask is because unless you have (I'd guess) tens of thousands of sprites, each with many animations, the amount of memory taken by each one having their own AnimationManager instance is probably smaller than one of the image files you'll use to draw those sprites. Unless you've measured otherwise, I don't think you need to worry about this. Link to comment Share on other sites More sharing options...
Kent Wood Posted December 15, 2016 Author Share Posted December 15, 2016 suppose i have a star spritesheet (like the attachment show. also inclde the frames jsonarray) i import it and create a animation dictionary from these code //in main.ts //load sprite sheet and jsonarray this.game.load.atlasJSONArray('star','./assets/stars.png',null,'./assets/stars.json') //in Star.ts //just record all the frame data in a static variable //that is a table, which has each color as the key,and the frame as that color's animation frames if(Star.starsFramesAni==null) { var starsFrameData:Phaser.FrameData=this.game.cache.getFrameData('star'); var starsFramesAni:any={}; starsFrameData.getFrames().forEach((value,index)=>{ var key=value.name.match(/(.+?)0\d+/)[1]; if(starsFramesAni[key]==null) starsFramesAni[key]=[]; else starsFramesAni[key].push(index); }) Star.starsFramesAni=starsFramesAni; } //for each star instance,i should find thouth that animation table,and add the frames to this star instance var self=this; Object.keys(Star.starsFramesAni).forEach(key=>{ self.animations.add(key,Star.starsFramesAni[key]); }) //so that,at last,i can play this specific color's animation this.animations.play(color,5,true); if it is only star,program can handle that,even though it is still a little jam. but when i try to make the star be a particle, like a star explosion effect.the program is totally crashed, just because i have to add anmations again in each star particle instance that's why i think the animation should be shared or just seprated from the sprite. define somewhere,sprite just reference to the animations instance,and use it. no need to add it in each sprite constrator stars.json Link to comment Share on other sites More sharing options...
drhayes Posted December 15, 2016 Share Posted December 15, 2016 When you say "totally crashed", what do you mean? Are you seeing an error in the console? Is the game starting to run really slowly? Without running a profiler or seeing an error message we're guessing as to what went wrong. Link to comment Share on other sites More sharing options...
samme Posted December 15, 2016 Share Posted December 15, 2016 @Kent Wood can you post a working example? There may be ways to share an AnimationManager instance, but you'd be sharing everything: all the sprites would play or stop the same sequence simultaneously. It doesn't sound like that's what you want. Whether for Sprites or Particles, you need to add animations only once per object, probably during the create phase. Link to comment Share on other sites More sharing options...
Kent Wood Posted December 16, 2016 Author Share Posted December 16, 2016 thanks guys,at last i found the problem is i run "makeParticles" too frequently and incorrect, particles are born more and more, made a memory leak. the effect i want make is i need my star has an explosion when it get touched, and the star has its own color, there is no way to change the particle instance to play definely animation, so i just make it once one color star reached and do it again when get another color star. at last, i write a custom emitter extends from Phaser.Particles.Arcade.Emitter,and also,i modified Phaser.Particles.Arcade.Emitter,and add 2 methods -- beforeParticleEmit and afterParticleEmit, when one star particle emmited, i just change its color at first. coz used the exisit particle, no memory wasted my code like this ExpandEmitter.js /** * override emitParticle,add 2 methods,beforeParticleEmit and afterParticleEmit */ Phaser.Particles.Arcade.Emitter.prototype.emitParticle = function (x, y, key, frame) { if (x === undefined) { x = null; } if (y === undefined) { y = null; } var particle = this.getFirstExists(false); if (particle === null) { return false; } var rnd = this.game.rnd; if (key !== undefined && frame !== undefined) { particle.loadTexture(key, frame); } else if (key !== undefined) { particle.loadTexture(key); } var emitX = this.emitX; var emitY = this.emitY; if (x !== null) { emitX = x; } else if (this.width > 1) { emitX = rnd.between(this.left, this.right); } if (y !== null) { emitY = y; } else if (this.height > 1) { emitY = rnd.between(this.top, this.bottom); } particle.reset(emitX, emitY); particle.angle = 0; particle.lifespan = this.lifespan; if (this.particleBringToTop) { this.bringToTop(particle); } else if (this.particleSendToBack) { this.sendToBack(particle); } if (this.autoScale) { particle.setScaleData(this.scaleData); } else if (this.minParticleScale !== 1 || this.maxParticleScale !== 1) { particle.scale.set(rnd.realInRange(this.minParticleScale, this.maxParticleScale)); } else if ((this._minParticleScale.x !== this._maxParticleScale.x) || (this._minParticleScale.y !== this._maxParticleScale.y)) { particle.scale.set(rnd.realInRange(this._minParticleScale.x, this._maxParticleScale.x), rnd.realInRange(this._minParticleScale.y, this._maxParticleScale.y)); } if (frame === undefined) { if (Array.isArray(this._frames)) { particle.frame = this.game.rnd.pick(this._frames); } else { particle.frame = this._frames; } } if (this.autoAlpha) { particle.setAlphaData(this.alphaData); } else { particle.alpha = rnd.realInRange(this.minParticleAlpha, this.maxParticleAlpha); } particle.blendMode = this.blendMode; var body = particle.body; body.updateBounds(); body.bounce.copyFrom(this.bounce); body.drag.copyFrom(this.particleDrag); body.velocity.x = rnd.between(this.minParticleSpeed.x, this.maxParticleSpeed.x); body.velocity.y = rnd.between(this.minParticleSpeed.y, this.maxParticleSpeed.y); body.angularVelocity = rnd.between(this.minRotation, this.maxRotation); body.gravity.y = this.gravity; body.angularDrag = this.angularDrag; //add this line,for child Emitter class to override this.beforeParticleEmit(particle); particle.onEmit(); //add this line,for child Emitter class to override this.afterParticleEmit(particle); return true; }; //add these 2 methods Phaser.Particles.Arcade.Emitter.prototype.beforeParticleEmit=function(particle) { } Phaser.Particles.Arcade.Emitter.prototype.afterParticleEmit=function(particle) { } (i strongly recommend to add these 2 methods in the offcial code) Star.ts class StarEmitter extends Phaser.Particles.Arcade.Emitter { currentColor = 'blue'; //override start method,support color change start(explode?, lifespan?, frequency?, quantity?, forceQuantity?, color?) { if (color != undefined) { this.currentColor = color; } return super.start(explode, lifespan, frequency, quantity, forceQuantity); }; beforeParticleEmit(particle) { //just add these lines,in order to call changeColor for normal StarParticle. (no need to do with RandomStarParticle instances) if (particle instanceof StarParticle) { if (!(particle instanceof RandomStarParticle)) { particle.changeColor(this.currentColor); } } } } export class StarParticle extends Phaser.Particle { constructor(game: Phaser.Game, x: number, y: number, key?: any, frame?: any) { super(game, x, y, 'star'); this.anchor = new Phaser.Point(0.5, 0.5); var self = this; Star.colors.forEach(key => { self.animations.add(key, Star.starsFramesAni[key]); }) this.visible = false; } changeColor(color) { this.animations.play(color, 5, true); this.visible = true; } } export class RandomStarParticle extends StarParticle { constructor(game: Phaser.Game, x: number, y: number, key?: any, frame?: any) { super(game, x, y); this.changeColor(Star.colors[game.rnd.integerInRange(0, 7)]); } } export class Star extends Phaser.Sprite { static starsFramesAni: any; static colors: any = ['blue', 'cyan', 'green', 'orange', 'purple', 'red', 'yellow']; static getColorIndex(color) { return Star.colors.indexOf(color); } color: string; constructor(game: any, x?: number, y?: number, color?: string) { super(game, x, y, 'star'); if (color == null) color = Star.colors[this.game.rnd.integerInRange(0, 7)]; this.anchor = new Phaser.Point(0.5, 0.5); this.color = color; //do some staff like "Phaser.Animation.generateFrameNames(key,0,7,'',4)", but cached the frames in a static variable if (Star.starsFramesAni == null) { var starsFrameData: Phaser.FrameData = this.game.cache.getFrameData('star'); var starsFramesAni: any = {}; starsFrameData.getFrames().forEach((value, index) => { var key = value.name.match(/(.+?)0\d+/)[1]; if (starsFramesAni[key] == null) starsFramesAni[key] = []; else starsFramesAni[key].push(index); }) Star.starsFramesAni = starsFramesAni; } //add animations for each star instance, ofcourse, load frames from the cache above var self = this; Star.colors.forEach(key => { self.animations.add(key, Star.starsFramesAni[key]); }) this.animations.play(color, 5, true); //define one only particle emitter, for star explosion, there are many stars,but just one emitter,if some star need a explosion,just move the emitter location to that star if (Star.exploEmitter == null) { Star.exploEmitter = new StarEmitter(this.game, 0, 0, 400); this.game.add.existing(Star.exploEmitter); //use the custome particle class Star.exploEmitter.particleClass = StarParticle; //make particle instance inside the emitter Star.exploEmitter.makeParticles(); Star.exploEmitter.setAlpha(1, 0.1, 2000, Phaser.Easing.Cubic.In); Star.exploEmitter.setScale(1, 0, 1, 0, 1000, Phaser.Easing.Cubic.In); Star.exploEmitter.gravity = 500; } } static exploEmitter: StarEmitter; explosion() { Star.exploEmitter.x = this.body.x; Star.exploEmitter.y = this.body.y; //make an explosion,and set a color,'coz i just override the start method Star.exploEmitter.start(true, 2000, null, 10, true, this.color); this.destroy(); } update() { if ((this.y - 300) > this.game.camera.view.bottom) { this.destroy(); } } } and check the demo effect http://d2z4fez41b07b4.cloudfront.net/game/index.html samme and drhayes 2 Link to comment Share on other sites More sharing options...
samme Posted December 16, 2016 Share Posted December 16, 2016 I LOVE THE CAT drhayes 1 Link to comment Share on other sites More sharing options...
Recommended Posts