gpt4 book ai didi

c# - 如何在不杀死FPS的情况下绘制数千个瓷砖

转载 作者:太空宇宙 更新时间:2023-11-03 16:06:08 31 4
gpt4 key购买 nike

我到处寻找解决此问题的方法(我可能只是盲目地看到周围的解决方案)。我的游戏目前在屏幕上渲染瓦片 map ,不会渲染实际上不在屏幕边界内的瓦片。但是,每个图 block 都是 16x16 像素,这意味着如果屏幕上的每个像素都包含一个分辨率为 1920x1080 的图 block ,则需要绘制 8100 个图 block 。

每个周期绘制那么多图 block 真的会扼杀我的 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 个部分。每个图 block 由二维数组中的一个 char 对象表示。

画 block 方法:

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() 方法只返回与字符对应的图 block 的帧索引。

我想知道如何在不以这种方式降低帧速率的情况下真正允许一次绘制这么多内容。我提供的代码显然不是很优化,还是我应该做一些具体的事情才能在不降低性能的情况下绘制这么多单独的图 block ?

最佳答案

不确定这是否是解决问题的最佳方法,但我已经开始使用 RenderTarget2D 将世界的 block 预渲染到纹理中。我必须一次加载实际屏幕边界周围给定区域内的 block ,因为一次加载所有 block 会耗尽内存。

当您接近当前预渲染区域的边界时,它会根据您在世界中的新位置重新处理区 block 。处理过程大约需要 100 毫秒,因此在加载新区域时,玩家在此期间会感觉速度略有下降。我不太喜欢这样,但至少 FPS 现在是 60。

这是我的 block 处理器:

    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;
}

如果有任何关于如何改进这种方法的建议,我不会感到难过!

在此感谢您的帮助!

关于c# - 如何在不杀死FPS的情况下绘制数千个瓷砖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19297508/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com