Canvas increasing the animation speed with each change of animation

Asked

Viewed 188 times

2

I’m animating some sprites from LPC on a canvas, using Javascript. However, every time I change animation, the animation starts to get faster. The test can be done in the code below. Just press any key for it to run the attack animation, and see it happen.

Honestly, I couldn’t figure out the problem, I tried to reset all the objects by switching the animation, but the error persists

var battleField;
var entities = [];

$(document).ready(function (){
	battleField = document.getElementById("duel");
	//duel.width = 64;
	//duel.height = 64;
	
	// Create sprite sheet
	var mySprite = new Image();	
	mySprite.height = 64;
	// Create sprite
	var me = {
		state : 0,
		defaultAnim : function (){},
		render : function (){
			if(this.state === 0){
				this.defaultAnim.render();
			}
		},
		update : function (){
			if(this.state === 0){
				this.defaultAnim.update();
			}
		}
	};
	me.defaultAnim = sprite({
		context: battleField.getContext("2d"),
		width: 128,
		height: 64,
		image: mySprite,
		numberOfFrames: 2,
		ticksPerFrame: 30,
		loop: true
	});
	
	// Load sprite sheet
	mySprite.addEventListener("load", gameLoop);
	mySprite.src = "https://image.ibb.co/jmgXCb/male_white_idle.png";
	entities.push(me);
});

function sprite (options, reset) {
	var mySprite = new Image();	
	mySprite.height = 64;
	var that = {},
		frameIndex = 0,
		tickCount = 0,
		ticksPerFrame = options.ticksPerFrame || 0,
		numberOfFrames = options.numberOfFrames || 1;
	
	that.context = options.context;
	that.width = options.width;
	that.height = options.height;
	that.image = options.image;
	that.loop = options.loop;
	
	that.update = function () {
      tickCount += 1;
      if (tickCount > ticksPerFrame) {
			  tickCount = 0;
        if (frameIndex < numberOfFrames - 1) {	
          frameIndex += 1;
        } else if(that.loop) {
          frameIndex = 0;
        } else {
				  that.onAnimationEnded();
			  }
   }
};
	
	that.render = function () {
	
	  // Clear the canvas
	  that.context.clearRect(0, 0, that.width, that.height);
	  
	  // Draw the animation
	  that.context.drawImage(
	    that.image,
	    frameIndex * that.width / numberOfFrames,
	    0,
	    that.width / numberOfFrames,
	    that.height,
	    0,
	    0,
	    that.width / numberOfFrames,
	    that.height);
	};
	
	that.onAnimationEnded = function (){
		
	}
	
	return that;
}

function gameLoop () {
	
  window.requestAnimationFrame(gameLoop);
  for(let i = 0; i < entities.length; i++){
	  var e = entities[i];
	  e.render();
	  e.update();
  }
}

document.onkeydown = function (){
	var mySprite = new Image();	
	mySprite.height = 64;
	entities[0] = sprite({
		context: battleField.getContext("2d"),
		width: 260,
		height: 64,
		image: mySprite,
		numberOfFrames: 4,
		ticksPerFrame: 12	
	}, true);
	mySprite.addEventListener("load", gameLoop);
	mySprite.src = "https://image.ibb.co/eXq3JG/male_white_cast.png";
	entities[0].onAnimationEnded = function (){
		goToIdle(0);
	}
}

function goToIdle(entityIndex){
	var mySprite = new Image();	
	mySprite.height = 64;
	mySprite.src = "https://image.ibb.co/jmgXCb/male_white_idle.png";
	// Create sprite
	entities[entityIndex] = sprite({
		context: battleField.getContext("2d"),
		width: 128,
		height: 64,
		image: mySprite,
		numberOfFrames: 2,
		ticksPerFrame: 30,
    loop: true
	});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="duel"></canvas>

1 answer

1


You don’t need the line mySprite.addEventListener("load", gameLoop); in the onkeydown.

Your gameLoop is already constantly scheduling the next run. If this function is invoked again, you end up having two (or more) loops happening in "parallel", which causes this effect of animation acceleration.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.