SDL TTF_RenderText_Blended会随机失败

7

编辑:尽管问题仍然存在,但我还没有能够经常重现它以更仔细地检查它。请参见问题结尾处的更多信息。


我是一名有用的助手,可以为您翻译文本。
我开始制作一个游戏,目前正在编写其基本库。我使用D编程语言与SDL-2和OpenGL 3(使用Derelict3绑定),在Linux Mint 13(Maya)上进行开发。编译器是DMD64 D编译器v2.067.1,每次都使用“rdmd”重新构建二进制文件。
为了呈现(更改)文本,我按需创建字形。我使用的代码片段如下:
class Font {
...

Texture render(char c) {
    if(!(c in rendered)) rendered[c] = texture(to!string(c));
    return rendered[c];
}

Texture texture(string text) {
    SDL_Color color={255, 255, 255, 255};

    auto bitmap = TTF_RenderText_Blended(
        font,
        std.string.toStringz(text),
        color
    );
    if(!bitmap) {
        throw new TTFError(
            "TTF_RenderText_Blended: " ~
            to!string(TTF_GetError()) ~ ": '" ~ text ~ "'"
        );
    }
    auto texture = new Texture(bitmap);
    SDL_FreeSurface(bitmap);
    return texture;
}

问题在于这种失败是纯随机的。有时候它可以毫无问题地工作。当它无法呈现字形时,有趣的是它会一次又一次地无法呈现相同的字形。以下是一个例子,当捕捉到我抛出的异常时:
...
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
...

我正在将分数打印到屏幕上,除了其中几个数字之外,其他数字都正常显示。TTF_RenderText_Blended无法渲染的数字因每次运行而异,并且有时会渲染所有数字,如前所述。
一个细节是,在进入游戏循环之前呈现的静态字符串尚未无法呈现,只有用于更改文本的单个字母。
我已经没有任何想法,并且在搜索网络时没有找到与此问题相关的任何内容。非常感谢任何寻找解决方案的想法。
当前情况:我已将编译器更新至DMD 2.067.1版本,但问题仍然存在(迄今为止使用的编译器版本为2.066.1和2.067.1)。整个项目组目前都在github上。

https://github.com/mkoskim/games

文本字形渲染函数位于此文件中:

https://github.com/mkoskim/games/blob/master/engine/ext/font.d

...并且它是从这里使用的:

https://github.com/mkoskim/games/blob/master/engine/ext/gui/label.d

问题主要/最常发生在吃豆人游戏中(尽管现在很少发生):

https://github.com/mkoskim/games/tree/master/testbench/pacman

如果您想尝试它,请先阅读(希望足够完整的)安装说明:

https://github.com/mkoskim/games/blob/master/INSTALL

该项目适用于64位Linux Mint Maya,目前在构建方面不够用户友好且不易移植。Pacman是唯一一个(有望)在没有游戏控制器的情况下工作的演示。成功安装所需的库和工具后,您可以使用以下命令构建它:
games/testbench/pacman$ make default

@AdamD.Ruppe,我已经尝试过类似的方法了。无论如何,我将代码更改为这样:if(!(c in rendered)) rendered[c] = texture(std.string.format(" %c ", c));,第一次测试运行给了我无尽的列表:...TTF_RenderText_Blended: Text has zero width: ' 7 '... - MaKo
@CyberShadow,我没有为此进行明确的测试,但是分数会像10、20、30等一样上升,因此代码按相同顺序创建数字。因此,在示例中,它已按顺序创建数字0、1、2、...、9,并未能呈现数字6和9。哪些字形失败纯属随机,但一旦失败,它们就会一直失败。我尝试明确地制作一个测试用例来测试该情况。 - MaKo
我无法理解这个... 我稍微修改了代码以查看哪些字形被渲染,哪些没有,但无法重现该情况。现在,即使将代码改回来也无法再次重现失败:o 我的小小猜测是这与SDL&TTF无关,而与编译器有关(我正在使用Linux DMD64 D Compiler v2.066.1,并使用rdmd进行编译)... 我将继续调查此案例。 - MaKo
你正在使用线程吗? - Vladimir Panteleev
这件事情真的让我抓狂。毫无明显原因,它有时候工作有时候不工作,而当我添加跟踪和捕获来解决问题时,它却停止了失败 D: 我现在正在将 GUI 元素(文本/字体密集代码)添加到我的基础库中,但是自己的异常引发的随机崩溃(尝试捕获时没有崩溃或其他情况),让我的生活非常痛苦。感觉在某些情况下,D 和 SDL-TTF-C 库不同意参数,也就是说,D 认为没问题,而底层(在这种情况下)的 libft 却不同意。 - MaKo
显示剩余11条评论
2个回答

3

我遇到了同样的问题,对我来说解决方法是保持用于创建字体(使用TTF_OpenFontRW)的SDL_RWops结构在整个TTF_Font生命周期内保持活动状态。我看到你也是使用TTF_OpenFontRW来创建字体,所以我认为这对你也会有所帮助。似乎SDL_ttf依赖于此保持活动状态,否则它会读取已释放的内存。


有趣!我需要在继续项目时尽快尝试一下! - MaKo
今天我成功复现了在SDL_ttf 2.20.0版本中出现的问题。尽管我们使用非零值来调用'TTF_OpenFontRW'函数中的freesrc参数,但它在调用后仍依赖于源SDL_RWops。如同您描述的那样,我现在会将它们和字体一起保留,只要我在使用它们,它就可以完美地运行。这可能是SDL_ttf文档中'freesrc'参数的一个错误或误解。 - Cee McSharpface

1

我知道这个问题有点过时,但我可能遇到了类似的问题。 我通过在使用TTF_Render_Text_Blended()之前简单调用SDL_DestroyTexture()来解决它:)


呵呵,老问题了,但并不过时 :) 感谢提示,我会在回到文本渲染时尝试它!我会尽力记得在这里更新此项目,但可悲的是许多事情已经改变了(SDL版本、编译器版本等等)。 - MaKo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接