我到处寻找解决这个问题的方法(我可能只是盲目地看到了周围的解决方案)。我的游戏目前呈现的tilemap在屏幕上,并将不会呈现的瓷砖,实际上是在屏幕范围内。然而,每个平铺是16x16像素,如果屏幕上的每个像素包含一个1920x1080分辨率的瓷砖,就意味着要绘制8100块。
每个周期画那么多的瓷砖真的会毁掉我的FPS。如果我运行800x600分辨率,我的FPS达到20,而在1920x1080,它运行在3-5 FPS左右。这真的让我发疯了。
我尝试过线程处理和使用异步任务,但是这些任务只会闪烁屏幕。可能只是我做错了编码。
这是我目前使用的绘图代码。
// Get top-left tile-X
Vector topLeft = new Vector(Screen.Camera.X / 16 - 1,
Screen.Camera.Y / 16 - 1);
Vector bottomRight = new Vector(topLeft.X + (Screen.Width / 16) + 2,
topLeft.Y + (Screen.Height / 16) + 2);
// Iterate sections
foreach (WorldSection section in Sections)
{
// Continue if out of bounds
if (section.X + ((Screen.Width / 16) + 2) < (int)topLeft.X ||
section.X >= bottomRight.X)
continue;
// Draw all tiles within the screen range
for (int x = topLeft.X; x < bottomRight.X; x++)
for (int y = topLeft.Y; y < bottomRight.Y; y++)
if (section.Blocks[x - section.X, y] != '0')
DrawBlock(section.Blocks[x - section.X, y],
x + section.X, y);
}
有8至12节。每个瓷砖都由二维数组中的char对象表示.
绘制块法:
public void DrawBlock(char block, int x int y)
{
// Get the source rectangle
Rectangle source = new Rectangle(Index(block) % Columns * FrameWidth,
Index(block) / Columns * FrameHeight, FrameWidth, FrameHeight);
// Get position
Vector2 position = new Vector2(x, y);
// Draw the block
Game.spriteBatch.Draw(Frameset, position * new Vector2(FrameWidth, FrameHeight) - Screen.Camera, source, Color.White);
}
Index()方法只返回与char对应的块的框架索引。
我想知道我怎样才能让这样的事情发生,同时又不以这种方式杀死这位律师。我提供的代码显然不是很优化,还是我应该做一些具体的工作,以便在不降低性能的情况下绘制这么多单独的块呢?
发布于 2013-10-11 11:45:29
不确定这是否是处理这个问题的最佳方法,但我已经开始使用RenderTarget2D将世界上的各个部分预渲染成纹理。我必须一次在实际屏幕边界周围的给定区域内加载块,因为一次加载所有块将使其耗尽内存。
当您接近当前预渲染区域的边界时,它将根据您在世界上的新位置重新处理块。处理大约需要100毫秒,因此当加载新区域时,播放机在此期间会感觉到轻微的减速。我不太喜欢这个,但至少现在FPS是60岁了。
这是我的块处理器:
public bool ProcessChunk(int x, int y)
{
// Create render target
using (RenderTarget2D target = new RenderTarget2D(Game.CurrentDevice, 16 * 48, 16 * 48,
false, SurfaceFormat.Color, DepthFormat.Depth24))
{
// Set render target
Game.CurrentDevice.SetRenderTarget(target);
// Clear back buffer
Game.CurrentDevice.Clear(Color.Black * 0f);
// Begin drawing
Game.spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend);
// Get block coordinates
int bx = x * 48,
by = y * 48;
// Draw blocks
int count = 0;
foreach (WorldSection section in Sections)
{
// Continue if section is out of chunk bounds
if (section.X >= bx + 48) continue;
// Draw all tiles within the screen range
for (int ax = 0; ax < 48; ax++)
for (int ay = 0; ay < 48; ay++)
{
// Get the block character
char b = section.Blocks[ax + bx - section.X, ay + by];
// Draw the block unless it's an empty block
if (b != '0')
{
Processor.Blocks[b.ToString()].DrawBlock(new Vector2(ax, ay), true);
count++;
}
}
}
// End drawing
Game.spriteBatch.End();
// Clear target
target.GraphicsDevice.SetRenderTarget(null);
// Set texture
if (count > 0)
{
// Create texture
Chunks[x, y] = new Texture2D(Game.CurrentDevice, target.Width, target.Height, true, target.Format);
// Set data
Color[] data = new Color[target.Width * target.Height];
target.GetData<Color>(data);
Chunks[x, y].SetData<Color>(data);
// Return true
return true;
}
}
// Return false
return false;
}
如果有任何关于如何改进这种方法的建议,我不会为听到这些建议而难过!
谢谢你在这里的帮助!
https://stackoverflow.com/questions/19297508
复制相似问题