2012-01-03 32 views
3

我試着寫一個等距瓷磚的遊戲引擎,並有問題,這個代碼的速度:如何加速在畫布上繪製瓷磚?

$(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 = 60,Location.height = 120)framerate是10fps,我需要50fps,你有什麼sugestions如何加快這個腳本?

+1

出於好奇,乘法和除法在這裏完成了什麼:'Math.round(this.realFPS * 1)/ 1'? – 2012-01-03 15:25:19

回答

5

1)在我看來,即使他們不在視野中,你正在繪製每塊瓷磚。使用「裁剪」。在調用context.drawImage()之前,您需要計算是否在視圖中。

2)如果您的風景是靜態的,請預先計算(儘可能)。然而,創建一個巨大的圖像也不是一個好主意,你應該預先計算一些大塊(即512x512)。

3)在某些瀏覽器,它是說你可以得到更好的幀速率,如果不是使用「的setTimeout()」你用requestAnimationFrame(我還發現this article挺有意思)。

4)調整大小/縮放可能會影響性能(尤其是在較舊的瀏覽器或硬件中)。如果你的圖塊已經是32x64,你可以使用只有3個參數的drawImage(),避免調整大小(如果你需要縮放以達到縮放效果或類似效果,則不適用)。

+0

+1,特別是關於不繪製無法看到的瓷磚的部分,如果可能的話不要在動態調整它們的大小 – 2012-01-03 15:23:29

+1

僅供參考,他不繪製任何看不到的瓷磚。剪輯仍然是一個很好的建議,只是想指出。 – Loktar 2012-01-03 15:35:46

0

在您的代碼在我身邊搞亂之後我得到45-50之間與您發佈的代碼。一個建議是不使用jQuery,也不要修改顯示fps的元素的html。我還修改了你的演示版,最多可以達到100幀,並且它可以達到70幀/秒。

您也可以嘗試緩存調整大小的圖像並使用該圖像,您應該看到性能提高。在下面的演示中,我將調整大小的圖像緩存在臨時畫布上,然後使用它。

Live Demo(我不覺得自己實現了圖像的onload,所以如果一個白色的屏幕只是再次命中運行)

0

除了@jjmontes優秀的答案,你也應該用在多個畫布元素您的遊戲,並只更新畫布上已更改的部分。現在你每次都清理和重繪一切。