上一次我们建立起了SDL环境,接下来,我们谈一谈什么是SDL?如何起动和退出SDL.

  Simple DirectMedia Layer库,简称SDL,它是一个跨平台的多媒体库,以用于直接控制底层的多媒体硬件的接口。这些多媒体功能包括了视频、音频、键盘和鼠标(事件)、游戏摇杆等。当然,最为重要的是提供了2D图形帧缓冲(framebuffer)的接口,以及为OpenGL与各种操作系统之间提供了统一的标准接口以实现3D图形。也就是说我们通过这个图形库可以自己写游戏,播放电影、歌曲等等,哪些C语言基本库里无法完成的任务,我们可以通过SDL的库完成,只要按上一次的要求安装完了SDL,我们就可以自由的使用SDL完成自己想要完成的功能!

  SDL是一个跨平台的库,它支持: Windows, Windows CE,Linux, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX,QNX

  SDL是用C语言开发的,但它对C++支持的更好!所以你在网上可以找到很多SDL源代码都是C++写的。除了这两种语言,SDL还支持:Java,C#, D,PHP,Eiffel, Erlang, Python,Euphoria, Ada, Go,Guile, Haskell,  Lisp, Lua, ML, Objective C, Pascal, Perl,  Pike, Pliant,  Ruby, Smalltalk, and Tcl.几乎支持所有当下流行的语言!

  为什么选择SDL做图形库而不是DirectX、OpenGl等著名的图形库呢?第一,SDl是免费的,它能够完成绝大多数哪些大的图形库的功能,但你可以随意使用不需要付费,而且它是跨平台的,可以在多种平台上使用。第二,SDL小巧精悍,接口简单,向用户隐蔽了复杂的操作,用户只需要懂一点C语言的基础知识就可以调用它完成很炫的功能。换句话说SDL使你的编程工作变得简单容易,而完成同样的功能DirectX代码量最少是SDL的5到6倍!那么你现在是不是觉得对于一个编程新手来说,SDL是最佳选择!

  本系列教程是写给C编程的入门者或对C语言情有独钟者!所有代码均用C语言实现,用C语言也可以实现很酷的功能!

  下面我们看一下如何调用SDL的库函数完成相应的功能,还以上次安装教程里的代码为例。

#include 
#include 
#include 
SDL_Surface *gpScreen;
   
int main(int argc,char *argv[])
{
     if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) {
         exit(-1);
     }
   
    gpScreen = SDL_SetVideoMode(600,600, 0, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF );
    if( NULL == gpScreen ) {
       SDL_Quit();
       return -1;
    }
   
   SDL_Delay(3000);
   SDL_FreeSurface(gpScreen);//退出程序前必须释放
   SDL_Quit();//关闭SDL各个子系统
   system("pause");
   return 0;
}
      首先要使用SDL必须加载SDL.h头文件,再者主函数的写法必须是int main(int argc,char *argv[]),不能是int main(void),否则会报编译错误。

  要使用SDL,必须先初始化SDL,函数int SDL_Init(Uint32 flags),参数flags是一个无符号整数,表示要初始化SDL哪些子系统。  

表2.1 SDL各个子系统
名称  常量 说明 自动初始化

定时器

SDL_INIT_TIMER   0x00000001 初始化时间子系统

音频

SDL_INIT_AUDIO   0x00000010 初始化音频子系统

视频

SDL_INIT_VIDEO 0x00000020 初始化视频子系统

CDROM

SDL_INIT_CDROM   0x00000100 初始化CDROM子系统

游戏杆

SDL_INIT_JOYSTICK 0x00000200 初始化JOYSTICK子系统

错误捕获

SDL_INIT_NOPARACHUTE 0x00100000 避免捕获致命错误

线程

SDL_INIT_EVENTTHREAD 0x01000000 初始化线程子系统

全部子系统

SDL_INIT_EVERYTHING 0x0000FFFF 初始化上述所有子系统

  SDL_Init()函数初始化成功返回0。如果初始化失败,函数返回值为-1。函数只接受各个子系统的常量作为参数。如果要初始化视频屏幕,传入常数SDL_INIT_VIDEO作为参数;初始化音频,传入常数SDL_INIT_AUDIO;如果同时初始化视频和音频,传入SDL_INIT_VIDEO|SDL_INIT_AUDIO。如果同时传入多个量要使用|将它们隔开:  

1if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 )2{3  printf(“Unable to init SDL: %s\n”, SDL_GetError());4return1;5 } 

  初始化失败,要直接退出程序,不能使用SDL了,其中SDL_GetError函数是返回SDL的错误,其原型是:char *SDL_GetError(void);其返回值是一个字符串。

  初始化完成后,你就可以使用相应SDL子系统完成相应的任务了,当你完成所有工作需要退出程序时,必须关闭相应SDL子系统并做相关清理工作,完成这项工作可以调用void SDL_Quit(void);函数完成关闭SDL。一般可以这样写:

....//初始化SDL
SDL_InitSDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);//添加自己的处理代码.....SDL_Quit();......

  记住退出程序之前必须调用这个函数关闭SDL,如果你的代码里有多个地方写exit函数结束程序或return 0结束程序则必须在这些语句前调用SDL_Quit()函数。一般这种情况我们使用另外一个函数来关闭SDL:atexit(SDL_Quit); atexit(void (__cdecl *func )( void ))是C语言标准库里的函数,从函数名atexit可以看出这个函数是在结束程序的时候调用,所以我们可以调用这个函数来关闭SDL,atexit()函数的参数是一个函数的名字,意思是在程序结束前调用指定函数做一些善后处理工作。atexit()函数的作用是向系统注册传进来的函数,以便程序结束时调用该函数。这个函数可以在微软的MSDN中查到。  

....//初始化SDL
SDL_InitSDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);atexit(SDL_Quit);
//添加自己的处理代码...........

  这样写,无论你在哪里结束程序,系统都会执行SDL_Quit()函数关闭SDL。和初始化结束相关的函数还有:  

函数名 功能
SDL_Init 初始化SDL一个或多个子系统
SDL_InitSubSystem             在调用SDL_Init初始化SDL后,你可以调用该函数初始化其他子系统,用法和SDL_Init相同,但必须在SDL_Init调用后调用
SDL_Quit 关闭所有SDL子系统,清理SDL所占资源。
SDL_QuitSubSystem 在初始化后如果你想关闭某个子系统而不想关闭所有SDL子系统则可以调用该函数。
SDL_WasInit 检查指定子系统是否被初始化,返回值是该子系统的常量值(见表2.1)
SDL_GetError 返回最后一次SDL的错误,返回值是一个字符串。

  本次讨论了SDL起动和结束需要注意的地方。大家应该掌握SDL初始化过程和退出SDL时应该怎样处理。

  下一次我们将一起看一看SDL中用的最多的子系统视频子系统。