2012-01-03 6 views
3

私はアイソメトリックタイルゲームエンジンを作成し、このコードの速度に問題があることを試みる:私は低い数字にLocation.widthとLocation.heightを設定した場合、それは速い(50 FPS)を実行キャンバスで描画タイルをどのように高速化するには?

$(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 = 60Location.height = 120)フレームレートは10fpsで、50fpsが必要です。このスクリプトを高速化する方法はありますか?

+1

好奇心の高まりから、ここで乗算と除算が達成されます: 'Math.round(this.realFPS * 1)/ 1'? –

答えて

5

1)見ることができない場合でも、すべてのタイルを描画しているように見えます。 「クリッピング」を使用します。 context.drawImage()を呼び出す前に、タイルが表示されているかどうかを計算する必要があります。

2)あなたの風景が静止している場合は、できるだけ多く計算してください。しかし、巨大な画像を作成することは良い考えではありません。大きな塊(512x512など)をあらかじめ計算しておくことをお勧めします。

3)一部のブラウザでは、 'setTimeout()'の代わりにrequestAnimationFrame(私もthis articleがかなり興味深い)を使用すると、より良いフレームレートを得ることができると言われています。

4)サイズ変更/スケーリングがパフォーマンスに影響することがあります(特に古いブラウザやハードウェアでは)。タイルがすでに32x64の場合は、3つのパラメータでdrawImage()を使用してサイズ変更を避けることができます(ズームエフェクトなどを実現するために拡大/縮小する必要がある場合は該当しません)。

+0

+1、特に見ることができないタイルを描画しないで、可能であればそれらのサイズを変更しない部分については –

+1

見ることができないタイルは描画しません。クリッピングはまだ良い提案ですが、それを指摘したいだけです。 – Loktar

0

私の側であなたのコードをつぶした後、あなたが投稿したコードで45-50の間になってしまった。 1つの提案は、jQueryを使用しないことですが、fpsを表示する要素のhtmlも変更しないでください。また、デモを100フレームで最大限に修正し、約70フレーム/秒に変更しました。

また、サイズ変更したイメージをキャッシュして、その代わりにパフォーマンスを向上させることもできます。以下のデモでは、サイズ変更されたイメージを一時キャンバスにキャッシュし、代わりに使用します。

Live Demo(その白い画面がもう一度実行を打つので、もし私が、画像のためのonloadを実装するように感じるdidntは)

0

優れた答えを@jjmontesに加えて、あなたはまた、複数のcanvas要素を使用する必要がありますキャンバスの変更された部分のみを更新します。今は毎回すべてをクリアして再描画しています。

関連する問題