最近終於開始學習cocos2d-x引擎了,Cocos2d-x作爲一個手機遊戲引擎,屏幕觸摸事件(touch)的處理一定時非常重要的。上個禮拜,我就開始琢磨,如何在telnet終端通過CCConsole命令模擬touch事件? 要在引擎裏模擬touch事件,就先要弄清楚引擎是如何處理touch事件的。就以往的經驗,touch事件的處理是比較複雜的,所以千萬不能先看代碼或者查資料,要先想清楚。
觸摸事件是通過觸摸屏傳感器產生中斷傳給CPU,CPU再調用驅動的中斷處理程序傳給OS,OS再通過touch事件回調接口傳給應用處理的。引擎的位置顯然在應用層。那我們的目標就是OS的回調接口,以Android爲例,應用入口在android_main(),回調接口也是在這裏指定的:
void android_main(struct android_app* state) {
// Make sure glue isn't stripped.
app_dummy();
memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
state->inputPollSource.process = process_input;
engine.app = state;
....
}
input事件的處理函數就是engin_handle_input:
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
pthread_t thisthread = pthread_self();
LOG_EVENTS_DEBUG("engine_handle_input(%X, %X), pthread_self() = %X", app, event, thisthread);
struct engine* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine->animating = 1;
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return handle_touch_input(event);
}
else
return handle_key_input(event);
return 0;
}
input事件分兩種類型,touch input 和 key input,我們關心的是touch事件,處理函數爲handle_touch_input():
static int32_t handle_touch_input(AInputEvent *event) {
pthread_t thisthread = pthread_self();
LOG_EVENTS_DEBUG("handle_touch_input(%X), pthread_self() = %X", event, thisthread);
switch(AMotionEvent_getAction(event) &
AMOTION_EVENT_ACTION_MASK) {
case AMOTION_EVENT_ACTION_DOWN:
{
LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_DOWN");
int pointerId = AMotionEvent_getPointerId(event, 0);
float xP = AMotionEvent_getX(event,0);
float yP = AMotionEvent_getY(event,0);
LOG_EVENTS_DEBUG("Event: Action DOWN x=%f y=%f pointerID=%d\n",
xP, yP, pointerId);
float x = xP;
float y = yP;
cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &pointerId, &x, &y);
return 1;
}
break;
.....
}
}
爲節省篇幅,只列出touch begin的代碼,其他的類似。
這樣,就很清楚了,要模擬屏幕touch事件,只要通過:
cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin/handleTouchesEnd/handleTouchesMove
這幾個接口就可以實現了。
這樣,就可以在telnet終端裏輸入
>touch tap 300 600
>touch swipe 800 600 800 300
來模擬touch事件了
代碼可以看這裏:
https://github.com/cocos2d/cocos2d-x/pull/5462