SDL游戏开发教程03(消息循环和键盘事件响应)

  对于窗口程序来说,消息循环和事件响应是非常重要的,这节将介绍如何利用SDL提供的API函数实现消息循环和键盘ESC键响应。
将上节中的这部分代码注释掉:

Cpp代码   收藏代码
  1. //if( SDL_Flip( screen ) == -1 )  
  2. //{  
  3. //  return 1;  
  4. //}  
  5. //SDL_Delay( 2000 );  

 

    上面的代码主要是将内存中的内容显示到屏幕上,然后等待两秒,让用户有机会看到图片。

 

    下面要将这部分带代码替换成一个消息循环,让程序可以响应用户消息,代码如下:

 

Cpp代码   收藏代码
  1. bool bQuit = false;     //程序是否退出的标志  
  2. SDL_Event event;  
  3. while(!bQuit)           //如果bQuit不为true的话,循环一直进行  
  4. {  
  5.     //从消息循环中尝试取出一个消息,如果有的话返回ture,否则返回false  
  6.     //SDL_PollEvent不会等待,而是立刻返回  
  7.     while( SDL_PollEvent( &event ) )  
  8.     {  
  9.         switch(event.type)      //处理取到的消息,判断消息类型  
  10.         {  
  11.         case SDL_KEYDOWN:       //如果是键盘按下事件  
  12.             if(event.key.keysym.sym == SDLK_ESCAPE) //如果按的是ESC键  
  13.             {  
  14.                 bQuit = true;                       //退出循环  
  15.             }  
  16.             break;  
  17.         case SDL_QUIT:          //如果是窗口关闭事件,例如点击窗口的关闭按钮  
  18.             bQuit = true;                           //退出循环  
  19.             break;  
  20.         default:  
  21.             break;  
  22.         }  
  23.     }  
  24.   
  25.     //将内存中的内容显示到屏幕上,该函数每调用一次就会更新一次窗口的内容,即游戏中的一帧  
  26.     //由于在这个循环中我们没有修改内存中的内容,所以屏幕窗口中显示的内容不会发生变化  
  27.     if( SDL_Flip( screen ) == -1 )  
  28.     {  
  29.         break;  
  30.     }  
  31. }  

    学过windwos API编程的人一定对上面的这段代码非常熟悉,因为它和windows的消息循环机制很相似,对于windows的消息循环来说我们一般这样写:

Cpp代码   收藏代码
  1. MSG msg;  
  2. while(GetMessage(&msg,NULL,0,0))  
  3. {  
  4.     TranslateMessage(&msg);  
  5.     DispatchMessage(&msg);  
  6. }  

     在这里windows和SDL消息循环的区别在于GetMessage在消息队列中没有消息的情况下会等待,直到有消息为止;而SDL_PollEvent是不管有没有消息都马上返回。

    其实在windows api中也有与SDL的SDL_PollEvent对应的函数,那就是PeekMessage。同样在SDL中也有与GetMessage对于的SDL_WaitEvent函数。

 

    在这里,我们为什么用SDL_PollEvent而不用SDL_WaitEvent?是因为SDL_WaitEvent在没有用户消息的时候会造成程序等待,从而影响到游戏的帧数,这样在有动画的游戏中,就会出现用户不操作的时候界面停止,当用户再次操作时,界面发生跳跃的情况。试想玩俄罗斯方块的时候,你操作一下它就动一下,你不操作他就不动;或者刚刚方块还在上面,你等了一下没操作键盘,等你再操作键盘的时候,方块已经到下面了,这个是因为方块的下落一般是在定时器中处理的,是后台处理,没有用户消息的时候,后台的定时器还在运行,但界面没有和后台同步,从而造成画面跳跃前进的状况。

 

    对于消息处理来说,SDL还提供了一些函数,由于我们暂时对消息处理没有进一步更深的需求,所以在这里不详细介绍,等用到的时候再说。如果你想了解一下的话,可以阅读SDL的文档。

 

    下面分析SDL_Event的结构:

Cpp代码   收藏代码
  1. typedef union SDL_Event   
  2. {  
  3.     Uint8 type;                 //消息类型  
  4.     SDL_ActiveEvent active;     //窗口焦点、输入焦点及鼠标焦点的失去和得到消息  
  5.     SDL_KeyboardEvent key;      //键盘消息,键盘按下和释放  
  6.     SDL_MouseMotionEvent motion;//鼠标移动消息  
  7.     SDL_MouseButtonEvent button;//鼠标按键消息  
  8.     SDL_JoyAxisEvent jaxis;     //手柄消息  
  9.     SDL_JoyBallEvent jball;     //手柄消息  
  10.     SDL_JoyHatEvent jhat;       //手柄消息  
  11.     SDL_JoyButtonEvent jbutton; //手柄消息  
  12.     SDL_ResizeEvent resize;     //窗口大小变化事件  
  13.     SDL_ExposeEvent expose;     //窗口重绘消息  
  14.     SDL_QuitEvent quit;         //退出消息  
  15.     SDL_UserEvent user;         //用户自定义事件  
  16.     SDL_SysWMEvent syswm;       //平台相关的系统消息  
  17. } SDL_Event;  

     SDL_Event是一个联合体,type字段决定了其中的哪个结构体数据有效。 
    本节中只用到了键盘消息,所以这里主要介绍键盘消息,如果后面用到了其他消息,将做详细解释。SDL_KeyboardEvent定义:

Cpp代码   收藏代码
  1. typedef struct  
  2. {  
  3.   Uint8 type;           //消息类型,<tt class="LITERAL">SDL_KEYDOWN/UP</tt>  
  4.   
  5.   
  6.   Uint8 state;          //键盘状态,表示按下还是释放,在这里和type字段代表的意义相同  
  7.   SDL_keysym keysym;    //具体的按键信息  
  8. } SDL_KeyboardEvent;  

     这里是键盘消息结构体的定义,type表示类型,由于SDL_Event是联合体,所以SDL_KeyboardEvent中的type等于SDL_Event中的type字段。下面看SDL_keysym:

Cpp代码   收藏代码
  1. typedef struct  
  2. {  
  3.   Uint8 scancode;   //按键对应的硬件扫描码  
  4.   SDLKey sym;       //按键对应的SDL枚举定义,SDL定义的键盘键以SDLK_开头(如SDLK_DELETE表示删除键)  
  5.   SDLMod mod;       //哪个辅助键被按下,辅助键指ALT,SHIFT之类的键  
  6.   Uint16 unicode;   //输入对应的unicode编码(需要调用SDL_EnableUNICODE开启unicode,SDL默认不开启)  
  7. } SDL_keysym;  

    其中scancode 暂时用不着,判断哪个键被按下一般都是用sym ,SDLKey和SDLMod都是SDL定义的枚举,在头文件SDL_keysym.h中。具体的可参考SDL文档或者源代码。

 

     到这里为止,我们可以在窗口中显示一张图片,并且可以移动和关闭窗口了,在这过程中用到的函数的具体相关细节,需要大家自己去尝试,去了解,这里只是介绍了一些常用的功能。下一节中将介绍如何用C++将这些代码封装起来。

你可能感兴趣的:(SDL游戏开发教程03(消息循环和键盘事件响应))