redrawing canvas html5 without flickering

Juliano Lima picture Juliano Lima · Aug 25, 2013 · Viewed 12.4k times · Source

I've a screen being redraw every 25ms, and images are flickering, here is my code

                var FRAME_RATE = 40;
                var intervalTime = 1000/FRAME_RATE;
                gameLoop();

                function gameLoop(){
                    context.clearRect(0, 0, 640, 640);
                    renderMap();
                    window.setTimeout(gameLoop, intervalTime);  
                }

and here is renderMap() function

function renderMap(){
                    var startX = playerX - (screenW / 2);
                    var startY = playerY - (screenH / 2);

                    maxX = playerX + (screenW / 2);
                    maxY = playerY + (screenH / 2);
                    $.getJSON('mapa3.json', function(json){
                        for (x = startX; x < maxX; x=x+32){ 
                            for (y = startY; y < maxY; y=y+32){
                                intTile = json.layers[0].data[((y/32)* 100) + (x/32)];
                                context.putImageData(getTile(intTile - 1), x - startX, y - startY);
                            }
                        } 
                    });

                    var imgCharacter = new Image();
                    imgCharacter.src = 'char.png';

                    var posX = (screenW - imgCharacter.width) / 2;
                    var posY = (screenH - imgCharacter.height) / 2;
                    imgCharacter.onload = function(){context.drawImage(imgCharacter, posX, posY)}       
                }

What changes do I need to make to the code to stop flickering?

Answer

Zach Saucier picture Zach Saucier · Aug 25, 2013

I believe it is because you are loading the image each iteration. Try putting the var imgCharacter..., the following line, and the image's onload function outside of renderMap so it is only ran once

var imgCharacter = new Image();    
imgCharacter.onload = function () {
    renderMap();
}
imgCharacter.src = 'char.png';

function renderMap() {
    var startX = playerX - (screenW / 2);
    var startY = playerY - (screenH / 2);

    maxX = playerX + (screenW / 2);
    maxY = playerY + (screenH / 2);
    $.getJSON('mapa3.json', function (json) {
        for (x = startX; x < maxX; x = x + 32) {
            for (y = startY; y < maxY; y = y + 32) {
                intTile = json.layers[0].data[((y / 32) * 100) + (x / 32)];
                context.putImageData(getTile(intTile - 1), x - startX, y - startY);
            }
        }
    });

    var posX = (screenW - imgCharacter.width) / 2;
    var posY = (screenH - imgCharacter.height) / 2;

    context.drawImage(imgCharacter, posX, posY)
}

Thank you to markE for letting me know the onload function also needs to go outside renderMap, I overlooked it the first time