系列文章目录
SDL2 简明教程(一):使用 Cmake 和 Conan 构建 SDL2 编程环境
在窗口显示图片
在 SDL2 简明教程(二):创建一个空的窗口 中我们已经学会如何创建一个窗口,今天在其基础上更进一步,我们将在窗口上显示一张图片,首先回顾下创建空窗口的代码:
#if defined(__cplusplus)
extern "C" {
#endif
#include <SDL.h>
#if defined(__cplusplus)
};
#endif
int main(int argc, char *argv[]) {
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *screen = SDL_CreateWindow("My SDL Empty window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, 0);
for (; !quit;) {
SDL_WaitEvent(&event);
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
}
}
}
SDL_Quit();
return 0;
}
接着,创建一个 SDL_Renderer
:
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
SDL_CreateRenderer
创建一个 SDL_Renderer
实例,这个 render 表示绘制的输出设备(通常就是你的显卡)。事实上,它是我们图像的最终目的地,因为我们将按照下面的步骤进行:
SDL_CreateRenderer()
需要三个参数。第一个是我们正在绘制的窗口。第二个参数允许我们选择不同的渲染驱动;在我们的例子中,我们并不关心,我们可以把它设置为 -1,然后得到默认的驱动。最后一个参数允许我们设置 SDL_RendererFlags
来控制渲染的发生方式。我们可以把它设置为 0,默认为硬件渲染。如果这些听起来很混乱,不用担心,就像这里一样使用SDL_CreateRenderer()
。
现在我们可以使用 SDL_LoadBMP()
载入一张 BMP 图片,并将其加载到 SDL_Surface
中:
SDL_Surface * image = SDL_LoadBMP("image.bmp");
测试图片大小为 320*240,你可以在代码仓库中的 res 文件夹下找到
接着,我们需要创建一个 texture(纹理):
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, image);
一个 texture 其实就是一块靠近显卡的内存,通过 SDL_CreateTextureFromSurface()
将 surface 映射到 texture 上。Surface 和 texture 的关系如下图:
现在让我们在窗口上显示这个 texture。在 for 循环代码末尾处,添加如下代码:
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_RenderCopy
将 texture 拷贝到 render(输出设备)中;SDL_RenderPresent
将 texture 提交至视频内存,并显示它。
记得清理我们初始化过的每一个资源,你需要在 SDL_Quit()
前添加如下内容:
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
运行你的程序,你会看到窗口中显示了一张图片:
非常神奇!图片真的在窗口中显示出来了,但你会发现这图片似乎不太清晰,这是因为图片大小是 320240 ,但窗口大小是 640480,窗口自动将图片做了拉伸填满了整个窗口。为了让图片看起来不这么模糊,我们可以指定显示区域的位置和大小:
SDL_Rect dstrect = { 5, 5, 320, 240 };
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_RenderCopy
最后一个参数定义的显示区域,如果它是 NULL 的话,图片将被拉伸填充。
指定好显示区域后,运行代码,图片将被显示在某个区域而不是平铺在整个窗口:
总结
在这篇文章中,我们研究了如何创建渲染器、表面和纹理。我们用这些来加载位图并在屏幕上显示它们。我们还看到了将图像复制到窗口的某个区域,和使其填满整个窗口之间的区别。
本文源码你可以在 sdl2_tutorial 找到。