SDL游戏教程第三课 消息(Events)

翻译声明:
    本系列教程来自
Dev Hub,一切解释权归原作者。我只是出自个人爱好,才翻译了本系列教程。因为本人也是个初学者,而且英语水平有限,错误难免,望各路高手指正。

本课原文地址:http://www.sdltutorials.com/sdl-events/


和游戏开发基础相关的有一个叫事件(译者注:Events,我感觉还是消息比较贴切,以后就译为“消息”)的模块。消息是程序和用户之间最基本的交互。一个消息可能来自键盘、鼠标、游戏杆、游戏板等或者来自操作系统。要想处理好用户和游戏之间的交互,了解消息的运行机制很重要。前面我们已经用过消息了,虽然只是用来关闭窗口,现在我们就看看如何从用户那里接受消息。

如果你没跟上(译者注:你就去自己回顾下吧~),每个课程都是建立在前一个的基础之上的,所以我们就使用前面一节课的代码。为了跟踪所有的消息,并把它们传递给适当的函数,我们就要建立一个新的类。创建两个文件,CEvent.h和CEvent.cpp。这两个文件要处理我们的消息,并调用相应的函数。CApp要继承此类,以便我们需要捕获一个消息的时候简单的重写一个函数就行了。

打开CEvent.h,添加如下代码:
  1. #ifndef _CEVENT_H_
  2. #define _CEVENT_H_
  3. #include <SDL.h>
  4. class CEvent {
  5.     public:
  6.         CEvent();
  7.         virtual ~CEvent();
  8.         virtual void OnEvent(SDL_Event* Event);
  9.         virtual void OnInputFocus();
  10.         virtual void OnInputBlur();
  11.         virtual void OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode);
  12.         virtual void OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode);
  13.         virtual void OnMouseFocus();
  14.         virtual void OnMouseBlur();
  15.         virtual void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle);
  16.         virtual void OnMouseWheel(bool Up, bool Down);  //Not implemented
  17.         virtual void OnLButtonDown(int mX, int mY);
  18.         virtual void OnLButtonUp(int mX, int mY);
  19.         virtual void OnRButtonDown(int mX, int mY);
  20.         virtual void OnRButtonUp(int mX, int mY);
  21.         virtual void OnMButtonDown(int mX, int mY);
  22.         virtual void OnMButtonUp(int mX, int mY);
  23.         virtual void OnJoyAxis(Uint8 which, Uint8 axis, Sint16 value);
  24.         virtual void OnJoyButtonDown(Uint8 which, Uint8 button);
  25.         virtual void OnJoyButtonUp(Uint8 which, Uint8 button);
  26.         virtual void OnJoyHat(Uint8 which, Uint8 hat, Uint8 value);
  27.         virtual void OnJoyBall(Uint8 which, Uint8 ball, Sint16 xrel, Sint16 yrel);
  28.         virtual void OnMinimize();
  29.         virtual void OnRestore();
  30.         virtual void OnResize(int w,int h);
  31.         virtual void OnExpose();
  32.         virtual void OnExit();
  33.         virtual void OnUser(Uint8 type, int code, void* data1, void* data2);
  34. };
  35. #endif

