Pawel
Pawel

Reputation: 555

html canvas animation flickering

I'm in the middle of creating this simple animation using HTML5 Canvas and JavaScript and I'm experiencing a problem with flickering objects. I was trying to find the solution on the internet before I asked this question and all I found was basically:

I think I've done that all and the flickering is still happening. (blue rectangles (obstacles) in my case.

The only solution that works is reducing the number of pixels in method responsible for moving the object, here:

obstacle.prototype.moveObstacle = function(){
 this.x -=3
}

but the the animation is too slow. Is there any way around it?

JSFiddle: https://jsfiddle.net/wojmjaq6/

Code:

var cnv = document.getElementById("gameField");
var ctx = cnv.getContext("2d");
var speedY = 1
var obst1 = new obstacle(cnv.width + 50);
var myBird = new bird(100, 1);

function bird(x, y) {
  this.x = x;
  this.y = y;
  this.gravity = 0.3
  this.gravitySpeed = 0
}

bird.prototype.drawbird = function() {
  ctx.fillStyle = "red"
  ctx.fillRect(this.x, this.y, 20, 20);
}

bird.prototype.animate = function() {
  this.gravitySpeed += this.gravity
  this.y += speedY + this.gravitySpeed
}

function obstacle(x) {
  this.x = x;
  this.y = 0;
  this.obstLen = Math.floor(Math.random() * 400)
}

obstacle.prototype.drawobstacle = function() {
  ctx.fillStyle = "blue";
  ctx.fillRect(this.x, this.y, 15, this.obstLen)
  ctx.fillRect(this.x, cnv.height, 15, -(cnv.height - this.obstLen - 100))
}

obstacle.prototype.moveObstacle = function() {
  this.x -= 3
}



function myFun() {
  ctx.clearRect(0, 0, cnv.width, cnv.height);
  myBird.animate();
  myBird.drawbird();
  obst1.moveObstacle();
  obst1.drawobstacle();

  if (obst1.x < 0) {
    obst1 = new obstacle(cnv.width + 50);
  }
  window.requestAnimationFrame(myFun)
};

function test() {

  if (myBird.gravity > 0) {
    myBird.gravity = -1
  } else {
    myBird.gravity = 0.3
  }
}


document.getElementById("gameField").onmousedown = test
document.getElementById("gameField").onmouseup = test

window.requestAnimationFrame(myFun)

Upvotes: 0

Views: 2208

Answers (1)

dougtesting.net
dougtesting.net

Reputation: 571

I do see some stuttering with the blue obstacle - the animation is not smooth.

Changing the x position of the obstacle based on the raw requestAnimationFrame loop will not necessarily result in a smooth operation as requestAnimationFrame just requests that the browser re-draws when it can.

The time between calls to requestAnimationFrame can vary depending on the power of the device the animation is on and how much there is to do each frame. There is no guarantee that requestAnimationFrame will give you 60 FPS.

The solutions are to decouple the changing of objects positions with the actual drawing of them, or factor it the elapsed time between frames and calculate the new position based on that to give a smooth animation.

Normally in my canvas animations I just use a library like GreenSock's Animation Platform (GSAP) https://greensock.com/get-started-js which can animate any numeric property over time, then I only have to write code for the drawing part.

It is possible to compute a time based animation in your own requestAnimationFrame, though there is a bit of complexity involved. This looks like a good tutorial on it http://www.javascriptkit.com/javatutors/requestanimationframe.shtml

Cheers, DouG

Upvotes: 3

Related Questions