SDL 2.0课程周期:第6课-使用SDL_ttf下载字体

图片

来自翻译者:

这是Twinklebear教程系列翻译的延续,可在此处获得该翻译是部分免费的,可能包含翻译的少量修改或补充。前两节课的翻译-作者身份无效指针第三和第四 k1-801


课程清单:


使用SDL_ttf下载字体


在本教程中,我们将学习如何使用SDL_ttf扩展库显示True Type字体。安装该库与在第3课中设置SDL_image相同,但是我们只需写“ ttf”(而不是“ image”)(Windows用户还应复制包含的freetype dll)。因此,下载SDL_ttf,查看文档并开始教程!

我们需要使用SDL_ttf的第一件事是ttf字体。使用BitFontMaker,作者制作了一种非常糟糕的字体,您可以从存储库中下载该字体。但是如果您已经拥有自己漂亮的字体,则可以使用它。该字体仅提供简单的ASCII字符,因此,如果您尝试显示非ASCII字符,则很可能不会成功。本课程的代码将基于第5课编写,通常您可以从Github下载图像,切片的精灵和绘图将在本教程中进行更改。

显示文字


SDL_ttf提供了几种显示各种速度和质量的字体的方法,以及显示UTF8和Unicode字符的能力。该文档很好地概述了各种显示方法,因此您应该阅读和了解它们,以及何时,根据质量和速度要求使用哪种方法。在本教程中,我们将使用TTF_RenderText_Blended,因为我们没有时间限制,并且希望我们的文本漂亮。各种文本显示功能都接受RGB SDL_Color color,我们可以使用它来选择要绘制的文本的颜色。

不幸的是,SDL_ttf只能显示在表面上,因此,在渲染文本之后,您必须执行一个附加步骤以从中创建纹理,我们可以使用渲染器进行绘制。当然,您仍然需要下载我们将使用的字体,这是使用TTF_OpenFont完成的,您还可以在其中指定所需的字体大小。

编写renderText函数


为了使我们的生活更轻松,我们将创建一个renderText函数,该函数将接收文本,包含TTF字体,颜色,所需大小和渲染器的文件,以加载最终纹理。该函数打开字体,显示文本,将其转换为纹理并返回纹理。由于可能会出现问题,因此您需要检查每个库调用是否有错误并正确处理它们,例如,清理资源,记录错误并返回nullptr,以便我们知道发生了一些不良情况。SDL_ttf通过SDL_GetError报告其所有错误,因此您可以继续使用logSDLError记录错误。

牢记这些要求,让我们编写renderText函数:

/**
*      
* @param message ,   
* @param fontFile ,   
* @param color ,     
* @param fontSize  
* @param renderer ,     
* @return SDL_Texture,     nullptr,  -   
*/
SDL_Texture* renderText(const std::string &message, const std::string &fontFile,
        SDL_Color color, int fontSize, SDL_Renderer *renderer)
{
        // 
        TTF_Font *font = TTF_OpenFont(fontFile.c_str(), fontSize);
        if (font == nullptr){
                logSDLError(std::cout, "TTF_OpenFont");
                return nullptr;
        }       
        //       TTF_RenderText,
        //    
        SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
        if (surf == nullptr){
                TTF_CloseFont(font);
                logSDLError(std::cout, "TTF_RenderText");
                return nullptr;
        }
        SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
        if (texture == nullptr){
                logSDLError(std::cout, "CreateTexture");
        }
        //   
        SDL_FreeSurface(surf);
        TTF_CloseFont(font);
        return texture;
}

性能警告


需要特别注意的是,每次我们要显示文本时,都需要重新打开和关闭字体,这对我们来说是合适的,因为我们只显示一次文本,但是如果我们要显示很多文本和/或过于频繁地显示,那么最好保持字体根据需要打开。对于这种更常见的情况,我们的renderText版本将接受TTF_Font *而不是字体文件的名称,并且不会打开和关闭,因为字体文件的寿命将单独调整。

初始化SDL_ttf


与SDL一样,我们需要在使用库之前对其进行初始化。这是使用TTF_Init完成的,如果成功,它将返回0。要初始化SDL_ttf,我们仅在初始化SDL之后调用此函数,并检查返回值以确保一切正常。

if (TTF_Init() != 0){
        logSDLError(std::cout, "TTF_Init");
        SDL_Quit();
        return 1;
}

使用renderText


使用我们方便的renderText函数,我们可以在一个简单的调用中显示文本。对于本教程,显示文本“ TTF字体很棒!” 白色,我们之前下载的字体大小为64。然后,我们可以像请求其他任何纹理一样请求宽度和高度,并计算x / y坐标以在窗口中心绘制一条消息。

const std::string resPath = getResourcePath("Lesson6");
//   "TTF fonts are cool!"
//   RGBA
SDL_Color color = { 255, 255, 255, 255 };
SDL_Texture *image = renderText("TTF fonts are cool!", resPath + "sample.ttf",
        color, 64, renderer);
if (image == nullptr){
        cleanup(renderer, window);
        TTF_Quit();
        SDL_Quit();
        return 1;
}
//    ,     
int iW, iH;
SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
int x = SCREEN_WIDTH / 2 - iW / 2;
int y = SCREEN_HEIGHT / 2 - iH / 2;

画文字


最后,我们可以像使用renderTexture函数之前那样绘制纹理。

//:     
SDL_RenderClear(renderer);
//    ,     ,  
//    
renderTexture(image, renderer, x, y);
SDL_RenderPresent(renderer);

如果一切按计划进行,您将看到类似以下内容:

图片

第6课结束


这就是开始使用SDL_ttf所需的全部知识!请务必查看文档以查看该库的功能。与往常一样,如果您对本课有疑问,可以在评论中写。

作者开始忙于其他项目,不能再写课程了,所以这是该周期的最后一课。您可以观看Lazy Foo的教程,或从SDL Wiki阅读示例和文档

All Articles