SDL 2课:第4课-拉伸PNG

大家好! 这是SDL 2中的第四节课。我决定将这两节课合并为一个,因为在最初的时候它们很小。 但是可以在这里这里找到它们。 好,让我们开始上课。

首先,我们将决定我们将做什么。 今天,我们将学习如何上传另一个扩展程序(不是BMP)的图像,即:PNG。 以其他格式重做图像,以加快工作速度并调整图像大小。 我们将使用此图像:

图片

安装方式


因此,首先我们学习如何下载PNG。 标准SDL 2功能集不会加载非BMP格式的图像。 要下载其他格式,您需要安装扩展程序。

以下是说明:

窗户
您可以转到此页面并从“ 开发库”部分下载ZIP或TAR.GZ归档。 解压缩并将它们放入编译器的文件夹中。

的Linux
如果您的系统使用Debian,则需要输入以下命令:

apt-cache search libsdl2-image apt-get install libsdl2-image-dev 

如果使用“ Yellowdog Updater,Modified”,则输入以下命令:

 yum search SDL2_image-devel yum  SDL2_image-devel 


Mac OS
下载DMG文件并阅读自述文件。

编写代码


设置SDL_image之后,我们开始编写代码。 首先,与往常一样,连接库,设置窗口大小并创建3个全局变量。

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; 

请注意,我单独连接了SDL_image.h ,因为它是一个单独的库。

接下来,我们编写3个众所周知的函数,像往常一样在其中添加和更改某些内容。

初始化()
 bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } 


在这里,我们添加了SDL_image模块的初始化。 要初始化它,首先创建一个int变量,我们有flags ,然后将要用于初始化的所有标志保存在那里。

所有标志列表
SDL_INIT_PNG-初始化PNG图像下载器;
SDL_INIT_JPG-初始化JPG图像下载器;
SDL_INIT_TIF-初始化TIF图像下载器;

接下来,我们编写此条件:

 if ( !( IMG_Init( flags ) & flags ) ) 

IMG_Init()函数返回它能够初始化的标志。 如果她返回了这些标志,但是我们想要的那个标志丢失了,我们将返回一个错误。 很简单 另外,请注意,我使用IMG_GetError而不是SDL_GetError ,因为我们正在寻找SDL_image模块而不是SDL函数的错误。

我还想指出,我决定使用布尔类型返回 a-这是一种更合理的方法。

让我们继续编写程序,编写Load()函数,在其中加载PNG图像并进行转换。

负荷
 bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } 


在这里,我们使用新的IMG_Load函数上传图像。 它的功能与SDL_LoadBMP的功能相同,并且结果相同-它返回SDL_Surface类的实例。 为了在加载期间发现错误,我们还使用了IMG_GetError

现在该转换了。 首先,一点理论。 很少有人知道,但是在下载图像时,它以24位格式下载,大多数现代显示器都是32位格式。 每次我们在屏幕上显示图像时,都会首先重做32位格式。 对于简单程序,这无关紧要,但是在创建某种大型项目时,它将极大地影响性能,因此我们会采用它,在下载图像的阶段,我们将以显示格式重新制作它们。 SDL_ConvertSurface函数将有所帮助。 它包含3个值:我们要设置格式的表面,我们要设置格式的表面以及标志。 我们要格式化花朵图像,将其传递给第一个参数。 第二个参数是窗口表面的格式,我们将不使用标志。 此函数返回表面的副本,我们立即将其分配给flower 。 为了发现错误,我们采用SDL_GetError()函数, 因为我们已经在使用曲面,它们来自SDL ,而不是来自SDL_image

接下来,我们编写Quit函数,仅向其中添加一个函数。

退出
 void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } 


我们添加了IMG_Quit取消初始化SDL_image模块。

主要的


现在,最简单的事情仍然存在- 主要功能。

 int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } 

首先,请初始化并创建所需的所有内容,然后上传必要的文件。 我们不会在这里停止。

  SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; 

之后,创建一个类SDL_Rect的对象。 我们将需要它来拉伸图像。 如果您注意到,花朵图像比窗口大小小4倍(变薄2倍,变小2倍),我们需要将其拉伸到窗口大小。 因此,在矩形的宽度bg_flower中,写入窗口宽度的值,并在高度中输入窗口的高度。 将坐标设置为0,以便图像显示在左上角。

要显示调整大小的图像,有一项特殊功能。 看起来像这样:

  SDL_BlitScaled(flower, NULL, scr, &bg_flower); 

它有4个含义。 第一个是我们要显示的图像,第二个是我们要从该图像切出的矩形(如果要拍摄整个图像,我们将其写为NULL),第三个是要在其上显示图像的表面,第四个是相同的矩形,尺寸以及我们用来拉伸或压缩并显示图像的坐标。

接下来,只需更新屏幕表面,设置延迟,退出并返回0。

  SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

这是我们程序结束的地方。 为了编译这个奇迹,您需要添加-lSDL2_image作为另一个编译选项。

至此,我们将今天结束。 这是我们得到的代码:

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; SDL_BlitScaled(flower, NULL, scr, &bg_flower); SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

再见!

<<上一课|| 下一课>>

Source: https://habr.com/ru/post/zh-CN456656/


All Articles