使用SDL渲染文本的一种方法是使用扩展库SDL_ttf。SDL_ttf允许你从TrueType字体中创建图像,我们将在这里使用它从字体文本中创建纹理。
// 使用SDL、SDL_image、SDL_ttf、标准IO、math和string
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>
#include <string>
#include <cmath>
要使用 SDL_ttf,你必须设置 SDL_ttf 扩展库[1],就像你 设置 SDL_image一样。就像之前一样,只是把头文件、库文件和二进制文件放在正确的位置,并把编译器配置成使用它们。
//Texture wrapper class
class LTexture
{
public:
//Initializes variables
LTexture();
//Deallocates memory
~LTexture();
//Loads image at specified path
bool loadFromFile( std::string path );
//Creates image from font string
bool loadFromRenderedText( std::string textureText, SDL_Color textColor );
//Deallocates texture
void free();
//Set color modulation
void setColor( Uint8 red, Uint8 green, Uint8 blue );
//Set blending
void setBlendMode( SDL_BlendMode blending );
//Set alpha modulation
void setAlpha( Uint8 alpha );
//Renders texture at given point
void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
//Gets image dimensions
int getWidth();
int getHeight();
private:
//The actual hardware texture
SDL_Texture* mTexture;
//Image dimensions
int mWidth;
int mHeight;
};
在这里,我们在texture class中添加了另一个函数,叫做loadFromRenderedText。SDL_ttf的工作方式是从字体和颜色中创建一个新的图像。对于我们的纹理类来说,这意味着我们将从SDL_ttf渲染文本而不是从文件中加载图像。
//我们要渲染的窗口
SDL_Window* gWindow = NULL;
//窗口渲染器
SDL_Renderer* gRenderer = NULL;
//全局通用的字体
TTF_Font *gFont = NULL;
//渲染纹理
LTexture gTextTexture;
在本教程和未来的教程中,我们将使用全局字体进行文本渲染。在SDL_ttf中,字体的数据类型是TTF_Font。
我们还有一个纹理,它将由字体生成。
bool LTexture::loadFromRenderedText( std::string textureText, SDL_Color textColor ){
//释放已有的纹理
free();
//渲染文本表面
SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
if( textSurface == NULL ){
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}else{
//从表面像素创建纹理
mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( mTexture == NULL ){
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
}else{
//Get image dimensions
mWidth = textSurface->w;
mHeight = textSurface->h;
}
//释放旧表面
SDL_FreeSurface( textSurface );
}
//Return success
return mTexture != NULL;
}
这里是我们实际创建文本纹理的地方,我们将从字体中渲染。这个函数接收我们想要渲染的文本字符串和我们想要用来渲染它的颜色。之后,这个函数的工作原理和从文件中加载文字的工作原理差不多,只是这次我们使用的是SDL_ttf创建的SDL_Surface而不是文件。
在释放任何预存在的纹理后,我们使用 TTF_RenderText_Solid[2] 加载一个表面。这将从给定的字体、文本和颜色中创建一个纯色表面。如果表面创建成功,我们将从中创建一个纹理,就像之前从文件中加载表面时一样。在创建纹理后,我们可以像其他纹理一样用它进行渲染。
还有其他方法可以渲染出更平滑或混合的文本。实验一下SDL_ttf文档[3]中概述的不同类型的渲染。Shaded
/Blended
渲染可能对不同大小的文本效果更好。
//初始化PNG加载
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) ){
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
//初始化 SDL_ttf
if( TTF_Init() == -1 ){
printf( "SDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
就像SDL_image一样,我们必须对它进行初始化,否则字体加载和渲染功能将无法正常工作。我们使用TTF_init[4]来启动SDL_ttf。我们可以使用TTF_GetError()来检查错误。
bool loadMedia(){
//Loading success flag
bool success = true;
//Open the font
gFont = TTF_OpenFont( "16_true_type_fonts/lazy.ttf", 28 );
if( gFont == NULL ){
printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}else{
//Render text
SDL_Color textColor = { 0, 0, 0 };
if( !gTextTexture.loadFromRenderedText( "The quick brown fox jumps over the lazy dog", textColor ) ){
printf( "Failed to render text texture!\n" );
success = false;
}
}
return success;
}
在我们的加载函数中,使用TTF_OpenFont[5]加载字体。这需要字体文件的路径和我们想要渲染的点大小。
如果字体加载成功,我们要使用加载方法加载一个文本纹理。作为一般规则,你要尽量减少渲染文本的次数。只有在需要的时候才重新渲染,由于我们在整个程序中使用的是同一个文本表面,所以我们只想渲染一次。
void close(){
//Free loaded images
gTextTexture.free();
//Free global font
TTF_CloseFont( gFont );
gFont = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
TTF_Quit();
IMG_Quit();
SDL_Quit();
}
在我们的清理函数中,希望使用TTF_CloseFont[6]来释放字体。我们还想使用TTF_Quit[7]来退出SDL_ttf库,以完成清理工作。
//While application is running
while( !quit ){
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 ){
//User requests quit
if( e.type == SDL_QUIT ){
quit = true;
}
}
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render current frame
gTextTexture.render( ( SCREEN_WIDTH - gTextTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gTextTexture.getHeight() ) / 2 );
//Update screen
SDL_RenderPresent( gRenderer );
}
正如你所看到的,在我们渲染了文本纹理之后,我们可以像其他纹理一样渲染它。
在 这里[8]下载本教程的媒体和源代码。
原文链接[9]
[1]
SDL_ttf 扩展库: http://www.libsdl.org/projects/SDL_ttf/
[2]
TTF_RenderText_Solid: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_43.html
[3]
SDL_ttf文档: http://www.libsdl.org/projects/docs/SDL_ttf/SDL_ttf_35.html
[4]
TTF_init: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_8.html
[5]
TTF_OpenFont: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_14.html
[6]
TTF_CloseFont: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_18.html
[7]
TTF_Quit: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_10.html
[8]
这里: http://www.lazyfoo.net/tutorials/SDL/16_true_type_fonts/16_true_type_fonts.zip
[9]
原文链接: http://www.lazyfoo.net/tutorials/SDL/16_true_type_fonts/index.php
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有