好的,所以基本上在我的游戏中,世界是由瓷砖组成的,瓷砖被分成块(50x50 瓷砖,瓷砖是 16x16),所以整个世界都没有加载到内存中。块被保存到文件中,并且只加载需要的块(屏幕上的块和屏幕两侧的 1 个屏幕外(顶部、左侧、底部、右侧)),其他块被卸载等。这一切都有效但是很好,当加载实际包含图块的块时,游戏逻辑会冻结很多(你知道加载文件吗?),基本上我的问题是如何使我当前的方法更快,所以几乎没有明显的滞后?
基本上每个块只包含一个 2D 字节数组,包含 tile 类型而不是实际的 tile 类,并且该字节数组保存到文件中以供以后加载。我的块加载/保存功能:
保存:
public void SaveChunk(int cx, int cy)
{
String chunkname = "";
chunkname = WorldChunks[cx, cy].X + "_" + WorldChunks[cx, cy].Y;
FileStream fileStream = File.Create(Main.ChunkPath + "\\Chunks\\" + chunkname + ".chnk");
StreamWriter writer = new StreamWriter(fileStream);
String json = JsonConvert.SerializeObject(WorldChunks[cx, cy].myTiles, Formatting.None);
writer.Write(json);
writer.Close();
}
加载:
public void LoadChunk(int xx, int yy)
{
string chunkname = xx + "_" + yy;
if (File.Exists(Main.ChunkPath + "\\Chunks\\" + chunkname + ".chnk"))
{
//If the chunk is not loaded, Create a new chunk and begin loading it's tiles.
if (WorldChunks[xx, yy] == null)
{
WorldChunks[xx, yy] = new Chunk(xx, yy);
}
System.Diagnostics.Debug.WriteLine("Loading chunk [" + xx + "," + yy + "]");
Stream stream = File.Open(Main.ChunkPath + "\\Chunks\\" + chunkname + ".chnk", FileMode.Open);
StreamReader reader = new StreamReader(stream);
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.TypeNameHandling = TypeNameHandling.Objects;
WorldChunks[xx, yy].myTiles = JsonConvert.DeserializeObject<byte[,]>(reader.ReadToEnd(), settings);
stream.Close();
System.Diagnostics.Debug.WriteLine("Chunk loaded.. [" + xx + "," + yy + "]");
int x, y;
for (x = 0; x < Main.ChunkSizeX; x++)
{
for (y = 0; y < Main.ChunkSizeY; y++)
{
byte _Type = WorldChunks[xx, yy].myTiles[x, y];
int tx = (xx * ChunkSizeX) + x;
int ty = (yy * ChunkSizeY) + y;
if (_Type > 0)
{
if (Tiles[tx, ty] == null && tx < MaxTilesX && ty < MaxTilesY)
{
Tiles[x + (xx * ChunkSizeX), (yy * ChunkSizeY) + y] = new Tile();
Tiles[(xx * ChunkSizeX) + x, (yy * ChunkSizeY) + y].Type = _Type;
if (ty > GROUND_LEVEL[tx] + 1)
{
//System.Diagnostics.Debug.Write("Below level:" + x + "|" + tx);
Tiles[tx, ty].HasBG = true;
}
}
else continue;
}
}
}
}
}
我尝试过更改块大小,尝试过 25x25、16x16、35x35 等。但仍然无济于事。那么我怎样才能使这些功能更快呢?任何其他提示/建议将不胜感激!谢谢!
编辑:我的代码中的瓶颈来自秒表和其他测试,是从文件中实际加载我什至删除了瓷砖的放置,它仍然锁定了游戏逻辑,但是我意识到最大的明显延迟是当我在 -在块之间,它必须加载比平时更多的块,如下所示:
现在我的块实际上可能比这更大,但同样的事情是可能的。
我的保存功能只是为每个图块保存 1 个字节,我的文件大小仅为每个块 2.5kb 左右,因为每个块有 2,500 个图块,每个图块 1 个字节(只是保存图块的类型)。
所以我认为保存和加载它们不会有太大影响,我之前也设置了一个异步文件流,但性能实际上是相同的。
这是我加载/卸载块的代码:
public void CheckChunks()
{
int StartX = (int)Math.Floor(ScreenPosition.X / (ChunkSizeX * 16)) - 2;
int StartY = (int)Math.Floor(ScreenPosition.Y / (ChunkSizeY * 16)) - 2;
if (StartX < 0) StartX = 0;
if (StartY < 0) StartY = 0;
int EndX = (int)Math.Floor((ScreenPosition.X + GraphicsDevice.Viewport.Width) / (ChunkSizeX * 16)) + 2;
int EndY = (int)Math.Floor((ScreenPosition.Y + GraphicsDevice.Viewport.Height) / (ChunkSizeY * 16)) + 2;
if (EndX > MaxChunksX) EndX = MaxChunksX;
if (EndY > MaxChunksY) EndY = MaxChunksY;
for (int x = StartX; x < EndX; x++)
{
for (int y = StartY; y < EndY; y++)
{
if (WorldChunks[x, y] == null)
{
LoadChunk(x, y, true);
if (WorldChunks[x, y] != null)
{
LoadedChunks.Add(WorldChunks[x, y]);
}
break;
}
}
}
foreach (Chunk cc in LoadedChunks)
{
if (cc.X < StartX || cc.Y < StartY || cc.X >EndX || cc.Y > EndY)
{
System.Diagnostics.Debug.WriteLine("Chunk to be unloaded..");
ChunkBuffer.Add(cc);
UnloadChunk(cc);
}
}
foreach (Chunk c in ChunkBuffer)
{
LoadedChunks.Remove(c);
}
ChunkBuffer.Clear();
}
像我的世界这样的游戏如何如此快速地加载和卸载它们的块?