James Dawson
James Dawson

Reputation: 5409

Animating sprite frames in canvas

I'm making a small platform game with the canvas element and I'm having trouble working out the best way to use sprites.

Canvas doesn't support animated GIFs, so I can't do that, so instead I made a film strip for my animated sprites to give the illusion that a character is moving. Like this: https://i.sstatic.net/FUuHg.png

Here's the relevant code:

function player() {

    this.idleSprite = new Image();
    this.idleSprite.src = "/game/images/idleSprite.png";
    this.idleSprite.frameWidth = 28;
    this.idleSprite.frameHeight = 40;
    this.idleSprite.frameCount = 12;

    this.runningSprite = new Image();
    this.runningSprite.src = "/game/images/runningSprite.png";
    this.runningSprite.frameWidth = 34;

    this.update = function() {

    }

    var frameCount = 1;
    this.draw = function() {
        c.drawImage(this.idleSprite, this.idleSprite.frameWidth * frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, 0, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
        if(frameCount < this.idleSprite.frameCount - 1) { frameCount++; } else { frameCount = 0; }
    }
}

var player = new player();

As you can see, I'm defining the idle sprite and also its frame width and frame count. Then in my draw method, I'm using those properties to tell the drawImage method what frame to draw. Everything works fine, but I'm unhappy with the frameCount variable defined before the draw method. It seems... hacky and ugly. Would there be a way that people know of to achieve the same effect without keeping track of the frames outside the draw method? Or even a better alternative to drawing animated sprites to canvas would be good.

Thanks.

Upvotes: 1

Views: 1802

Answers (1)

andrewmu
andrewmu

Reputation: 14534

You could select the frame depending on some fraction of the current time, e.g.

this.draw = function() {
    var fc = this.idleSprite.frameCount;
    var currentFrame = 0 | (((new Date()).getTime()) * (fc/1000)) % fc;
    c.drawImage(this.idleSprite, this.idleSprite.frameWidth * currentFrame, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, 0, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
}

That will give you animation with a period of one second (the 1000 is a millisecond value). Depending on your frame rate and animation this might look jerky, but it doesn't rely on persistent counters.

Upvotes: 1

Related Questions