2010-12-28 5 views
5

.NET Framework 4を使用してC#でプログラミングしていて、XNAでタイルベースのゲームを作成しようとしています。私は1つの大きなテクスチャ(256ピクセルx 4096ピクセル)を持っています。これはタイルベースのゲームなので、このテクスチャは32ピクセル×32ピクセルのタイルが多数含まれているため、非常に大量です。私は専門家が間違いなくタイルベースのゲームが何であるかを知っていると思います。向きは直交(チェスボードのような)で、等角ではありません。Draw()20,000 32 x 32テクスチャまたは1つの大きなテクスチャ20,000 Times

Game.Draw()メソッドでは、2つの選択肢がありますが、そのうちの1つは他よりも非常に効率的です。

選択/方法#1:

セミ擬似コード:

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       SpriteBatch.Draw(
        MyLargeTexture, // One large 256 x 4096 texture 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(x, y, 32, 32), // Notice the source rectangle 'cuts out' 32 by 32 squares from the texture corresponding to the loop 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

キャプション:だから、効果的に、第1の方法は、一つの大きなテクスチャを毎回多くの多くの回を参照していますこの大きなテクスチャの小さな四角形を使用して適切なタイルイメージを描画します。

選択/方法#2

セミ擬似コード:

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       Texture2D tileTexture = map.GetTileTexture(x, y); // Getting a small 32 by 32 texture (different each iteration of the loop) 

       SpriteBatch.Draw(
        tileTexture, 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(0, 0, tileTexture.Width, tileTexture.Height), // Notice the source rectangle uses the entire texture, because the entire texture IS 32 by 32 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

キャプション:だから、効果的に、第二の方法は、多くの小さなテクスチャを何度も描いています。

質問:どの方法と理由ですか?個人的には、私は最初の方法を使う方がずっと効率的だと思います。マップ内のタイル配列の意味について考えてみましょう(2000タイルで2000タイルの大きなマップを考えてみましょう)、各タイルオブジェクトはソースのXとYの位置に2つの整数しか入れなくてはなりません1つの大きなテクスチャの長方形 - 8バイト。ただし、メソッド#2を使用する場合、マップのタイル配列の各Tileオブジェクトは、RGBAピクセルのメモリを32×32回割り当てなければならない32バイトのテクスチャ(画像)をタイルごとに4096バイトそれで?だから、どの方法と、なぜですか?第一の優先事項はスピード、次にメモリー負荷、効率、またはあなたの専門家が信じるものです。

答えて

9

最初の方法はです。多くはです。実際には、CPU側のデータ構造とは何の関係もありません。どちらの場合も、おそらく2バイトになる可能性があります。問題ではありません。

最初の方法が高速になる理由は、GPUの仕組みのためです。簡単に言えば、頂点/三角形のリストを含むGPU描画コマンドを送信するだけです。これらの頂点には、さまざまなデータ(位置、色、テクスチャ座標など)があります。重大なことに、テクスチャを指定することはできません。描画する前に、三角形を描画するテクスチャをグラフィックスデバイスで指定する必要があります。

SpriteBatchはスプライトを自動的に一括してバッチ処理するので、テクスチャスワップを最小限に抑え、送信されるコマンドを描画することができます。このため、ソートバイテクスチャを実行するオプションがあります。また、スプライトシートを使用できるようにするためにsource-rectangleパラメータが存在する理由もあるため、テクスチャを変更することなくスプライトを描画することができます。

(実際には、SpritBatchを使用していなくても、GPUに送信する描画コマンドは「バッチ」と呼ばれます)送信回数が多すぎると「バッチ限定」になることは驚くほど簡単ですバッチ限定 - 数百回のバッチが限界の非常に大まかな見積もりです)。

+0

包括的な回答をいただきありがとうございます。どうもありがとう! – Jason

2

GPUの状態変化を最小限に抑えるため、テクスチャが少ないほど速くなります。

ほとんどのタイルはフレーム間で変更されないことに注意してください。したがって、それらをすべて1つの画面サイズのレンダーターゲットに描画し、その後のフレームでは、1回の描画呼び出しでその単一のテクスチャを再描画します。上に変化するタイルを追加します。

+0

あなたの洞察に感謝します! – Jason

関連する問題