Я работал над игровым движком, похожим на Terraria , в основном как вызов, и, хотя я понял большую его часть, я не могу понять, как они справляются с миллионами интерактивных / собираемых плиток в игре есть одно время. Создание около 500 000 плиток, что составляет 1/20 от того, что возможно в Terraria , в моем движке приводит к падению частоты кадров с 60 до около 20, даже если я все еще только отображаю плитки в поле зрения. Имейте в виду, я ничего не делаю с плитками, только храню их в памяти.
Обновление : код добавлен, чтобы показать, как я делаю вещи.
Это часть класса, который обрабатывает плитки и рисует их. Я предполагаю, что виновником является часть «foreach», которая повторяет все, даже пустые индексы.
...
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);
}
}
}
...
Также здесь есть метод Tile.Draw, который также можно сделать с обновлением, поскольку каждый Tile использует четыре вызова метода SpriteBatch.Draw. Это часть моей системы автотайлинга, которая подразумевает рисование каждого угла в зависимости от соседних плиток. texture_ * - это прямоугольники, которые устанавливаются один раз при создании уровня, а не при каждом обновлении.
...
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);
}
}
...
Любая критика или предложения к моему коду приветствуются.
Обновление : решение добавлено.
Вот последний метод Level.Draw. Метод Level.TileAt просто проверяет введенные значения, чтобы избежать исключений 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);
}
}
}
...