Question

I have a pong game that I made 6 months ago when I was much worse at programming. The only thing is it flickers like CRAZY, which ruins it for me.

Here is some code which is involved in the drawing and clearing of the canvas, so may be behind the flickering:

canvas: document.getElementById( "canvas" ),
    // Get our 2D context for drawing
    ctx: canvas.getContext( "2d" ),
    // Frames-per-second
    FPS: 30,

draw: function() {
        if (preGameContent.isStartScreen === false && endOfGame.isEndOfGame === false) {
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            this.Banana1.draw();
            this.Banana2.draw();
            this.Banana3.draw();
            this.displayScore();
            this.player1Paddle.draw();
            this.player2Paddle.draw();
            this.ball.draw();
        }
    }

update: function() {
        if (preGameContent.isStartScreen === false && endOfGame.isEndOfGame === false) {
            this.player1Paddle.updatePaddle();
            this.player2Paddle.updatePaddle();
            this.ball.updateBall();
            if (this.ball.x < 0) {
                if (this.is2PlayerGame === true) {
                    this.pointScored.startNextSet("player2");
                    this.setUp("right");
                }
                else {
                    this.pointScored.startNextSet("computer");
                    this.setUp("right");
                }
            }
            if (this.ball.x + this.ball.width > this.canvas.width) {
                gameController.pointScored.startNextSet("player1");
                this.setUp("left");
            }
        }
    }

tick: function() {
        if (preGameContent.isStartScreen === false
            && endOfGame.isEndOfGame === false) {
            gameController.draw();
            gameController.update();
        }
    }

setInterval( gameController.tick, 1000 / gameController.FPS );

Do you see anything that can be done to this to reduce flicker? Thanks.

EDIT

Check out how i was redrawing each image every interval by creating a NEW image in its draw method:

//This class is to construct anything with an image
//vx and vy are for the velocity along the x and y axis
function Item(xStartPos, yStartPos, vx, vy, width, height, imgSrc) {
    this.x = xStartPos;
    this.y = yStartPos;
    this.vx = vx;
    this.vy = vy;
    this.width = width;
    this.height = height;
    this.imgSrc = imgSrc;
    //this function draws the image to the canvas
    this.draw = function() { 
        var self = this;
        var img = new Image();  
        img.src = self.imgSrc;  
        img.onload = function(){
            gameController.ctx.drawImage(img, self.x, self.y);  
        };
    };
    //this function updates the position of the object on the canvas
    this.update = function() {
        // Divide velocity by gameController.FPS before adding it
        // onto the position.
        this.x += this.vx / gameController.FPS;
        this.y += this.vy / gameController.FPS;
         // wall collision detection
         //stop the object from going through the top and bottom walls,
         //but not the side walls, so the ball can go through them
        if ( (this.y) < 0 ) {
            this.y = 0;
        }
        if ( (this.y + this.height) > gameController.canvas.height) {
            this.y = gameController.canvas.height - this.height;
        }
    };
};

EDIT So i did this:

function Item(xStartPos, yStartPos, vx, vy, width, height, imgSrc) {

    this.x = xStartPos;
    this.y = yStartPos;
    this.vx = vx;
    this.vy = vy;
    this.width = width;
    this.height = height;
    this.img = new Image();
    this.imgSrc = imgSrc;
    this.img.src = imgSrc;
    //this.loaded = false;
    //img.onload = function() { this.loaded = true; }
    //this function draws the image to the canvas
    this.draw = function() { 
        //if (this.loaded) 
           gameController.ctx.drawImage(this.img, this.x, this.y);  
    };

Which makes it draw all items nicely except the paddles and ball which do not draw at all

Was it helpful?

Solution

It is hard to say where exactly it flickers without looking at the whole solution, but I would blame setInterval(). The way to go is to use requestAnimationFrame technique described here: http://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/ I was able to achieve very smooth animations by using this code template:

 window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
          window.setTimeout(callback, 1000 / 60);
        };
      })();

      function animate() {
        var canvas = document.getElementById('myCanvas');
        var context = canvas.getContext('2d');

        // update

        // clear
        context.clearRect(0, 0, canvas.width, canvas.height);

        // draw stuff

        // request new frame
        requestAnimFrame(function() {
          animate();
        });
      }
      animate();

In general, setInterval() is fairly bad, use setTimeout() after each re-draw, since interval might come at the worst timing possible.

Note, depending on required browser versions support, you might want to drop setTimeout alltogether, as requestAnimationFrame is universally supported by now.

Update A simple fix for the image loading without using extra tools within the code would be this, although it might run some animation cycles until all images will be loaded:

function Item(.. imgSrc) {
   ...
    this.img = new Image();
    this.imgSrc = imgSrc;
    var self = this;
    this.loaded = false;
    img.onload = function() { self.loaded = true; }

    //this function draws the image to the canvas
    this.draw = function() { 
        if (this.loaded) 
           gameController.ctx.drawImage(this.img, this.x, this.y);  
    };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top