非常强大的一个类吧?好了,接着打开CEvent.cpp,并添加如下代码:
  1. #include "CEvent.h"
  2. CEvent::CEvent() {
  3. }
  4. CEvent::~CEvent() {
  5.     //Do nothing
  6. }
  7. void CEvent::OnEvent(SDL_Event* Event) {
  8.     switch(Event->type) {
  9.         case SDL_ACTIVEEVENT: {
  10.             switch(Event->active.state) {
  11.                 case SDL_APPMOUSEFOCUS: {
  12.                     if ( Event->active.gain )   OnMouseFocus();
  13.                     else                OnMouseBlur();
  14.                     break;
  15.                 }
  16.                 case SDL_APPINPUTFOCUS: {
  17.                     if ( Event->active.gain )   OnInputFocus();
  18.                     else                OnInputBlur();
  19.                     break;
  20.                 }
  21.                 case SDL_APPACTIVE: {
  22.                     if ( Event->active.gain )   OnRestore();
  23.                     else                OnMinimize();
  24.                     break;
  25.                 }
  26.             }
  27.             break;
  28.         }
  29.         case SDL_KEYDOWN: {            OnKeyDown(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode);
  30.             break;
  31.         }
  32.         case SDL_KEYUP: {            OnKeyUp(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode);
  33.             break;
  34.         }
  35.         case SDL_MOUSEMOTION: {            OnMouseMove(Event->motion.x,Event->motion.y,Event->motion.xrel,Event->motion.yrel,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_RIGHT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0);
  36.             break;
  37.         }
  38.         case SDL_MOUSEBUTTONDOWN: {
  39.             switch(Event->button.button) {
  40.                 case SDL_BUTTON_LEFT: {
  41.                     OnLButtonDown(Event->button.x,Event->button.y);
  42.                     break;
  43.                 }
  44.                 case SDL_BUTTON_RIGHT: {
  45.                     OnRButtonDown(Event->button.x,Event->button.y);
  46.                     break;
  47.                 }
  48.                 case SDL_BUTTON_MIDDLE: {
  49.                     OnMButtonDown(Event->button.x,Event->button.y);
  50.                     break;
  51.                 }
  52.             }
  53.             break;
  54.         }
  55.         case SDL_MOUSEBUTTONUP: {
  56.             switch(Event->button.button) {
  57.                 case SDL_BUTTON_LEFT: {
  58.                     OnLButtonUp(Event->button.x,Event->button.y);
  59.                     break;
  60.                 }
  61.                 case SDL_BUTTON_RIGHT: {
  62.                     OnRButtonUp(Event->button.x,Event->button.y);
  63.                     break;
  64.                 }
  65.                 case SDL_BUTTON_MIDDLE: {
  66.                     OnMButtonUp(Event->button.x,Event->button.y);
  67.                     break;
  68.                 }
  69.             }
  70.             break;
  71.         }
  72.         case SDL_JOYAXISMOTION: {            OnJoyAxis(Event->jaxis.which,Event->jaxis.axis,Event->jaxis.value);
  73.             break;
  74.         }
  75.         case SDL_JOYBALLMOTION: {        OnJoyBall(Event->jball.which,Event->jball.ball,Event->jball.xrel,Event->jball.yrel);
  76.             break;
  77.         }
  78.         case SDL_JOYHATMOTION: {
  79. OnJoyHat(Event->jhat.which,Event->jhat.hat,Event->jhat.value);
  80.             break;
  81.         }
  82.         case SDL_JOYBUTTONDOWN: {           OnJoyButtonDown(Event->jbutton.which,Event->jbutton.button);
  83.             break;
  84.         }
  85.         case SDL_JOYBUTTONUP: {
  86.             OnJoyButtonUp(Event->jbutton.which,Event->jbutton.button);
  87.             break;
  88.         }
  89.         case SDL_QUIT: {
  90.             OnExit();
  91.             break;
  92.         }
  93.         case SDL_SYSWMEVENT: {
  94.             //Ignore
  95.             break;
  96.         }
  97.         case SDL_VIDEORESIZE: {
  98.             OnResize(Event->resize.w,Event->resize.h);
  99.             break;
  100.         }
  101.         case SDL_VIDEOEXPOSE: {
  102.             OnExpose();
  103.             break;
  104.         }
  105.         default: {
  106.             OnUser(Event->user.type,Event->user.code,Event->user.data1,Event->user.data2);
  107.             break;
  108.         }
  109.     }
  110. }
  111. void CEvent::OnInputFocus() {
  112.     //Pure virtual, do nothing
  113. }
  114. void CEvent::OnInputBlur() {
  115.     //Pure virtual, do nothing
  116. }
  117. void CEvent::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) {
  118.     //Pure virtual, do nothing
  119. }
  120. void CEvent::OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode) {
  121.     //Pure virtual, do nothing
  122. }
  123. void CEvent::OnMouseFocus() {
  124.     //Pure virtual, do nothing
  125. }
  126. void CEvent::OnMouseBlur() {
  127.     //Pure virtual, do nothing
  128. }
  129. void CEvent::OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle) {
  130.     //Pure virtual, do nothing
  131. }
  132. void CEvent::OnMouseWheel(bool Up, bool Down) {
  133.     //Pure virtual, do nothing
  134. }
  135. void CEvent::OnLButtonDown(int mX, int mY) {
  136.     //Pure virtual, do nothing
  137. }
  138. void CEvent::OnLButtonUp(int mX, int mY) {
  139.     //Pure virtual, do nothing
  140. }
  141. void CEvent::OnRButtonDown(int mX, int mY) {
  142.     //Pure virtual, do nothing
  143. }
  144. void CEvent::OnRButtonUp(int mX, int mY) {
  145.     //Pure virtual, do nothing
  146. }
  147. void CEvent::OnMButtonDown(int mX, int mY) {
  148.     //Pure virtual, do nothing
  149. }
  150. void CEvent::OnMButtonUp(int mX, int mY) {
  151.     //Pure virtual, do nothing
  152. }
  153. void CEvent::OnJoyAxis(Uint8 which,Uint8 axis,Sint16 value) {
  154.     //Pure virtual, do nothing
  155. }
  156. void CEvent::OnJoyButtonDown(Uint8 which,Uint8 button) {
  157.     //Pure virtual, do nothing
  158. }
  159. void CEvent::OnJoyButtonUp(Uint8 which,Uint8 button) {
  160.     //Pure virtual, do nothing
  161. }
  162. void CEvent::OnJoyHat(Uint8 which,Uint8 hat,Uint8 value) {
  163.     //Pure virtual, do nothing
  164. }
  165. void CEvent::OnJoyBall(Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel) {
  166.     //Pure virtual, do nothing
  167. }
  168. void CEvent::OnMinimize() {
  169.     //Pure virtual, do nothing
  170. }
  171. void CEvent::OnRestore() {
  172.     //Pure virtual, do nothing
  173. }
  174. void CEvent::OnResize(int w,int h) {
  175.     //Pure virtual, do nothing
  176. }
  177. void CEvent::OnExpose() {
  178.     //Pure virtual, do nothing
  179. }
  180. void CEvent::OnExit() {
  181.     //Pure virtual, do nothing
  182. }
  183. void CEvent::OnUser(Uint8 type, int code, void* data1, void* data2) {
  184.     //Pure virtual, do nothing
  185. }

