2011-12-10 40 views
8

Tôi đang thực hiện một trò chơi HTML5 nhỏ và, trong khi tải các họa tiết của tôi ở đầu bản đồ, tôi thực hiện một số thao tác với GetImageData()/lặp qua tất cả hình ảnh/PutImageData().Hiệu năng GetImageData()/PutImageData() trên điện thoại di động

Điều này hoạt động tuyệt vời tuyệt vời trên PC của tôi, tuy nhiên, trên điện thoại di động của tôi đó là khủng khiếp chậm.

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

Tôi đã thực hiện một số điểm chuẩn cơ bản, và cả GetImageData và PutImageData chạy rất nhanh, những gì diễn ra lâu dài là lặp qua nội dung.

Bây giờ, tôi rõ ràng là mong đợi sự sụt giảm trên điện thoại, nhưng âm thanh 1000x hơi quá mức và tải mất khoảng 4 phút trên HTC của tôi, vì vậy sẽ không hoạt động. Ngoài ra, mọi thứ khác trong trò chơi hoạt động ở tốc độ rất hợp lý (chủ yếu vì màn hình là ridiculously nhỏ hơn, nhưng vẫn còn, nó hoạt động đáng ngạc nhiên tốt cho JS trên điện thoại di động)


Những gì tôi đang làm trong chế biến này về cơ bản là "tối đen" các sprite đến một mức độ nhất định. Tôi chỉ đơn giản là lặp qua tất cả các điểm ảnh, và nhân chúng với một giá trị < 1. Đó là tất cả.

Vì điều này quá chậm ... Có cách nào tốt hơn để làm điều tương tự, sử dụng chức năng Canvas, (tổng hợp, độ mờ đục, bất cứ điều gì), mà không lặp qua tất cả các pixel từng cái một?

LƯU Ý: Lớp này có một số pixel trong suốt 100% và một số pixel mờ đục 100%. Cả hai cần phải duy trì 100% mờ hoặc 100% trong suốt.

Những điều tôi đã nghĩ về điều đó sẽ không hoạt động:
1) Vẽ họa tiết trong canvas mới, có độ mờ thấp hơn. Điều này sẽ không hiệu quả vì tôi cần các sprites vẫn còn đục, chỉ tối hơn.
2) Vẽ các họa tiết, và vẽ một hình bán nguyệt màu đen trong suốt trên đầu trang của chúng. Điều này sẽ làm cho chúng tối hơn, nhưng nó cũng sẽ làm cho các pixel trong suốt của tôi không trong suốt nữa ...

Bất kỳ ý tưởng nào?

Đây là mã tôi đang sử dụng, chỉ trong trường hợp bạn nhìn thấy một cái gì đó khủng khiếp ngu ngốc trong đó:

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 
} 

EDIT: Đây là một ví dụ về những gì tôi đang cố gắng để làm với các hình ảnh :
gốc: http://www.crystalgears.com/isoengine/sprites-ground.png
Darkened: http://www.crystalgears.com/isoengine/sprites-ground_darkened.png

Cảm ơn!
Daniel

+0

vui lòng cho chúng tôi biết trước và sau ảnh của hiệu ứng bạn đang cố gắng đạt được? –

+0

Chỉ cần thêm các liên kết ở cuối câu hỏi. Cảm ơn! –

+3

Bạn đang cố gắng làm tối một số họa tiết? Để đạt được hiệu quả tốt, không sử dụng dữ liệu hình ảnh trên mỗi pixel cho điều đó. Chỉ cần vẽ màu đen bán trong suốt (với một [globalCompositeOperation'] khác nhau (http://www.tutorialspoint.com/html5/canvas_composition.htm) để bảo tồn alpha). – Phrogz

Trả lời

11

Phrogz có ý tưởng đúng. Bạn thực sự chỉ muốn vẽ một màu đen nửa trong suốt (hoặc tỷ lệ trong suốt) trên toàn bộ điều với 'nguồn trên đỉnh' globalCompositeOperation.

Như thế này: http://jsfiddle.net/F4cNg/

Có thực sự là một câu hỏi hay về sạm phức tạp như thế này nhưng tác giả đã xóa nó mà là một sự xấu hổ thực sự. Nó chắc chắn có thể làm cho mặt nạ tối trên các công cụ vẽ, ngay cả với hình dạng tinh vi.Họ có thể không giúp bạn, nhưng vì lợi ích của sự hoàn chỉnh và cho bất kỳ ai tìm kiếm công cụ "làm tối vải" nơi một số bộ phận được giữ ánh sáng (khu vực loại trừ), có thể được thực hiện với 'xor' globalCompositeOperation, như sau:

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

+0

Cảm ơn bạn rất nhiều, đây chính xác là những gì tôi cần. Tôi đã xem xét tối thiểu kết quả cuối cùng của bản vẽ. Bí quyết XOR thật tuyệt, đơn giản hơn nhiều so với những gì tôi định làm, nhưng ngay cả khi không có nó, tôi chỉ có thể vẽ trực tràng bằng "lỗ hổng". Tại thời điểm đó, tôi không quan tâm đến các pixel trong suốt nữa. Tuy nhiên, tôi không dùng cách tiếp cận đó, vì tôi đang sử dụng quan điểm ISO và phương pháp của tôi, trong khi chậm hơn, cho phép tôi có độ chính xác cao hơn một chút về một vài điều mà tôi quan tâm. Cảm ơn cho tip, mặc dù, tôi chắc chắn sẽ có ích đôi khi. CẢM ƠN!!! –

10

bạn đã thấy mũi hiệu suất này ?: http://ajaxian.com/archives/canvas-image-data-optimization-tip

Họ nói về việc giảm các cuộc gọi đến DOM để tăng hiệu suất.

Vì vậy, dựa trên mẹo này bạn có thể thử:

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; 
    } 

cuộc gọi .data của bạn có thể làm chậm bạn xuống.

Các vấn đề liên quan