SDL_第二课 优化表面的加载和Blit

时间:2022-09-07 12:05:12

SDL中文教程:http://tjumyk.github.io/sdl-tutorial-cn/contents.html

第二课:http://tjumyk.github.io/sdl-tutorial-cn/lessons/lesson02/index.html


SDL_第二课 优化表面的加载和Blit


这课的主要内容是改用更高效的方法加载表面和Blit。

Blit的含义是内存中图像的位块传输,指的是将某一表面的全部或部分图像复制到另一表面上。

代码首先用SDL_LoadBMP(filename.c_str())加载了图像,但是这个图像不能立即使用,因为这个位图是24位色的,而窗口是32位色的, 将一个表面blit到另一个不同格式的表面上不是一个好主意,因为这样SDL会在每次blit时做一次临时性的格式转换,这会导致程序的运行效率降低。

因而这是就需要用到SDL_DisplayFormat()函数,之所以这么做,是因为当你尝试将一个表面粘贴到另一个不同格式的表面时,SDL会自动转换它的格式,使它们具有相同的格式。

而在每次blit时都创建一个转换后的表面会浪费机器的处理能力并降低程序运行速度。由于我们在加载表面时就已经将其格式转换好了,所以当你要将此表面应用到窗口上时,它已经与窗口具有相同格式,那么SDL就不必进行临时的格式转换了。

注意:旧的加载得到的表面和新的优化处理后的表面都存在,注意事后要及时释放它们。


接着就是一些图片显示的坐标问题,留意是左上角为原点就行了

SDL_第二课 优化表面的加载和Blit


补充:std::string是C++的String,如果您不了解C++,也可以使用C的String,即char*char数组。下面代码中用到的filename.c_str()是C++ String的取指针操作,返回类型为char*,指向字符串首字符地址,即可理解为C++ String转C String,所以这里用哪种String都没问题。


笔记:

下面这些函数都是第一课见过的,就再简单说说当做复习吧

SDL_LoadBMP():加载BMP图片
SDL_FreeSurface():释放掉图片所占的空间

SDL_Init():初始化SDL的子系统

SDL_SetVideoMode():设置窗口的参数

SDL_Delay():设置几秒后关闭

SDL_Quit():退出SDL系统


下面的就是这课的新东西

SDL_Rect:SDL的坐标类
SDL_WM_SetCaption("Hello World",NULL):设置窗口标题,如果显示窗口时出现了问题,screen会被设为NULL。

SDL_DisplayFormat():创建一个优化了格式的图像

SDL_BlitSurface(source,NULL,destination,&offset):第四个参数是设置把图放到的坐标位置


//头文件
#include"SDL.h"
#include<string>

//窗口属性
const int SCREEN_WIDTH=640;
const int SCREEN_HEIGHT=480;
const int SCREEN_BPP=32;

//将要使用的表面
SDL_Surface *message=NULL; //一张写着字样的图片
SDL_Surface *background=NULL; //背景图片
SDL_Surface *screen=NULL; //程序窗口


SDL_Surface *load_image( std::string filename)
{
//临时的空间,用于存储刚刚加载好的图像
SDL_Surface *loadedImage=NULL;

//优化后的图像,实际使用的是这个图像
SDL_Surface *optimizedImage=NULL;

//加载图像
loadedImage=SDL_LoadBMP(filename.c_str());

//如果加载图片没有出错
if(loadedImage!=NULL)
{
//创建一个优化了的图像
optimizedImage = SDL_DisplayFormat(loadedImage);
//释放临时的图像
SDL_FreeSurface(loadedImage);
}
//返回优化后的表面
return optimizedImage;
}

void apply_surface(int x,int y, SDL_Surface *source, SDL_Surface *destination)
{
//新建一个临时的矩形来保存偏移量
SDL_Rect offset;
//将传入的偏移量保存到矩形中
offset.x=x;
offset.y=y;
//执行表面的Blit
SDL_BlitSurface(source,NULL,destination,&offset);
}

int main(int arge, char *args[])
{
//初始化SDL的所有子系统
if(SDL_Init(SDL_INIT_EVERYTHING)==-1)
return -1;

//设置窗口
screen=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE);

//如果设置窗口时出现错误
if(screen==NULL)
return 1;

//设置窗口标题
SDL_WM_SetCaption("Hello World",NULL);

//加载图片
message=load_image("hello1.bmp");
background=load_image("background.bmp");

//将背景图片background应用到screen上
apply_surface(0,0,background,screen);
apply_surface(320,0,background,screen);
apply_surface(0,240,background,screen);
apply_surface(320,240,background,screen);

//将message表面应用到窗口中
apply_surface(180,140,message,screen);

//更新窗口
if(SDL_Flip(screen)==-1)
return 1;

//等待3秒
SDL_Delay(3000);
//释放表面
SDL_FreeSurface(message);
SDL_FreeSurface(background);
//退出SDL
SDL_Quit();

//main函数返回
return 0;
}