0
\$\begingroup\$

I'm creating a 2D platformer game with HTML5 canvas and javascript. I'm having a bit of a struggle with animations. Currently I animate by getting preloaded images from an array, and the code is really simple, in player.update() I call a function that does this:

var animLength = this.animations[id].length;
this.counter++;
this.counter %= 3;
if (this.counter == 2) this.spriteCounter++;
this.spriteCounter %= animLength;
return this.animations[id][this.spriteCounter];

There are a couple of problems with this one: When the player does 2 actions that require animating at the same time, animation speed doubles. Apparently this.counter++ is working twice at the same time. I imagine that if I start animating multiple sprites with this, the animation speed will multiply by the amount of sprites. Other issue is that I couldn't make the animation run only once instead of looping while key is held down.

Someone told me that I should create a function Animation(animation id, isLooped boolean) and the use something like player.sprite = new Animation("explode", false) but I don't know how to make it work.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

You may benefit from looking at my answer to another question on this site: Sprite Animation Best Practices. In that answer I link to a working animation system written in JavaScript.

In short, there is probably an easy way to solve this. Create an object that represents an Animation. This is usually just an ordered list of frames and durations.

Create a separate object to store the playback information, in other words, how "far" into an animation you have played. I recommend using a time-based animation scheme. This way, you can play an animation by advancing time and you should not run into problems with double speed.

\$\endgroup\$
2
\$\begingroup\$

The update of the anim should take as argument the current time or actual frame duration (timers are not so acurate, and requestAnimationFrame can trigger any time). You can compute the time with Date.now() or even better window.performance.now().
(For reasons too long to explain here, the really best solution is to have your own game time.)
Each frame should also be assigned a given time. Most simple way is to have the same duration for each frame, and have an array that allows you to repeat some frame to shape your animation as you want :

frameDuration = 10 ;  // in ms  
frameArray   = [ 0,0,1,2,3,3,2,3]; // array of index

obviously the best way is to have both a frameArray and a frameDurationArray :

frameArray   =         [ 0,1,2,3,2,3]   ; // array of index
frameDurationArray   = [ 20,10,20,10,10]; // array of durations

... but it requires a little more computation.

if you go for the first solution (same frame duration), the updateAnim should look like :

updateAnim = function ( time ) {
   var timeElapsed = Date.now()-this.startTime;
   var imgIndex = Math.floor(this.frameArray.length * timeElapsed / this.frameDuration );
   //... do some  %  if needed
   ...
}
\$\endgroup\$

You must log in to answer this question.

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