代码有点多呵,不过应该已经覆盖了所有的SDL消息了。我们要做的很简单,建立一个SDL_Event指针,然后根据其类型进行switch,并调用相应的函数。由于消息比较多,所有代码看起来有点长。

现在一切就绪,让我们回到CApp.h,然后把这两个连接起来:
  1. #ifndef _CAPP_H_
  2. #define _CAPP_H_
  3. #include <SDL.h>
  4. #include "CEvent.h"
  5. #include "CSurface.h"
  6. class CApp : public CEvent {
  7.     private:
  8.         bool            Running;
  9.         SDL_Surface*    Surf_Display;
  10.         SDL_Surface*    Surf_Test;
  11.     public:
  12.         CApp();
  13.         int OnExecute();
  14.     public:
  15.         bool OnInit();
  16.         void OnEvent(SDL_Event* Event);
  17.         void OnLoop();
  18.         void OnRender();
  19.         void OnCleanup();
  20. };
  21. #endif

编译一切正常。我们已经设定好了消息类,现在就让我们把消息连接到我们新类的结构里。打开CApp_OnEvent.cpp并编辑如下函数:
  1. #include "CApp.h"
  2. void CApp::OnEvent(SDL_Event* Event) {
  3.     CEvent::OnEvent(Event);
  4. }
 
现在我们已经把消息结构传送给我们的类了,要注意调用正确的回调函数。现在,当我们要检查一个消息的时候,就重写一个函数。由于我们去掉了对SDL_QUIT消息的检查,就让我们用函数来代替。再次打开CApp.h,并添加如下函数:
  1.  
  2. #ifndef _CAPP_H_
  3. #define _CAPP_H_
  4. #include <SDL.h>
  5. #include "CEvent.h"
  6. #include "CSurface.h"
  7. class CApp : public CEvent {
  8.     private:
  9.         bool            Running;
  10.         SDL_Surface*    Surf_Display;
  11.         SDL_Surface*    Surf_Test;
  12.     public:
  13.         CApp();
  14.         int OnExecute();
  15.     public:
  16.         bool OnInit();
  17.         void OnEvent(SDL_Event* Event);
  18.         void OnExit();
  19.         void OnLoop();
  20.         void OnRender();
  21.         void OnCleanup();
  22. };
  23. #endif
 
OnExit()函数会处理SDL_QUIT消息。现在我们有了原型,让我们定义下它都做些什么。打开CApp_OnEvent.cpp,并添加如下代码:
  1. #include "CApp.h"
  2. void CApp::OnEvent(SDL_Event* Event) {
  3.     CEvent::OnEvent(Event);
  4. }
  5. void CApp::OnExit() {
  6.     Running = false;
  7. }

重新编译一下,试试看。你应该可以像以前那样退出程序。

我希望你能认真看看我们检查的那些消息。以后我们将在我们的游戏里用到某些消息,现在你就先去熟悉熟悉吧。

跳到下一节课,看看创建我们的第一个游戏吧,Tic-Tac-Toe.

SDL 消息 —— 课程文件:
Win32: Zip, Rar
Linux: Tar(多谢Gaten)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值