我还有一个关于SDL2的问题。
我有一些drawSprite
& drawBackround
& drawText
函数,它们都是在屏幕上绘制的。他们通过创造一个新的表面,把它变成一个新的纹理,渲染纹理,然后破坏/释放一切。
这很好,直到我想把它放在一个非常快的循环。有一个轻微的延迟(或什么),这导致屏幕上的图像闪烁。(它会画背景,画精灵,画文字,然后循环。因此,这导致精灵闪烁。)
我查找了这个问题,发现您不应该创建和破坏每一个帧的纹理,AKA分配和释放每个帧的内存。所以,我创建了一些全局纹理和表面变量,目的是在每次调用绘图函数时重新分配这些变量,然后在程序结束时销毁它们。(减少、再利用、再循环!)
这是行不通的。我的程序所需要的记忆膨胀到千兆字节,这使得它完全没有反应。通过一些尝试和错误,我发现我仍然必须在每个绘图函数的末尾运行DestroyTexture和FreeSurface函数。我不明白这是为什么,因为我重复使用了变量。
无论如何,一旦我添加了这些返回,我发现我的程序是工作的,但在渲染比以前慢得多!这是为什么??我做错什么了?(再一次)
发布于 2018-01-05 10:16:23
您的drawSprite
和drawBackground
函数绝对不应该分配任何内存。你在它们里面做什么,需要你分配内存?
无论如何,我将首先解释手动内存管理是如何工作的。SDL_CreateTexture
& SDL_DestroyTexture
背后的功能非常类似于new
和delete
在C++中的工作方式。
让我们来做一个例子:
SDL_Texture* texture = SDL_CreateTexture(...);
在这里,我们创造了一个纹理。我们的程序中存在一种纹理。
SDL_DestroyTexture(texture);
在这里我们破坏了被创造的纹理。不再存在纹理。
现在让我们稍微改变一下:
texture = SDL_CreateTexture(...);
texture = SDL_CreateTexture(...);
这里我们创建了两个纹理,所以总共存在两个纹理。但是现在,如果我们调用SDL_DestroyTexture
,我们将只删除后者创建的纹理,因为这就是texture
所指向的!也无法访问第一个SDL_CreateTexture
调用的结果,因此我们有一个内存泄漏。一般规则是,每个SDL_DestroyTexture
必须有一个匹配的SDL_CreateTexture
调用。
现在,文本呈现有点棘手。文本呈现所需的纹理是相对频繁的变化,确实需要在呈现时创建。但是,没有必要在每一个帧中都这样做,因为不太可能只为一个框架呈现文本。
我个人使用LRU缓存在SDL中进行文本呈现。本质上,在文本呈现函数中,您检查缓存中是否存在具有相同颜色、文本和大小的项,如果存在,只需获取缓存项,并将其中的纹理混合到屏幕上。如果文本没有缓存项,则可以使用正确的TTF_*
调用来创建缓存项。这样,如果您在下一帧呈现相同的文本,就已经存在用于呈现的纹理。我们使用一个固定大小的LRU缓存,这样就不会导致内存泄漏。我想我在我的游戏中一次保存了200个缓存项。
作为最后一点,全球化绝对不是前进的道路。我不知道为什么要在最基本的sprite和背景渲染功能中分配内容,因为您可能应该将所需的纹理预加载到启动时使用它们的对象。
struct Sprite
{
float X, Y;
SDL_Texture* texture;
~Sprite() { SDL_DestroyTexture(texture); }
};
Sprite player { 0.0f, 0.0f, SDL_CreateTexture(...) };
while (runGame)
{
handleEvents();
updateStuff();
render(player);
}
从本质上说,这是给精灵用的。
https://gamedev.stackexchange.com/questions/152838
复制相似问题