2012-03-26 11 views
1

Diese Methode, scheint meine Fliesen zieht ganz langsam zu sein, ich bin nicht sicher, genau falsch, was ist, ist es meine Culling Methode ist nicht belive arbeiten und so zieht Offscreen, aber im nicht ganz herunter sicher. Hier ist sie:XNA - Culling Leistungsproblem

 // 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 ist eine Funktion zu erhalten, welche Fliesen sind um ihn herum, für verschiedene Texturen, wie DirtBlock_North, DirtBlock_Center usw.

Tile Inhalt wird nur eine Klasse mit meinem Block Texturen.

+0

Wie haben Sie festgestellt, dass dies der Code ist, der langsam ist? Wie viele Kacheln werden im Allgemeinen pro Bild gezeichnet? Wo nennst du SpriteBatch.Begin und .End? –

+0

Es ist sicher ein SpriteBatch-Problem, wenn ich nur die Zeichnung der Fliesen überspringe, aber Kollision und so lade, erhalte ich 30 fps. Das führt mich zu der Annahme, dass die Culling-Methode an der Spitze immer noch Sachen vom Bildschirm entfernt und das Umschalten der Grafik ein Problem ist. – Cyral

+0

sollten Sie wahrscheinlich einen Profiler verwenden, damit Sie genau feststellen können, was ihn langsam verursacht. Beispiel: SlimTune; http://code.google.com/p/slimtune/ –

Antwort

1

Versuchen Sie, SpriteBatch.Begin defered und alle Steine ​​auf eine Textur zu kombinieren.

Siehe this GameDev Frage für Informationen darüber, warum latenten ist höchstwahrscheinlich die schnellste Option für Sie.

Stellen Sie außerdem sicher, dass Sie jedes Mal, wenn Sie eine neue Textur zeichnen, die alte aus der GPU nehmen und die neue einfügen. Dieser Prozess wird Textur-Swapping genannt und ist normalerweise kein Problem, aber Sie tauschen Texturen aus zweimal pro Fliese, was die Leistung spürbar beeinträchtigen kann.

Dies kann durch die Kombination mehrerer Sprites auf eine Struktur und unter Verwendung des Quellrechtecks ​​Argument festgelegt werden. Dadurch können Sie mehrere Sprites ohne Texturaustausch zeichnen. Dafür gibt es ein paar OSS-Bibliotheken. Sprite Sheet Packer ist mein persönlicher Favorit.

Unfortunantly ohne das Projekt und ein Profiler ich nur raten bin; Dies sind jedoch die zwei größten Probleme beim Rendern von Tilemaps, die ich kenne. Ich kann wirklich nichts falsch von hier sehen. Im Folgenden ist der Code, den ich verwende, um meine Kachelmaps zu zeichnen und wie Sie sehen, ist es sehr ähnlich zu Ihrem.

Wenn alle Stricke reißen würde ich vorschlagen, einen Profiler verwenden, um herauszufinden, welche Bits langsam ausgeführt werden.

 //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

Während Sprite Sheets am ehesten zu empfehlen sind, könnte das OP 'SpriteSortMode.Texture' anstelle von Deferred ausprobieren. Dadurch wird alles nach Textur sortiert, wodurch der Texturwechsel minimiert wird. http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritesortmode.aspx –

+0

Ich werde SpriteSheets bald implementieren, aber ich versuchte es mit nur einer Textur anstelle von verschiedenen, und Es waren nur ein paar fps, also weiß ich, dass das nicht der Hauptgrund ist. – Cyral

+1

Danke, das ist ein guter Punkt, ich habe davon Abstand genommen, SpriteSortMode.Texture vorzuschlagen, denn wenn er Objekte oder Szenerien hat, kann das "Das kann die Leistung verbessern, wenn man nicht überlappende Sprites mit einheitlicher Tiefe zeichnet". Es zwingt ihn, ein separates Sprite-Batch zu verwenden, um nur die Kacheln zu rendern, was zwar die Renderzeit der Kachelkarte verbessert, aber die Gesamt-FPS beeinträchtigt, wenn NPCs und Szenerie berücksichtigt werden. – ClassicThunder