8

我正在做一个 HTML5 小游戏,在地图开头加载我的精灵时,我使用 GetImageData()/循环遍历所有图像/PutImageData() 进行了一些处理。

这在我的 PC 上效果非常好,但是在我的手机上却非常慢。

PC: 5-6 ms
iPhone 4: 300-600 ms
Android HTC Desire S: 2500-3000 ms

我一直在做一些非常基本的基准测试,GetImageData 和 PutImageData 都运行得非常快,需要很长时间的是内容的循环。

现在,我显然预计手机会变慢,但 1000 倍听起来有点过分,而且在我的 HTC 上加载大约需要 4 分钟,所以这是行不通的。此外,游戏中的其他一切都以非常合理的速度运行(主要是因为屏幕小得离谱,但对于手机上的 JS 来说,它仍然运行得非常好)


我在这个处理中所做的基本上是将精灵“变暗”到一定程度。我只是循环遍历所有像素,然后将它们乘以 < 1 的值。仅此而已。

因为这太慢了......有没有更好的方法来做同样的事情,使用 Canvas 功能(合成,不透明度,等等),而不是一个一个地循环遍历所有像素?

注意:这一层有一些 100% 透明像素和一些 100% 不透明像素。两者都需要保持 100% 不透明或 100% 透明。

我认为那行不通的事情:
1)在新的画布上绘制精灵,不透明度较低。这不起作用,因为我需要精灵保持不透明,只是更暗。
2)绘制精灵,并在它们上面绘制一个半透明的黑色矩形。这会使它们变暗,但它也会使我的透明像素不再透明......

有任何想法吗?

这是我正在使用的代码,以防万一你在其中看到一些非常愚蠢的东西:

function DarkenCanvas(baseImage, ratio) {
    var tmpCanvas = document.createElement("canvas");
    tmpCanvas.width = baseImage.width;
    tmpCanvas.height = baseImage.height;
    var ctx = tmpCanvas.getContext("2d");
    ctx.drawImage(baseImage, 0, 0);

    var pixelData = ctx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
    var length = pixelData.data.length;
    for (var i = 0; i < length; i+= 4) {
        pixelData.data[i] = pixelData.data[i] * ratio;
        pixelData.data[i + 1] = pixelData.data[i + 1] * ratio;
        pixelData.data[i + 2] = pixelData.data[i + 2] * ratio;
    }

    ctx.putImageData(pixelData, 0, 0);
    return tmpCanvas
}

编辑:这是我试图用图像做的一个例子:
原始:http:
//www.crystalgears.com/isoengine/sprites-ground.png 变暗:http ://www.crystalgears.com/isoengine /sprites-ground_darkened.png

谢谢!
丹尼尔

4

2 回答 2

11

Phrogz 的想法是正确的。你真的只想用'source-atop' globalCompositeOperation 在整个东西上画一个半透明(或比率透明)的黑色。

像这样:http: //jsfiddle.net/F4cNg/

实际上有一个关于像这样复杂的变暗的好问题,但作者删除了它,这是一个真正的耻辱。当然可以在绘制的东西上制作深色蒙版,即使是复杂的形状。它们可能对您没有帮助,但为了完整起见,以及任何搜索“深色画布”的人,其中某些部分保持亮光(禁区),可以使用“xor”globalCompositeOperation 来完成,如下所示:

http://jsfiddle.net/k6Xwy/1/

于 2011-12-10T04:14:02.627 回答
11

你见过这个性能提示吗?: http: //ajaxian.com/archives/canvas-image-data-optimization-tip

他们谈论减少对 DOM 的调用以提高性能。

因此,基于此提示,您可以尝试:

var pixel = ctx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
    pixelData=pixel.data; // detach the pixel array from DOM
    var length = pixelData.length;
    for (var i = 0; i < length; i+= 4) {
        pixelData[i] = pixelData[i] * ratio;
        pixelData[i + 1] = pixelData[i + 1] * ratio;
        pixelData[i + 2] = pixelData[i + 2] * ratio;
    }

您的 .data 调用可能会减慢您的速度。

于 2012-10-06T02:20:26.410 回答