Pracowałem nad silnikiem gry podobnym do Terrarii , głównie jako wyzwanie, i chociaż doszedłem do wniosku, że tak naprawdę, nie mogę się skupić na tym, jak radzą sobie z milionami interaktywnych / możliwych do zebrania płytek gra ma kiedyś. Utworzenie około 500 000 kafelków, czyli 1/20 tego, co jest możliwe w Terrarii , w moim silniku powoduje spadek szybkości klatek z 60 do około 20, nawet jeśli nadal wyświetlam kafelki tylko na widoku. Pamiętaj, że nie robię nic z kafelkami, tylko utrzymuję je w pamięci.
Aktualizacja : Dodano kod, aby pokazać, jak to robię.
Jest to część klasy, która obsługuje płytki i rysuje je. Zgaduję, że winowajcą jest część „foreach”, która iteruje wszystko, nawet puste indeksy.
...
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);
}
}
}
...
Również tutaj jest metoda Tile.Draw, która mogłaby również zrobić z aktualizacją, ponieważ każda płytka używa czterech wywołań metody SpriteBatch.Draw. Jest to część mojego systemu autotilowania, co oznacza rysowanie każdego rogu w zależności od sąsiadujących płytek. tekstury_ * są prostokątami, są ustawiane raz na poziomie tworzenia, a nie każdej aktualizacji.
...
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);
}
}
...
Każda krytyka lub sugestie dotyczące mojego kodu są mile widziane.
Aktualizacja : Dodano rozwiązanie.
Oto ostatnia metoda Level.Draw. Metoda Level.TileAt sprawdza po prostu wprowadzone wartości, aby uniknąć wyjątków 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);
}
}
}
...