user3628468
user3628468

Reputation: 121

Why does my Javascript animation slowdown after a while

So I am in the process of making this rhythm game with canvas, all that it does up to this point is render the receivers (the point the blocks are going to collide with so the user can press the corresponding buttons and get points) and it renders the dancer animation. For some reason though after the page is open for a while the dancer slows down significantly and continues to gradually slow.

I can't figure out why or how to fix it. Anyone have any ideas?

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);

var spritesheet = null; 


var dancer = {


    time:0,
    speed:0,
    image:null,
    x:0,
    y:0,
    currentFrame:0,
    width:50,
    height:100,
    ready:false 

}

function onload() {

    spritesheet = new Image(); 
    spritesheet.src = "danceSheet.png"; 
    spritesheet.onload = initiate; 


}

function initiate() {

    game.startTime = new Date().getTime() / 1000; 
    dancer.x = (canvas.width / 2) - dancer.width; 
    dancer.y =  120;
    game.initiateReceivers(); 

    main(); 

}

var game = {

    startTime:0,
    currentTime:0,
    receivers:[],
    senders:[],
    lanes:[],
    drawDancer: function() {

        ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0,                                                dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height ); 

},
clearWindow: function() {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

},
initiateReceivers: function() {
    var distanceRate = canvas.width / 4;
    var position = 30; 
    for(initiates = 0; initiates < 4; initiates++) {

        this.receivers[initiates] = new receivers;
        this.receivers[initiates].x = position; 
        this.receivers[initiates].y = 300; 
        position += distanceRate; 

    }

}

}

var gameUpdates = {

    updateMovement: function() {

    game.currentTime = new Date().getTime() / 1000; 
    dancer.time = game.currentTime - game.startTime;

    if(dancer.time >= 0.1) {

        game.startTime = new Date().getTime() / 1000; 
        dancer.currentFrame += 1; 
        if(dancer.currentFrame == 12) dancer.currentFrame = 0; 


        }

    },

collision: function(shapeA, shapeB) {


    // get the vectors to check against
    var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
        vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
        // add the half widths and half heights of the objects
        hWidths = (shapeA.width / 2) + (shapeB.width / 2),
        hHeights = (shapeA.height / 2) + (shapeB.height / 2); 

    // if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
    if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {                  

        return true; 

    }
        return false; 


}

}

function receivers() {

    this.x = 0;
    this.y = 0; 
    this.width = 60;
    this.height = 10; 

}

function senders() {

    this.x = 0;
    this.y = 0; 
    this.width = 60;
    this.height = 10; 
    this.lane = 0;
    this.status = true; 

}

function update() {

    gameUpdates.updateMovement();

}

function render() {

game.clearWindow();
game.drawDancer();

game.receivers.forEach( function(receiver) {
    ctx.rect(receiver.x,receiver.y,receiver.width,receiver.height);
    ctx.fillStyle = "red";
    ctx.fill(); 
    }
)
}

function main() {

update();
render(); 
requestAnimationFrame(main);

}

Upvotes: 3

Views: 357

Answers (1)

wolfhammer
wolfhammer

Reputation: 2661

I'm trying to get an idea of the slowness you're seeing so I adjusted your code to get a frames-per-second. Haven't found the cause yet for the drop.

Update

I found that the frames were dropping from drawing the rectangles. I've altered the code to use fillRect put the fill style outside of the loop. This seems to have fixed the frame drop.

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);

var spritesheet = null;


var dancer = {


  time: 0,
  speed: 0,
  image: null,
  x: 0,
  y: 0,
  currentFrame: 0,
  width: 50,
  height: 100,
  ready: false

}

function onload() {
  
  spritesheet = document.createElement('canvas');
  spritesheet.width = (dancer.width * 12);
  spritesheet.height = dancer.height;
  var ctx = spritesheet.getContext('2d');
  ctx.font = "30px Arial";
  ctx.fillStyle = "black";
  ctx.strokeStyle = "red";
  for (var i = 0; i < 12; i++) {
    var x = (i * dancer.width) + 10;
    ctx.fillText(i,x,60);
    ctx.beginPath();
    ctx.rect(i*dancer.width,0,dancer.width,dancer.height);
    ctx.stroke();
  }
  initiate();
}

function initiate() {

  game.startTime = new Date().getTime() / 1000;
  dancer.x = (canvas.width / 2) - dancer.width;
  dancer.y = 120;
  game.initiateReceivers();

  main();

}

var game = {

  startTime: 0,
  currentTime: 0,
  receivers: [],
  senders: [],
  lanes: [],
  drawDancer: function() {

    ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0, dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height);
    //ctx.strokeStyle="red";
    //ctx.beginPath();
    //ctx.lineWidth = 3;
    //ctx.rect(dancer.x,dancer.y,dancer.width,dancer.height);
    //ctx.stroke();

  },
  clearWindow: function() {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

  },
  initiateReceivers: function() {
    var distanceRate = canvas.width / 4;
    var position = 30;
    for (initiates = 0; initiates < 4; initiates++) {

      this.receivers[initiates] = new receivers;
      this.receivers[initiates].x = position;
      this.receivers[initiates].y = 300;
      position += distanceRate;

    }

  }

};

var gameUpdates = {

  updateMovement: function() {

    game.currentTime = new Date().getTime() / 1000;
    dancer.time = game.currentTime - game.startTime;

    if (dancer.time >= 0.1) {

      game.startTime = new Date().getTime() / 1000;
      dancer.currentFrame += 1;
      if (dancer.currentFrame == 12) dancer.currentFrame = 0;


    }

  },

  collision: function(shapeA, shapeB) {


    // get the vectors to check against
    var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
      vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
      // add the half widths and half heights of the objects
      hWidths = (shapeA.width / 2) + (shapeB.width / 2),
      hHeights = (shapeA.height / 2) + (shapeB.height / 2);

    // if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
    if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {

      return true;

    }
    return false;


  }

}

function receivers() {

  this.x = 0;
  this.y = 0;
  this.width = 60;
  this.height = 10;

}

function senders() {

  this.x = 0;
  this.y = 0;
  this.width = 60;
  this.height = 10;
  this.lane = 0;
  this.status = true;

}

function update() {

  gameUpdates.updateMovement();

}

function render() {

  game.clearWindow();
  game.drawDancer();
  ctx.fillStyle = "red";
  
  game.receivers.forEach(function(receiver) {
    ctx.fillRect(receiver.x, receiver.y, receiver.width, receiver.height);
  });
  
  ctx.fillText(fps,10,10);
}
var fps = 0;
var frames = 0;
function getFps() {
  fps = frames;
  frames = 0;
  setTimeout(getFps,1000);
}
getFps();

function main() {
  update();
  render();
  frames++;
  requestAnimationFrame(main);

}
onload();
canvas {
  border:1px solid blue;
}

Upvotes: 2

Related Questions