我一直在开发类似于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方法的四个调用。这是我的自动平铺系统的一部分,这意味着根据相邻的图块绘制每个角。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);
}
}
}
...