Jump to content

Multiple Sequences Sprite constructor that might be useful to you


Oscar Abraham
 Share

Recommended Posts

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 Sprite
  • Being 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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...