Ho lavorato su un motore di gioco simile a Terraria , principalmente come una sfida, e mentre ho capito la maggior parte di esso, non riesco davvero a avvolgere la mia testa su come gestiscono i milioni di tessere intercambiabili / vendibili il gioco ha contemporaneamente. La creazione di circa 500.000 tessere, ovvero 1/20 di ciò che è possibile fare in Terraria , nel mio motore fa scendere il frame rate da 60 a circa 20, anche se sto ancora visualizzando solo le tessere in vista. Intendiamoci, non sto facendo nulla con le tessere, ma solo conservandole in memoria.
Aggiornamento : codice aggiunto per mostrare come faccio le cose.
Questo fa parte di una classe, che gestisce le tessere e le disegna. Immagino che il colpevole sia la parte "foreach", che itera tutto, anche gli indici vuoti.
...
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);
}
}
}
...
Anche qui è il metodo Tile.Draw, che potrebbe anche fare con un aggiornamento, poiché ogni Tile utilizza quattro chiamate al metodo SpriteBatch.Draw. Questo fa parte del mio sistema di autotiling, che significa disegnare ogni angolo a seconda delle tessere vicine. texture_ * sono Rettangoli, vengono impostati una volta alla creazione del livello, non ogni aggiornamento.
...
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);
}
}
...
Qualsiasi critica o suggerimento al mio codice è il benvenuto.
Aggiornamento : soluzione aggiunta.
Ecco il metodo Level.Draw finale. Il metodo Level.TileAt controlla semplicemente i valori immessi, per evitare eccezioni OutOfRange.
...
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);
}
}
}
...