Andrew Huang
一.事件循环
------------------------------------------------------
一个完整的GUI程序,需要处理各种事件,如按键,鼠标,窗口操作等。一般这种程序会设计成一个与底层交互的事件驱动模型。即底层不断发送事件,而在程序用一个循环不断处理各种事件
各个GUI都是采用这样模型来实现,SDL抽象这个模型,采用SDL_event来抽象表示具体的事件,它有如下几种类型。
/** Event enumerations */ typedef enum { SDL_NOEVENT = 0, /**< Unused (do not remove) */ SDL_ACTIVEEVENT, /**< Application loses/gains visibility */ SDL_KEYDOWN, /**< Keys pressed */ SDL_KEYUP, /**< Keys released */ SDL_MOUSEMOTION, /**< Mouse moved */ SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */ SDL_MOUSEBUTTONUP, /**< Mouse button released */ SDL_JOYAXISMOTION, /**< Joystick axis motion */ SDL_JOYBALLMOTION, /**< Joystick trackball motion */ SDL_JOYHATMOTION, /**< Joystick hat position change */ SDL_JOYBUTTONDOWN, /**< Joystick button pressed */ SDL_JOYBUTTONUP, /**< Joystick button released */ SDL_QUIT, /**< User-requested quit */ SDL_SYSWMEVENT, /**< System specific event */ SDL_EVENT_RESERVEDA, /**< Reserved for future use.. */ SDL_EVENT_RESERVEDB, /**< Reserved for future use.. */ SDL_VIDEORESIZE, /**< User resized video mode */ SDL_VIDEOEXPOSE, /**< Screen needs to be redrawn */ SDL_EVENT_RESERVED2, /**< Reserved for future use.. */ SDL_EVENT_RESERVED3, /**< Reserved for future use.. */ SDL_EVENT_RESERVED4, /**< Reserved for future use.. */ SDL_EVENT_RESERVED5, /**< Reserved for future use.. */ SDL_EVENT_RESERVED6, /**< Reserved for future use.. */ SDL_EVENT_RESERVED7, /**< Reserved for future use.. */ /** Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use */ SDL_USEREVENT = 24, /** This last event is only for bounding internal arrays * It is the number of bits in the event mask datatype -- Uint32 */ SDL_NUMEVENTS = 32 } SDL_EventType;
|
SDL采用 int SDL_PollEvent(SDL_Event *event); 来从底层提取事件。
每一个事件都有一个独立数据结构来定义,但是第一个成员必是一个int type,
SDL_Event就是一个各种事件定义的联合
/** General event structure */ typedef union SDL_Event { Uint8 type; SDL_ActiveEvent active; SDL_KeyboardEvent key; SDL_MouseMotionEvent motion; SDL_MouseButtonEvent button; SDL_JoyAxisEvent jaxis; SDL_JoyBallEvent jball; SDL_JoyHatEvent jhat; SDL_JoyButtonEvent jbutton; SDL_ResizeEvent resize; SDL_ExposeEvent expose; SDL_QuitEvent quit; SDL_UserEvent user; SDL_SysWMEvent syswm; } SDL_Event;
|
而象常用的事件有,退出事件(当你点击窗口关闭键,就会触发此事件)
typedef struct SDL_QuitEvent { Uint8 type; /**< SDL_QUIT */ } SDL_QuitEvent;
|
按键处理事件
/** Keyboard event structure */ typedef struct SDL_KeyboardEvent { Uint8 type; /**< SDL_KEYDOWN or SDL_KEYUP */ Uint8 which; /**< The keyboard device index */ Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ SDL_keysym keysym; } SDL_KeyboardEvent;
|
同步事件
1.2 同步事件处理框架
它将是在主循环完成事件处理,这个循环过程是就是主线程的执行过程
int quit = false; while( quit == false ) { Now we start the main loop. This loop will keep going until the user sets quit to true. //While there's an event to handle
while( SDL_PollEvent( &event ) ) { switch(event.type) { case SDL_QUIT: quit = true; break; default: break; } }
|
还有两个不常用的事件函数
SDL_WaitEvent(); //必须等到有一个事件才返回,而SDL_PollEvent 没有事件也立即返回,这样提高系统反应速度。
SDL_PeepEvents(). 是提出事件,但事件本身仍然在事件队列中
1.3异步事件处理。
有时比较复杂的游戏的主循环可能用作其它程序,这时用得上事件过滤器,事件过滤器,在有事件发生调用事件处理回调函数。因此称为异步事件处理.
它调用 void SDL_SetEventFilter(SDL_EventFilter filter);来加入事件过滤回调函数.
其中.filter是一个函数指针,它有如下类型
SDL_SetEventFilter(PAL_EventFilter);
二.SDL按键处理
---------------------------------------------------------------------
按键类型是 event.type == SDL_KEYDOWN,
typedef struct{ Uint8 scancode; SDLKey sym; SDLMod mod; Uint16 unicode; } SDL_keysym;
|
表示用户按下键盘
1.普通按键盘处理。
保存在event.key.keysym.sym 是相应的键值
keysym有如下定义
/* SDLK_LEFTBRACKET = 91, SDLK_BACKSLASH = 92, SDLK_RIGHTBRACKET = 93, SDLK_CARET = 94, SDLK_UNDERSCORE = 95, SDLK_BACKQUOTE = 96, SDLK_a = 97, SDLK_b = 98, SDLK_c = 99, SDLK_d = 100, SDLK_e = 101, SDLK_f = 102, */ int quit = false; while( quit == false ) { Now we start the main loop. This loop will keep going until the user sets quit to true. //While there's an event to handle
while( SDL_PollEvent( &event ) ) { switch(event.type) { case SDL_QUIT: quit = true; break; case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_UP: ; break; case SDLK_DOWN: ; break; case SDLK_a: ; break; case SDLK_RIGHT: ; break; } break; default: break; } }
|
2.判断是按下组合键
key.keysym.mod 保存组合键状态,如果检测是否按下 ALT
if(lpEvent->key.keysym.mod & KMOD_ALT)
各个组合状态如下
SDLMod |
Meaning |
KMOD_NONE |
No modifiers applicable |
KMOD_LSHIFT |
Left Shift is down |
KMOD_RSHIFT |
Right Shift is down |
KMOD_LCTRL |
Left Control is down |
KMOD_RCTRL |
Right Control is down |
KMOD_LALT |
Left Alt is down |
KMOD_RALT |
Right Alt is down |
KMOD_LMETA |
Left Meta is down |
KMOD_RMETA |
Right Meta is down |
KMOD_NUM |
Numlock is down |
KMOD_CAPS |
Capslock is down |
KMOD_MODE |
Mode is down |
KMOD_CTRL |
A Control key is down |
KMOD_SHIFT |
A Shift key is down |
KMOD_ALT |
An Alt key is down |
KMOD_META |
A Meta key is down |
阅读(3123) | 评论(0) | 转发(1) |