나는 Terraria 와 비슷한 게임 엔진을 주로 도전 과제 로 연구 해 왔으며 대부분을 알아 냈지만 수백만 개의 상호 작용 가능 / 수확 가능한 타일을 처리하는 방법에 대해 머리를 감쌀 수는 없습니다. 게임은 한 번에 있습니다. 내 엔진에서 약 500.000 타일, 즉 Terraria 에서 가능한 것의 1/20을 만들면 프레임 속도가 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 메서드를 4 번 호출하므로 업데이트를 수행 할 수도 있습니다. 이것은 자동 타일링 시스템의 일부이며 인접한 타일에 따라 각 모서리를 그리는 것을 의미합니다. 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);
}
}
}
...