Ich habe eine Spiel-Engine entwickelt, die Terraria ähnelt , hauptsächlich als Herausforderung, und obwohl ich das meiste herausgefunden habe, kann ich nicht wirklich meinen Kopf darum legen, wie sie mit den Millionen von interagierbaren / erntbaren Kacheln umgeht Das Spiel hat auf einmal. Wenn ich in meiner Engine ungefähr 500.000 Kacheln erstelle , was 1/20 der in Terraria möglichen Kacheln entspricht, sinkt die Framerate von 60 auf ungefähr 20, obwohl ich immer noch nur die Kacheln in der Ansicht rendere. Wohlgemerkt, ich mache nichts mit den Kacheln, sondern behalte sie nur in Erinnerung.
Update : Code hinzugefügt, um zu zeigen, wie ich Dinge mache.
Dies ist Teil einer Klasse, die die Kacheln handhabt und zeichnet. Ich vermute, der Täter ist der "foreach" -Teil, der alles durchläuft, sogar leere Indizes.
...
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
foreach (Tile tile in this.Tiles)
{
if (tile != null)
{
if (tile.Position.X < -this.Offset.X + 32)
continue;
if (tile.Position.X > -this.Offset.X + 1024 - 48)
continue;
if (tile.Position.Y < -this.Offset.Y + 32)
continue;
if (tile.Position.Y > -this.Offset.Y + 768 - 48)
continue;
tile.Draw(spriteBatch, gameTime);
}
}
}
...
Hier ist auch die Tile.Draw-Methode, die auch ein Update verträgt, da jede Kachel vier Aufrufe der SpriteBatch.Draw-Methode verwendet. Dies ist Teil meines Autotiling-Systems, was bedeutet, dass jede Ecke in Abhängigkeit von benachbarten Kacheln gezeichnet wird. texture_ * sind Rechtecke, die bei der Levelerstellung einmal gesetzt werden, nicht bei jedem Update.
...
public virtual void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
if (this.type == TileType.TileSet)
{
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position, texture_tl, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 0), texture_tr, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(0, 8), texture_bl, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 8), texture_br, this.BlendColor);
}
}
...
Jede Kritik oder Anregung zu meinem Code ist willkommen.
Update : Lösung hinzugefügt.
Hier ist die letzte Level.Draw-Methode. Die Level.TileAt-Methode überprüft einfach die eingegebenen Werte, um OutOfRange-Ausnahmen zu vermeiden.
...
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
Int32 startx = (Int32)Math.Floor((-this.Offset.X - 32) / 16);
Int32 endx = (Int32)Math.Ceiling((-this.Offset.X + 1024 + 32) / 16);
Int32 starty = (Int32)Math.Floor((-this.Offset.Y - 32) / 16);
Int32 endy = (Int32)Math.Ceiling((-this.Offset.Y + 768 + 32) / 16);
for (Int32 x = startx; x < endx; x += 1)
{
for (Int32 y = starty; y < endy; y += 1)
{
Tile tile = this.TileAt(x, y);
if (tile != null)
tile.Draw(spriteBatch, gameTime);
}
}
}
...