3
\$\begingroup\$

I am building a Javascript/canvas platformer game, and it's coming along nicely. The only problem I've really run into where I can think of any solution at all is the animation of my player sprite.

The game loop is running every 16ms, which equates to 60fps. On every game loop, I'm using a method of my player class (called draw) to draw the player sprite. The sprite looks like this: https://i.sstatic.net/THlGX.png

On every call of the draw method, I am advancing the "frame" of the player sprite, to give the illusion that the player is moving. As far as I know, this is common practice. However, due to my draw method being run every 16ms with the game loop, my player sprite is animating extremely quickly, and it doesn't look realistic at all.

Is there a way to slow this down to a pre-defined speed, or will I have to resort to adding loads of duplicate frames to my player sprite? Obviously that's not a great solution, as to make it look realistic at a game speed of 60fps I'd need to have a LOT of frames.

Here's my relevant code:

// Sets off the main game loop
setInterval("gameLoop()", gameSpeed);

function gameLoop() {
    // Updates
    player.update();

    // Draw
    c.clearRect(0, 0, canvas.width, canvas.height);
    player.draw();
}

// Then in my player class...

this.draw = function() {
        if(this.state == "idle") {
            c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
            if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; }
        } else if(this.state == "running") {
            var height = 0;
            if(this.facing == "left") { height = 37; }
            c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, height, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight);
            if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; }
        }
    }
\$\endgroup\$

2 Answers 2

10
\$\begingroup\$

What I always do in this case is store a frameTime variable and store the last update time variable inside my animation class. Then I only update the frame if the currentTime - lastUpdateTime > frameTime, in which case I also set last update time to currentTime.

Huzzah for animation =]

\$\endgroup\$
1
  • 1
    \$\begingroup\$ @Andy, I do the same thing as ultifinitus, Except that do lastUpdateTime = lastUpdateTime + frametime so as to not lose time. If you simply set the lastUpdateTime = currentTime, your animation's speed will vary just a little bit. Probably not noticeable in most cases, but if you need to predict exactly when a long animation will end, you don't want to lose time. \$\endgroup\$ Commented Oct 28, 2011 at 14:15
-1
\$\begingroup\$

I'd try to use a new timer for the player, just a timeout for the next animation and in case of bad things the gameloop can clear this timer and reset the player.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .