本系列教程來自Dev Hub,一切解釋權歸原作者。我只是出自個人愛好,才翻譯了本系列教程。因爲本人也是個初學者,而且英語水平有限,錯誤難免,望各路高手指正。
本課原文地址:http://www.sdltutorials.com/sdl-events/
和遊戲開發基礎相關的有一個叫事件(譯者注:Events,我感覺還是消息比較貼切,以後就譯爲“消息”)的模塊。消息是程序和用戶之間最基本的交互。一個消息可能來自鍵盤、鼠標、遊戲杆、遊戲板等或者來自操作系統。要想處理好用戶和遊戲之間的交互,瞭解消息的運行機制很重要。前面我們已經用過消息了,雖然只是用來關閉窗口,現在我們就看看如何從用戶那裏接受消息。
如果你沒跟上(譯者注:你就去自己回顧下吧~),每個課程都是建立在前一個的基礎之上的,所以我們就使用前面一節課的代碼。爲了跟蹤所有的消息,並把它們傳遞給適當的函數,我們就要建立一個新的類。創建兩個文件,CEvent.h和CEvent.cpp。這兩個文件要處理我們的消息,並調用相應的函數。CApp要繼承此類,以便我們需要捕獲一個消息的時候簡單的重寫一個函數就行了。
打開CEvent.h,添加如下代碼:
- #ifndef _CEVENT_H_
- #define _CEVENT_H_
- #include <SDL.h>
- class CEvent {
- public:
- CEvent();
- virtual ~CEvent();
- virtual void OnEvent(SDL_Event* Event);
- virtual void OnInputFocus();
- virtual void OnInputBlur();
- virtual void OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode);
- virtual void OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode);
- virtual void OnMouseFocus();
- virtual void OnMouseBlur();
- virtual void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle);
- virtual void OnMouseWheel(bool Up, bool Down); //Not implemented
- virtual void OnLButtonDown(int mX, int mY);
- virtual void OnLButtonUp(int mX, int mY);
- virtual void OnRButtonDown(int mX, int mY);
- virtual void OnRButtonUp(int mX, int mY);
- virtual void OnMButtonDown(int mX, int mY);
- virtual void OnMButtonUp(int mX, int mY);
- virtual void OnJoyAxis(Uint8 which, Uint8 axis, Sint16 value);
- virtual void OnJoyButtonDown(Uint8 which, Uint8 button);
- virtual void OnJoyButtonUp(Uint8 which, Uint8 button);
- virtual void OnJoyHat(Uint8 which, Uint8 hat, Uint8 value);
- virtual void OnJoyBall(Uint8 which, Uint8 ball, Sint16 xrel, Sint16 yrel);
- virtual void OnMinimize();
- virtual void OnRestore();
- virtual void OnResize(int w,int h);
- virtual void OnExpose();
- virtual void OnExit();
- virtual void OnUser(Uint8 type, int code, void* data1, void* data2);
- };
- #endif
非常強大的一個類吧?好了,接着打開CEvent.cpp,並添加如下代碼:
- #include "CEvent.h"
- CEvent::CEvent() {
- }
- CEvent::~CEvent() {
- //Do nothing
- }
- void CEvent::OnEvent(SDL_Event* Event) {
- switch(Event->type) {
- case SDL_ACTIVEEVENT: {
- switch(Event->active.state) {
- case SDL_APPMOUSEFOCUS: {
- if ( Event->active.gain ) OnMouseFocus();
- else OnMouseBlur();
- break;
- }
- case SDL_APPINPUTFOCUS: {
- if ( Event->active.gain ) OnInputFocus();
- else OnInputBlur();
- break;
- }
- case SDL_APPACTIVE: {
- if ( Event->active.gain ) OnRestore();
- else OnMinimize();
- break;
- }
- }
- break;
- }
- case SDL_KEYDOWN: { OnKeyDown(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode);
- break;
- }
- case SDL_KEYUP: { OnKeyUp(Event->key.keysym.sym,Event->key.keysym.mod,Event->key.keysym.unicode);
- break;
- }
- 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);
- break;
- }
- case SDL_MOUSEBUTTONDOWN: {
- switch(Event->button.button) {
- case SDL_BUTTON_LEFT: {
- OnLButtonDown(Event->button.x,Event->button.y);
- break;
- }
- case SDL_BUTTON_RIGHT: {
- OnRButtonDown(Event->button.x,Event->button.y);
- break;
- }
- case SDL_BUTTON_MIDDLE: {
- OnMButtonDown(Event->button.x,Event->button.y);
- break;
- }
- }
- break;
- }
- case SDL_MOUSEBUTTONUP: {
- switch(Event->button.button) {
- case SDL_BUTTON_LEFT: {
- OnLButtonUp(Event->button.x,Event->button.y);
- break;
- }
- case SDL_BUTTON_RIGHT: {
- OnRButtonUp(Event->button.x,Event->button.y);
- break;
- }
- case SDL_BUTTON_MIDDLE: {
- OnMButtonUp(Event->button.x,Event->button.y);
- break;
- }
- }
- break;
- }
- case SDL_JOYAXISMOTION: { OnJoyAxis(Event->jaxis.which,Event->jaxis.axis,Event->jaxis.value);
- break;
- }
- case SDL_JOYBALLMOTION: { OnJoyBall(Event->jball.which,Event->jball.ball,Event->jball.xrel,Event->jball.yrel);
- break;
- }
- case SDL_JOYHATMOTION: {
- OnJoyHat(Event->jhat.which,Event->jhat.hat,Event->jhat.value);
- break;
- }
- case SDL_JOYBUTTONDOWN: { OnJoyButtonDown(Event->jbutton.which,Event->jbutton.button);
- break;
- }
- case SDL_JOYBUTTONUP: {
- OnJoyButtonUp(Event->jbutton.which,Event->jbutton.button);
- break;
- }
- case SDL_QUIT: {
- OnExit();
- break;
- }
- case SDL_SYSWMEVENT: {
- //Ignore
- break;
- }
- case SDL_VIDEORESIZE: {
- OnResize(Event->resize.w,Event->resize.h);
- break;
- }
- case SDL_VIDEOEXPOSE: {
- OnExpose();
- break;
- }
- default: {
- OnUser(Event->user.type,Event->user.code,Event->user.data1,Event->user.data2);
- break;
- }
- }
- }
- void CEvent::OnInputFocus() {
- //Pure virtual, do nothing
- }
- void CEvent::OnInputBlur() {
- //Pure virtual, do nothing
- }
- void CEvent::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) {
- //Pure virtual, do nothing
- }
- void CEvent::OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode) {
- //Pure virtual, do nothing
- }
- void CEvent::OnMouseFocus() {
- //Pure virtual, do nothing
- }
- void CEvent::OnMouseBlur() {
- //Pure virtual, do nothing
- }
- void CEvent::OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle) {
- //Pure virtual, do nothing
- }
- void CEvent::OnMouseWheel(bool Up, bool Down) {
- //Pure virtual, do nothing
- }
- void CEvent::OnLButtonDown(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnLButtonUp(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnRButtonDown(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnRButtonUp(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnMButtonDown(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnMButtonUp(int mX, int mY) {
- //Pure virtual, do nothing
- }
- void CEvent::OnJoyAxis(Uint8 which,Uint8 axis,Sint16 value) {
- //Pure virtual, do nothing
- }
- void CEvent::OnJoyButtonDown(Uint8 which,Uint8 button) {
- //Pure virtual, do nothing
- }
- void CEvent::OnJoyButtonUp(Uint8 which,Uint8 button) {
- //Pure virtual, do nothing
- }
- void CEvent::OnJoyHat(Uint8 which,Uint8 hat,Uint8 value) {
- //Pure virtual, do nothing
- }
- void CEvent::OnJoyBall(Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel) {
- //Pure virtual, do nothing
- }
- void CEvent::OnMinimize() {
- //Pure virtual, do nothing
- }
- void CEvent::OnRestore() {
- //Pure virtual, do nothing
- }
- void CEvent::OnResize(int w,int h) {
- //Pure virtual, do nothing
- }
- void CEvent::OnExpose() {
- //Pure virtual, do nothing
- }
- void CEvent::OnExit() {
- //Pure virtual, do nothing
- }
- void CEvent::OnUser(Uint8 type, int code, void* data1, void* data2) {
- //Pure virtual, do nothing
- }
代碼有點多呵,不過應該已經覆蓋了所有的SDL消息了。我們要做的很簡單,建立一個SDL_Event指針,然後根據其類型進行switch,並調用相應的函數。由於消息比較多,所有代碼看起來有點長。
現在一切就緒,讓我們回到CApp.h,然後把這兩個連接起來:
- #ifndef _CAPP_H_
- #define _CAPP_H_
- #include <SDL.h>
- #include "CEvent.h"
- #include "CSurface.h"
- class CApp : public CEvent {
- private:
- bool Running;
- SDL_Surface* Surf_Display;
- SDL_Surface* Surf_Test;
- public:
- CApp();
- int OnExecute();
- public:
- bool OnInit();
- void OnEvent(SDL_Event* Event);
- void OnLoop();
- void OnRender();
- void OnCleanup();
- };
- #endif
編譯一切正常。我們已經設定好了消息類,現在就讓我們把消息連接到我們新類的結構裏。打開CApp_OnEvent.cpp並編輯如下函數:
- #include "CApp.h"
- void CApp::OnEvent(SDL_Event* Event) {
- CEvent::OnEvent(Event);
- }
現在我們已經把消息結構傳送給我們的類了,要注意調用正確的回調函數。現在,當我們要檢查一個消息的時候,就重寫一個函數。由於我們去掉了對SDL_QUIT消息的檢查,就讓我們用函數來代替。再次打開CApp.h,並添加如下函數:
- #ifndef _CAPP_H_
- #define _CAPP_H_
- #include <SDL.h>
- #include "CEvent.h"
- #include "CSurface.h"
- class CApp : public CEvent {
- private:
- bool Running;
- SDL_Surface* Surf_Display;
- SDL_Surface* Surf_Test;
- public:
- CApp();
- int OnExecute();
- public:
- bool OnInit();
- void OnEvent(SDL_Event* Event);
- void OnExit();
- void OnLoop();
- void OnRender();
- void OnCleanup();
- };
- #endif
OnExit()函數會處理SDL_QUIT消息。現在我們有了原型,讓我們定義下它都做些什麼。打開CApp_OnEvent.cpp,並添加如下代碼:
- #include "CApp.h"
- void CApp::OnEvent(SDL_Event* Event) {
- CEvent::OnEvent(Event);
- }
- void CApp::OnExit() {
- Running = false;
- }
重新編譯一下,試試看。你應該可以像以前那樣退出程序。
我希望你能認真看看我們檢查的那些消息。以後我們將在我們的遊戲裏用到某些消息,現在你就先去熟悉熟悉吧。
跳到下一節課,看看創建我們的第一個遊戲吧,Tic-Tac-Toe.
SDL 消息 —— 課程文件:
Win32:Zip,Rar
Linux:Tar(多謝Gaten)