Я играю в небольшую HTML5-игру и, загружая свои спрайты в начале карты, я выполняю некоторую обработку с помощью GetImageData () / зацикливаю все изображение / PutImageData ().
Это фантастически отлично работает на моем ПК, однако на моих мобильных телефонах он ужасающе медленный.
PC: 5-6 ms
iPhone 4: 300-600 ms
Android HTC Desire S: 2500-3000 ms
Я провел ОЧЕНЬ базовый тест, и GetImageData и PutImageData работают очень быстро, что занимает много времени, так это цикл
Я очевидно ожидаю замедления работы телефона, но 1000x звучит немного чрезмерно, и загрузка занимает примерно 4 минуты на моем HTC, так что это не сработает.Кроме того, все остальное в игре работает с очень разумной скоростью (в основном из-за того, что экран смехотворно меньше, но все же он работает на удивление хорошо для JS на мобильном телефоне)
В этой обработке я в основном "затемняю" "спрайт до определенного уровня. Я просто перебираю все пиксели и умножаю их на значение
Поскольку это слишком медленно ... Есть ли лучший способ сделать то же самое, используя функциональные возможности 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
Спасибо!
Даниэль