一个事件,简单说就是一件发生的事情。这可能是“一个按键被按下”、“鼠标发生了移动”、“窗口发生了缩放”,或者是本课中将要介绍的“窗口被用户关闭”。
//头文件 #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include <string> //窗口属性 const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; const int SCREEN_BPP = 32; //表面 SDL_Surface *image = NULL; SDL_Surface *screen = NULL;
这里和前面一样,我们有头文件、常量和表面。
//将要用到的事件结构体 SDL_Event event;
现在这个是新的。一个
SDL_Event
结构体存储了事件的信息,我们可以用这些信息来处理这个事件。SDL_Surface *load_image( std::string filename ) { //存储加载好的图像 SDL_Surface* loadedImage = NULL; //存储优化后的图像 SDL_Surface* optimizedImage = NULL; //加载图像 loadedImage = IMG_Load( 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 ); }
这些是我们的表面加载和blit的函数,与前面教程里的代码完全一样。
bool init() { //初始化SDL的所有子系统 if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return false; } //设置窗口 screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ); //如果设置出错 if( screen == NULL ) { return false; } //设置窗口标题 SDL_WM_SetCaption( "Event test", NULL ); //如果所有初始化操作都成功 return true; }
这是初始化函数。这个函数启动了SDL,设置了窗口,设置了窗口标题,如果发生任何错误,会返回false。
bool load_files() { //加载图像 image = load_image( "x.png" ); //如果加载出错 if( image == NULL ) { return false; } //如果所有图片加载正常 return true; }
这是文件加载函数。它加载了图片,如果发生了任何的错误,会返回false。
void clean_up() { //释放图像 SDL_FreeSurface( image ); //退出SDL SDL_Quit(); }
这里我们有程序末尾的清理函数。它清除了表面并退出了SDL。
int main( int argc, char* args[] ) { //确保程序一直等待quit bool quit = false;
现在我们进入main函数。
这里有一个quit变量,我们用它来跟踪用户是否想要退出程序。因为程序刚刚启动,所以我们要把它设为false,否则程序会立即退出。
这里有一个quit变量,我们用它来跟踪用户是否想要退出程序。因为程序刚刚启动,所以我们要把它设为false,否则程序会立即退出。
//初始化 if( init() == false ) { return 1; } //加载文件 if( load_files() == false ) { return 1; }
现在我们调用先前创建好的初始化函数和文件加载函数。
//将image表面应用到窗口上 apply_surface( 0, 0, image, screen ); //更新窗口 if( SDL_Flip( screen ) == -1 ) { return 1; }
然后我们让图片显示在窗口里。
//当用户还不想退出时 while( quit == false ) {
现在我们开始主循环。这个循环会不停地跑,直到用户将quit变量设为true。
//当有事件发生时,我们需要处理它们 while( SDL_PollEvent( &event ) ) {
在SDL中,每当有一个事件发生, 它会被置于事件队列中。事件队列为每个发生的事件保存了事件数据。
所以如果你按一下鼠标按钮,再移动一下鼠标,接着再按下键盘上某个按键,事件队列看起来会像这样:
函数
这段代码的作用是:只要事件队列中还有事件,将它们逐一地取出来。
所以如果你按一下鼠标按钮,再移动一下鼠标,接着再按下键盘上某个按键,事件队列看起来会像这样:
函数
SDL_PollEvent()
的作用是从事件队列底部取出一个事件并将其事件数据粘贴到一个SDL_Event
类型的结构体中。这段代码的作用是:只要事件队列中还有事件,将它们逐一地取出来。
//如果用户点击了窗口右上角的关闭按钮 if( event.type == SDL_QUIT ) { //退出程序 quit = true; } } }
当用户单击窗口右上角的关闭按钮时,事件的类型会是
因为我们想要这个程序在用户点击关闭按钮时退出,所以我们此时将quit设为true,这样可以中断并退出主循环。
SDL_QUIT
。译者注:“X out the window” 这个词组采用意译,翻译为“单击窗口右上角的关闭按钮”,虽然有点罗嗦,但如果直译为“叉掉窗口”,会显得很不正式,且表意不明确。
但是当用户执行这样的操作后,程序并不会被关闭,这只是告诉我们用户想要关闭程序。 因为我们想要这个程序在用户点击关闭按钮时退出,所以我们此时将quit设为true,这样可以中断并退出主循环。
//清理表面并退出SDL clean_up(); return 0; }