He estado trabajando en un motor de juego similar a Terraria , principalmente como un desafío, y aunque he descubierto la mayor parte, realmente no puedo entender cómo manejan los millones de fichas interactivas / cosechables el juego tiene a la vez. La creación de alrededor de 500,000 mosaicos, que es 1/20 de lo que es posible en Terraria , en mi motor hace que la velocidad de cuadros baje de 60 a alrededor de 20, incluso aunque todavía solo esté visualizando los mosaicos a la vista. Eso sí, no estoy haciendo nada con las fichas, solo las mantengo en la memoria.
Actualización : Código agregado para mostrar cómo hago las cosas.
Esto es parte de una clase, que maneja los mosaicos y los dibuja. Supongo que el culpable es la parte "foreach", que repite todo, incluso los índices vacíos.
...
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);
}
}
}
...
También aquí está el método Tile.Draw, que también podría funcionar con una actualización, ya que cada Tile utiliza cuatro llamadas al método SpriteBatch.Draw. Esto es parte de mi sistema de autotiling, lo que significa dibujar cada esquina dependiendo de los mosaicos vecinos. texture_ * son Rectángulos, se establecen una vez en el nivel de creación, no cada actualización.
...
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);
}
}
...
Cualquier crítica o sugerencia a mi código es bienvenida.
Actualización : Solución agregada.
Aquí está el método final de Level.Draw. El método Level.TileAt simplemente verifica los valores ingresados, para evitar excepciones 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);
}
}
}
...