Terraria'ya benzer bir oyun motoru üzerinde çalıştım, çoğunlukla bir meydan okuma olarak ve çoğu şeyi çözdüğümde , kafamı milyonlarca etkileşimli / toplanabilir döşemeyle nasıl başa çıktıklarına dolamıyorum oyun bir anda var. Motorumda Terraria’da mümkün olanın 1 / 20’si civarında olan yaklaşık 500.000 kiremit oluşturmak, hala kiremitleri görüntülemişken bile, kare hızının 60’ın 20’ye düşmesine neden oluyor. Dikkat et, fayanslarla bir şey yapmıyorum, sadece hafızada tutuyorum.
Güncelleme : Nasıl yaptığımı göstermek için kod eklendi.
Bu, fayansları işleyen ve çizen bir sınıfın parçası. Suçlu her şeyi yineleyen, boş dizinler bile "foreach" kısmı sanırım.
...
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);
}
}
}
...
Ayrıca burada, her bir Döşeme SpriteBatch.Draw yöntemine dört çağrı kullandığı için güncelleme ile de yapabilecek Tile.Draw yöntemidir. Bu benim ototileme sistemimin bir parçası, komşu fayanslara bağlı olarak her köşeyi çizmek anlamına geliyor. texture_ * dikdörtgenler, her güncelleme için değil, seviye oluşturmada bir kez ayarlanır.
...
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);
}
}
...
Kodumla ilgili herhangi bir eleştiri veya öneri kabul edilir.
Güncelleme : Çözüm eklendi.
İşte son Level.Draw yöntemi. Level.TileAt yöntemi, OutOfRange istisnalarını önlemek için girilen değerleri kontrol eder.
...
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);
}
}
}
...