Я працював над ігровим двигуном, подібним до Terraria , здебільшого як виклик, і, хоча я зрозумів більшість із цього, я не можу насправді загорнути голову, як вони обробляють мільйони взаємодіючих / збираючих плиток гра має за один раз. Створюючи близько 500 000 плиток, тобто 1/20 того, що можливо в Terraria , в моєму двигуні частота кадрів падає з 60 до 20, навіть тому я все ще лише вигляд плитки. Зауважте, я нічого не роблю з плитками, лише зберігаю їх у пам’яті.
Оновлення : код додано, щоб показати, як я роблю речі.
Це частина класу, яка обробляє плитки та малює їх. Я здогадуюсь, що винуватцем є частина "передбачення", яка повторює все, навіть порожні індекси.
...
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, який також може робити з оновленням, оскільки кожна плитка використовує чотири виклики методу SpriteBatch.Draw. Це частина моєї системи автоматичного накладання, що означає малювати кожен кут залежно від сусідніх плиток. text_ * - це прямокутники, встановлюються один раз на рівні створення, а не кожного оновлення.
...
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);
}
}
}
...