Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redrawing canvas html5 without flickering

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?

like image 783
Juliano Lima Avatar asked Aug 24 '13 22:08

Juliano Lima


2 Answers

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

like image 177
Zach Saucier Avatar answered Sep 24 '22 16:09

Zach Saucier


Load all images and other data before draw and storage them inside array.
Better use requestAnimationFrame.
Remember, getting JSON (or other data) can take some time.

like image 28
trebor Avatar answered Sep 23 '22 16:09

trebor