本章内容我们来讲解一下绘制图像的具体方法,上一篇文章中我们讲了SDL 渲染设备相关的知识,这一篇是在前文的基础之上,因为所有图像显示相关的接口,都需要用到上篇文章中提到的渲染器,也就是 SDL_Renderer 结构体。接下来的内容分为两个部分,主要介绍游戏中经常用到的两个功能,图形渲染和文字渲染。

1. 图形渲染

我们都知道游戏中最常用到的就是图形渲染,简单地说就是将图像显示到屏幕上。图像在 SDL 中被封装为一个叫做纹理的结构体 SDL_Texture,它代表了所有像素相关的内容数据。我们要想在程序中显示图像,首先要先将图像转化为纹理结构才可以。

SDL 中提供了 SDL_CreateTexture 和 SDL_DestoryTexture 来创建和销毁纹理,但是在现实中,很少从头创建一个新纹理,一般情况都是从硬盘上直接加载相关的图片转换为纹理结构体。SDL 也提供了相关的函数:

SDL_Surface* SDL_LoadBMP(const char* file)

这个函数可以从本地磁盘上加载一个位图图片,不过这里有两个重点需要提及:

  • 文件只能是位图图片,也就是常见以 bmp 后缀的图片文件。
  • 函数返回的并不是 SDL_Texture 结构体指针,而是另一种叫做 SDL_Surface 结构体的指针对象。

之所以该接口只支持位图是因为位图图像的格式比较简单,并不涉及图片压缩编码之类的操作,图片数据只是按照一定格式对像素的简单排列,这也是为什么位图图片相比于其它图片要大上很多的原因。如果你想支持其它的图片格式,可以使用 SDL 扩展库 SDL2_Image

再说一下为什么返回的不是 SDL_Texture 结构体。因为在大多的图形引擎里面都存在着一种概念,就是纹理。纹理可以说是一种最接近显示层的结构,它本身支持硬件加速,但是对图形有一定的要求,例如图形的宽高最好是 2 的 n 次方等等。但是现实中产生纹理的图片一般都是保存到硬盘上,所以在让图片按照规定要求转换为纹理的时候,存在着一种中间的状态,这个在 SDL 中用 SDL_Surface 结构体表示,这个结构体相关的数据都保存到内存中,大多不支持硬件加速,对图片的规格没有任何要求,它内部主要保存着图片的所有信息,特别是像素相关的数据。

所以用 SDL 显示图像前,你需要先将图片加载到内容,保存为 SDL_Surface 结构体,然后在转换为支持硬件加速的纹理结构体 SDL_Texture,最后在通过拷贝操作,将纹理数据暂存到后台缓冲中。整个过程的代码如下:

SDL_Surface* bmp = SDL_LoadBMP("test.bmp");
SDL_Texture* tex = SDL_CreateTextureFromSurface(pRenderer, bmp);
SDL_RenderCopy(pRenderer, tex, NULL, NULL);
SDL_FreeSurface(bmp);
SDL_DestroyTexture(tex);

程序中首先使用 SDL_LoadBMP 函数加载测试图片,然后通过 SDL_CreateTextureFromSurface 函数转化为纹理,接着使用 SDL_RenderCopy 将纹理拷贝到后台缓冲中,最后在使用完毕后释放相关资源。

在 SDL 中所有的图片显示流程基本都是类似的方式,这里面 SDL_RenderCopy 的函数原型如下:

int SDL_RenderCopy(SDL_Renderer*   renderer,
                   SDL_Texture*    texture,
                   const SDL_Rect* srcrect,
                   const SDL_Rect* dstrect)

函数的前两个参数分别是渲染器的指针和纹理指针,后两个参数前者 srcrect 简单的说就是在纹理上想要显示的坐标范围,而 dstrect 可以认为是显示窗口的坐标范围。如果二者不相同,SDL 默认会自动缩放。如果传递 NULL 指针,则会根据当对象的大小来替代,对纹理来说就是整个纹理的大小,对于显示窗口就是整个窗口的大小。

2. 文字渲染

文字渲染和图像渲染本质上是一样的,渲染文字之前已经先将文字转化为纹理,然后在通过绘制图片的方式绘制文字。SDL 默认是不支持文字渲染的,但是官方的扩展库 SDL_ttf 支持文字的渲染。该库支持 TrueType 字体渲染,TrueType 字体就是我们常用的 ttf 为后缀的字体,直接在 Windows 的字体文件夹下就可以找到。

找到合适的字体之后,接下来先用 TTF_OpenFont 打开字体,接着用 TTF_RenderText_Blended 函数将文字转换为 SDL_Surface 结构体,后面的步骤就和显示图片步骤完全一致了。

具体代码如下:

SDL_Color color = { 255, 255, 255, 255 };
TTF_Font* font = TTF_OpenFont("DS-DIGIB.TTF", 18);
SDL_Surface* surf = TTF_RenderText_Blended(font, "are you OK ?", color);
SDL_Texture* ftex = SDL_CreateTextureFromSurface(pRenderer, surf);
SDL_RenderCopy(pRenderer, ftex, NULL, NULL);
SDL_FreeSurface(surf);
SDL_DestroyTexture(ftex);

这里需要注意,在使用 SDL_ttf 字体库之前,需要执行和 SDL 库类似的初始化操作,函数名称叫做 TTF_Init,和其相对应的同样有一个 TTF_Quit 函数负责清理收尾。

3. 总结

到此为止,SDL 中简单的图像渲染内容就算介绍完毕了,熟练使用上面提到的 API,已经可以让你足以应付大部分游戏中的图像显示问题,下一篇我们来介绍在游戏中如何使用 SDL 播放音频文件,以及和直接使用 Windows 自带的音频 API 接口的不同之处,欢迎大家继续观看。