Canvas increasing the animation speed at each sprite exchange

2

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

I honestly could not figure out the problem, I tried to reset all objects by changing 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><canvasid="duel"></canvas>
    
asked by anonymous 06.11.2017 / 18:43

1 answer

1

You do not need the line mySprite.addEventListener("load", gameLoop); in onkeydown .

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

    
06.11.2017 / 23:02