Estou desenvolvendo um mecanismo de jogo semelhante ao Terraria , principalmente como um desafio, e embora tenha descoberto a maior parte, não consigo entender como eles lidam com os milhões de peças interativas / colhíveis o jogo tem ao mesmo tempo. Criar cerca de 500.000 peças, ou seja 1/20 do que é possível em Terraria , no meu mecanismo faz com que a taxa de quadros caia de 60 para cerca de 20, mesmo que eu ainda esteja apenas exibindo as peças. Veja bem, eu não estou fazendo nada com os ladrilhos, apenas mantendo-os na memória.
Atualização : código adicionado para mostrar como eu faço as coisas.
Isso faz parte de uma classe, que lida com os ladrilhos e os desenha. Acho que o culpado é a parte "foreach", que itera tudo, até índices vazios.
...
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);
}
}
}
...
Também aqui está o método Tile.Draw, que também pode ser uma atualização, pois cada Tile usa quatro chamadas para o método SpriteBatch.Draw. Isso faz parte do meu sistema de autotiling, o que significa desenhar cada canto, dependendo dos ladrilhos vizinhos. texture_ * são Retângulos, são definidos uma vez na criação do nível, não em cada atualização.
...
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);
}
}
...
Qualquer crítica ou sugestão ao meu código é bem-vinda.
Atualização : Solução adicionada.
Aqui está o método Level.Draw final. O método Level.TileAt simplesmente verifica os valores inseridos, para evitar exceções 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);
}
}
}
...