Oscar Abraham Posted June 11, 2013 Share Posted June 11, 2013 Hello, I've just found Pixi and I think it's a really good library. I'm writing a small open source html5 videogame library that wraps around Box2D.js. I've decided to use Pixi.js to do the rendering process. One of the problems that I've been having with the library is that the MovieClip constructor doesn't satisfy some of my needs, which are:Easily have multiple sprite sequences asociated with one SpriteBeing able to indicate a variable step of time to the Sprite, so that, if frame rate slows down, the speed of the sequence stays the same.Being able to indicate frameRate in a fps format, e.g. 24 frames per second.In that regard, it was important for me to use the frame that was queued to be drawn instead of round it to the nearest frame.So I wrote a constructor and called it AnimatedSprite, although maybe other name would be more indicated. It works more or less like MovieClip, it also extends Sprite. One passes it a sequences object, for which each property is an array of textures that represents a sequence. e.g.var sequences={ "run":[runtexture1, runtexture2, runtexture3, runtexture4], "jump":[jumptexture1, jumptexture2, jumptexture3], "idle":[idletexture1, idletexture2, idletexture3, idletexture4, idletexture5],}One can also optionally pass a frame rate and the first sequence that's going to be ready to play. If frameRate is not passed, it will default to 60fps. If firstSequence is not passed, it will try to pick one from the sequences object, since the Sprite on Pixi.js cannot be set without a texture. It has the same methods from MovieObject to play(), stop(), gotoAndPlay(), gotoAndStop(). If one passes to gotoAndPlay() or gotoAndStop() a string with the name of a sequence instead of a number, it will asign the sequence and go to the first frame of that sequence. e.g.myAnimatedSprite.gotoAndPlay("jump");It doesn't loop for default, to make it loop, one can set the property loop to true. There is, like on movieClip, a method called onComplete that you can define. It is called when a sequence is completed. It is passed the name of the sequence so that you can manage according to what sequence has ended. To make the sprite advance in time, you need to call the method advanceTime each time you draw the stage. To make it work properly, you need to pass it the time in seconds that has passed since the last time it was drawn. If no time is passed to advanceTime, it will default to 1/60 seconds, which is the most common case. This is the constructor I was talking about:PIXI.AnimatedSprite=function(sequences,frameRate,firstSequence){ this.sequences=sequences; if(firstSequence==undefined){ for(var key in sequences){ this.currentSequence=key; break; } } else{ this.currentSequence=firstSequence; } PIXI.Sprite.call(this,this.sequences[this.currentSequence][0]); this.anchor.x=this.anchor.y=.5; this.frameRate=frameRate||60; this.onComplete=null; this.currentFrame=0; this.previousFrame; this.playing=false; this.loop=false;}//animatedSpritePIXI.AnimatedSprite.constructor = PIXI.AnimatedSprite;PIXI.AnimatedSprite.prototype = Object.create(PIXI.Sprite.prototype);PIXI.AnimatedSprite.prototype.gotoAndPlay=function(where){ if(Object.prototype.toString.call(where)=='[object String]'){ this.currentFrame=0; this.currentSequence=where; } else{ this.currentFrame=where; } this.playing=true;}PIXI.AnimatedSprite.prototype.gotoAndStop=function(where){ if(Object.prototype.toString.call(where)=='[object String]'){ this.currentFrame=0; this.currentSequence=where; } else{ this.currentFrame=where; } this.setTexture(this.sequences[this.currentSequence][this.currentFrame]); this.playing=false;}PIXI.AnimatedSprite.prototype.play=function(){ this.playing=true;}PIXI.AnimatedSprite.prototype.stop=function(){ this.playing=false;}PIXI.AnimatedSprite.prototype.advanceTime=function(dt){ if(typeof dt=="undefined"){ dt=1/60; } if(this.playing){ this.currentFrame+=this.frameRate*dt; var constrainedFrame=Math.floor(Math.min(this.currentFrame, this.sequences[this.currentSequence].length-1)); this.setTexture(this.sequences[this.currentSequence][constrainedFrame]); if(this.currentFrame>=this.sequences[this.currentSequence].length){ if(this.loop){ this.gotoAndPlay(0); } else{ this.stop(); } if(this.onComplete){ this.onComplete(this.currentSequence); } } }} If you don't want to call the method advanceTime and you don't care about maintaining constant animation speed when the frameRate of the whole stage varies, I guess adding something like this would work:PIXI.AnimatedSprite.prototype.updateTransform = function(){ PIXI.Sprite.prototype.updateTransform.call(this); this.advanceTime();}I decided to share this here because I believe this could be used for more things than game developing, so I'd be glad if this is useful to anybody. I haven't found any bugs yet, but I haven't had the time to do proper debugging. So if anyone uses this, could you help me? Also, maybe later I'll add a method to queue sequences easily. Quote Link to comment Share on other sites More sharing options...
xerver Posted June 11, 2013 Share Posted June 11, 2013 I use a display object with multiple MovieClips inside, as you set the active animation I change the `visible` property of the corresponding MovieClip. Works great. Quote Link to comment Share on other sites More sharing options...
Oscar Abraham Posted June 11, 2013 Author Share Posted June 11, 2013 I saw that. It seems nice enough, but, like you said, you have to have multiple sprites for one animation, so, for example, its a little harder to queue them in perfect order and it's not as efficient. Quote Link to comment Share on other sites More sharing options...
Mat Groves Posted June 11, 2013 Share Posted June 11, 2013 This is great! I love your Advanced MovieClip! Quote Link to comment Share on other sites More sharing options...
Oscar Abraham Posted June 11, 2013 Author Share Posted June 11, 2013 Advanced MovieClip, that sounds so good! I'm honored. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.