如何加快画布上的绘图?

时间:2012-01-03 15:07:09

标签: javascript jquery html5-canvas

我尝试编写一个等距瓷砖游戏引擎,并且对此代码的速度有问题:

$(function() {

var canvas = document.getElementById('GameCanvas');
var context = document.getElementById('GameCanvas').getContext('2d');

var imgObj = new Image();
imgObj.src = 'img/sand_surface.png';

var Game = {

    tileScaleX: 64,
    tileScaleY: 32,
    FPSLimit: 50, // max allowed framerate
    realFPS: 0, // real framerate

    init: function() {


        this.cycle(); // main animation loop
    },

    cycle: function() {

        this.debug(); // print framerate

        startTime = new Date; // start fps time

        this.clear(); // celar canvas       
        this.draw(); // draw frame

        endTime = new Date; // end fps time

        setTimeout(function() {
            endTimeWithSleep = new Date; // end fps time with sleep
            this.realFPS = 1000 / (endTimeWithSleep - startTime);
            this.cycle(); // repeat animation loop
        }.bind(this), (1000 / this.FPSLimit) - (endTime - startTime));
    },

    debug: function() {

        $('.DebugScreen').html('<b>FPS:</b> ' + Math.round(this.realFPS*1)/1);
    },

    clear: function() {

        canvas.width = canvas.width; // clear canvas
    },

    draw: function() {

        Location.drawSurface(); // draw tiles
    },

}

var Location = {

    width: 60,
    height: 120,

    drawSurface: function() {

        for (y = 0; y < this.height; y++) {

            for (x = 0; x < this.width; x++) {

                if ((y % 2) == 0) {
                    rowLeftPadding = 0;
                } else {
                    rowLeftPadding = Game.tileScaleX / 2;
                }

                context.drawImage(imgObj, (x * Game.tileScaleX + rowLeftPadding), y * (Game.tileScaleY / 2), Game.tileScaleX, Game.tileScaleY);
            }
        }
    },
}

Game.init(); // start game
});

如果我将Location.width和Location.height设置为较低的数字,那么它会快速运行(50 fps),但在此示例中(Location.width = 60Location.height = 120)帧速率为10 fps,我需要50 fps,你有什么方法可以加快这个脚本的速度吗?

3 个答案:

答案 0 :(得分:5)

1)我觉得你正在绘制每一块瓷砖,即使它们不在视野中。使用“剪裁”。在调用context.drawImage()之前,您需要计算图块是否在视图中。

2)如果您的风景是静态的,请尽可能预先计算。然而,创建一个巨大的图像也不是一个好主意,你宁愿预先计算一些大块(即512x512)。

3)在某些浏览器中,如果不使用'setTimeout()'而使用requestAnimationFrame(我也发现this article非常有趣),可以说你可以获得更好的帧速率。

4)调整大小/缩放可能会影响性能(特别是在较旧的浏览器或硬件中)。如果你的图块已经是32x64,你可以使用只有3个参数的drawImage(),避免调整大小(如果你需要缩放以实现缩放效果或类似效果,则不适用)。

答案 1 :(得分:0)

在我的代码中弄乱你的代码后,我发布的代码在45-50之间。一个建议是不使用jQuery,也不要修改元素的html来显示fps。我还将您的演示修改为最大100帧,并且大约达到70帧/秒。

您还可以尝试缓存已调整大小的图像并使用它,您应该会看到性能提升。在下面的演示中,我将调整大小的图像缓存在临时画布上,然后使用它。

Live Demo (我不想为图片实现onload,所以如果它的白色屏幕再次点击运行了)

答案 2 :(得分:0)

除了@jjmontes优秀的答案外,您还应该在游戏中使用多个画布元素,并且只更新画布中已更改的部分。现在你每次都清理并重新绘制所有内容。