2012-03-26 47 views
1

這種繪製我的瓷磚的方法似乎很慢,我不確定究竟是什麼錯誤,它相信我的剔除方法不工作,並正在繪製屏幕外的東西,但我不完全確定。那就是:XNA - 剔除性能問題

 // Calculate the visible range of tiles. 
     int left = (int)Math.Floor(cameraPosition.X/16); 
     int right = left + spriteBatch.GraphicsDevice.Viewport.Width/16; 
     right = Math.Min(right, Width) + 1; // Width -1 originally - didn't look good as tiles drawn on screen 
     if (right > tiles.GetUpperBound(0)) 
      right = tiles.GetUpperBound(0) + 1; // adding 1 to get the last right tile drawn 

     int top = (int)Math.Floor(cameraPosition.Y/16); 
     int bottom = left + spriteBatch.GraphicsDevice.Viewport.Height/ 16; 
     bottom = Math.Min(bottom, Height) + 1; // Height -1 originally - didn't look good as tiles drawn on screen 
     if (bottom > tiles.GetUpperBound(1)) 
      bottom = tiles.GetUpperBound(1) + 1; // adding 1 to get the last bottom tile drawn 

     // For each tile position 
     for (int y = top; y < bottom; ++y) 
     { 
      for (int x = left; x < right; ++x) 
      { 
       // If there is a visible tile in that position, draw it 
       if (tiles[x, y].BlockType.Name != "Blank") 
       { 
        Texture2D texture = tileContent["DirtBlock_" + getTileSetType(tiles,x,y)]; 
        spriteBatch.Draw(texture, new Vector2(x * 16, y * 16), Color.White); 
        if (isMinimap) 
        spriteBatch.Draw(pixel, new Vector2(30+x, 30+y), Color.White); 
       } 

      } 
     } 

GetTileSetTypes是一個函數來獲取什麼磚周圍,爲不同的紋理,像DirtBlock_North,DirtBlock_Center等

瓷磚的內容僅僅是一類與我的塊紋理。

+0

你是怎麼確定這是代碼慢的?一般每幀有多少塊瓷磚?你在哪裏調用SpriteBatch.Begin和.End? – 2012-03-26 19:27:26

+0

它明顯是一個SpriteBatch問題,當我跳過瓷磚的繪製,但加載碰撞等,我獲得30幀/秒。這導致我認爲頂部的剔除方法仍然在屏幕上繪畫,切換圖形是一個問題。 – Cyral 2012-03-26 20:18:49

+0

你應該使用一個分析器,這樣你就可以精確地確定是什麼導致它變慢了。例如:SlimTune; http://code.google.com/p/slimtune/ – 2012-03-26 21:50:15

回答

1

嘗試更改SpriteBatch.Begin來將所有拼貼塊擊倒併合併到一個紋理上。

請參閱this關於爲什麼延期最有可能是您最快的選擇的信息的GameDev問題。

也意識到每次你繪製一個新的紋理時,你必須從GPU中取出舊的紋理並放入新的紋理。這個過程稱爲紋理交換,通常不是問題,而是交換紋理每瓦兩次,可能會顯着影響性能。

這可以通過將多個精靈組合到一個紋理上並使用源矩形參數來解決。這允許你繪製多個精靈而不需要紋理交換。這裏有幾個OSS庫。 Sprite Sheet Packer是我個人的最愛。

不幸的是沒有項目和一個探查器我只是猜測;然而,這些是我知道渲染tilemaps的兩個最大的陷阱。我從這裏看不到任何錯誤。下面是我用來繪製我的瓷磚地圖的代碼,因爲您看到它與您的非常相似。

如果一切都失敗了,我建議使用探查器找出哪些位運行緩慢。

 //Init the holder 
     _holder = new Rectangle(0, 0, TileWidth, TileHeight); 

     //Figure out the min and max tile indices to draw 
     var minX = Math.Max((int)Math.Floor((float)worldArea.Left/TileWidth), 0); 
     var maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right/TileWidth), Width); 

     var minY = Math.Max((int)Math.Floor((float)worldArea.Top/TileHeight), 0); 
     var maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom/TileHeight), Height); 

     for (var y = minY; y < maxY; y++) { 
      for (var x = minX; x < maxX; x++) { 

       _holder.X = x * TileWidth; 
       _holder.Y = y * TileHeight; 

       var t = tileLayer[y * Width + x]; 
       spriteBatch.Draw(
        t.Texture, 
        _holder, 
        t.SourceRectangle, 
        Color.White, 
        0, 
        Vector2.Zero, 
        t.SpriteEffects, 
        0); 
      } 
     } 
+0

雖然精靈表最有可能走的路,OP可以嘗試'SpriteSortMode.Texture'而不僅僅是延期。這將通過紋理對所有內容進行排序,這將最小化紋理切換。 http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritesortmode.aspx – 2012-03-26 18:19:17

+0

即將實現SpriteSheets很快,但我嘗試只用一個紋理而不是不同的紋理,並且它只有幾個fps,所以我知道這不是主要原因。 – Cyral 2012-03-26 18:21:16

+1

謝謝你,這是一個很好的觀點,我沒有建議SpriteSortMode.Texture,因爲如果他有物體或風景,「繪製不重疊的均勻深度精靈時,這可以提高性能」並不適用。它迫使他使用一個單獨的spritebatch來渲染tile,這有助於tilemap的渲染時間,但在考慮到NPC和風景後會傷害整體fps。 – ClassicThunder 2012-03-26 18:24:52