Animation Class

This was the first class I made which evolved a fair bit through the development. I also used it early on to try to get a rough idea of how much I could draw in a canvas at once before the frame rate started to die! The objective was simple- the contructor would require only the bare minimum of informaiton;

  • A pre-loaded image object containing the frames laid out horizontally
  • Parameter indicating total frame count
  • Boolean to indicate if the animation should be looped
  • Boolean for playing the animation in reverse
  • Boolean for physically flipping the rendered images
  • How fast to play the animation (Frames Per Second)

It required only a couple of methods;

  • Draw next frame in the sequence
  • Draw a specific frame

When you setup each animation object it works out how wide each frame is based on image total width/ frame count and stores it ready for use. Once the animation is setup, to draw you pass it the current context it should be drawing to, the location to draw to, and the current game time value passed from the main game loop so it can decide wether it should be on the next frame yet or not.

/* for a sequence of animation frames in a sprite sheet */
function Animation(img, FrameCount, Loop, FPS, Reversed) {

	// http://www.slideshare.net/kliehm/standardsnext-canvas-1651377

	this.FPS = FPS;
	this.CurrentFrame = 0;
	this.FrameCount = FrameCount;
	this.Loop = Loop;
	this.FlipX = false;
	this.Reversed = Reversed || false;

	this.TimeBetweenFrames = 0;
	this.TimeSinceLastFrame = 0;
	this.Image = img;

	/* internal calcs */
	if (this.FrameCount > 0)
		this.GridW = this.Image.width / this.FrameCount;
	else
		this.GridW = this.Image.width;
		
	if (Reversed) // if we're going backwards, start at the end..
		this.CurrentFrame = this.FrameCount - 1;
		
	this.GridH = this.Image.height;
	this.TimeBetweenFrames = 1 / FPS;
	this.TimeSinceLastFrame = this.TimeBetweenFrames;


}
Animation.prototype.DrawFrame = function (context, x, y, gameTime, frameNumber) {
	context.save();
	context.translate(x, y);

	if (this.FlipX) {
		context.save();
		context.scale(-1, 1);
		context.translate(-this.GridW, 0);
	}

	// https://developer.mozilla.org/en/Canvas_tutorial/Using_Images
	context.drawImage(this.Image, this.GridW * frameNumber, 0, this.GridW, this.GridH, 0, 0, this.GridW, this.GridH);

	if (this.FlipX) {
		context.restore();
	}

	context.restore();
}
Animation.prototype.DrawNextFrame = function (context, x, y, gameTime) {

	this.DrawFrame(context, x, y, gameTime, this.CurrentFrame);

	this.TimeSinceLastFrame -= gameTime;

	if (this.FrameCount > 0) {
		if (this.TimeSinceLastFrame <= 0) {
			this.TimeSinceLastFrame = this.TimeBetweenFrames;

			if (this.Loop || (!this.Reversed &amp;&amp; this.CurrentFrame + 1 != this.FrameCount) || (this.Reversed &amp;&amp; this.CurrentFrame > 0)) {
				if (this.Reversed) {
					this.CurrentFrame--;
					if (this.CurrentFrame == 0)
						if (this.Loop)
							this.CurrentFrame = this.FrameCount - 1;
						else
							return false; // end of sequence

				}
				else {
					this.CurrentFrame++;
					if (this.CurrentFrame == this.FrameCount)
						if (this.Loop)
							this.CurrentFrame = 0;
						else
							return false; // end of sequence
				}
			}

		}
	}

	return true; // indicates more to come...
};

And a Demo;

  1. No comments yet.
(will not be published)