cocos2dx android平台事件系统解析

时间:2023-03-08 18:36:11

对于cocos2dx在android平台事件的响应过程很模糊,于是分析了下源码,cocos2dx 版本3.4,先导入一个android工程,然后看下AndroidManifest.xml

    <application android:label="@string/app_name"
android:icon="@drawable/icon"> <!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cocos2dcpp" /> <activity android:name="org.cocos2dx.cpp.AppActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation"> <intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

由此得知启动窗口类为 org.cocos2dx.cpp.AppActivity,并继承之 Cocos2dxActivity

package org.cocos2dx.cpp;

import org.cocos2dx.lib.Cocos2dxActivity;

public class AppActivity extends Cocos2dxActivity {
}
public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener 

看下 Cocos2dxActivity 的 onCreate

    @Override
protected void onCreate(final Bundle savedInstanceState) {
Log.i(TAG, "------onCreate----");
super.onCreate(savedInstanceState);
CocosPlayClient.init(this, false); onLoadNativeLibraries();//加载了一些静态库 sContext = this;
this.mHandler = new Cocos2dxHandler(this); Cocos2dxHelper.init(this); this.mGLContextAttrs = getGLContextAttrs();
this.init();//初始化 if (mVideoHelper == null) {
mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
} if(mWebViewHelper == null){
mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);
}
}

onCreate 调用了  init()  初始化

   public void init() {

        // FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(framelayout_params); // Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params); // ...add to FrameLayout
mFrameLayout.addView(edittext); // Cocos2dxGLSurfaceView
this.mGLSurfaceView = this.onCreateView(); // ...add to FrameLayout
mFrameLayout.addView(this.mGLSurfaceView); // Switch to supported OpenGL (ARGB888) mode on emulator
if (isAndroidEmulator())
this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
this.mGLSurfaceView.setCocos2dxEditText(edittext); // Set framelayout as the content view
setContentView(mFrameLayout);
}

最终显示的视图为 this.mGLSurfaceView = this.onCreateView();

    public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
//this line is need on some device if we specify an alpha bits
if(this.mGLContextAttrs[3] > 0) glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); Cocos2dxEGLConfigChooser chooser = new Cocos2dxEGLConfigChooser(this.mGLContextAttrs);
glSurfaceView.setEGLConfigChooser(chooser); return glSurfaceView;
}

Cocos2dxGLSurfaceView 就是最终显示的视图,事件处理也在这个类中,包括 onResume,onPause,onSizeChanged,onKeyDown,onTouchEvent等 主要看下onTouchEvent事件的处理过程

 @Override
public boolean onTouchEvent(final MotionEvent pMotionEvent) { //Log.d(TAG, "------onTouchEvent action=----"+pMotionEvent.getAction()); // these data are used in ACTION_MOVE and ACTION_CANCEL
final int pointerNumber = pMotionEvent.getPointerCount();
final int[] ids = new int[pointerNumber];
final float[] xs = new float[pointerNumber];
final float[] ys = new float[pointerNumber]; for (int i = 0; i < pointerNumber; i++) {
ids[i] = pMotionEvent.getPointerId(i);
xs[i] = pMotionEvent.getX(i);
ys[i] = pMotionEvent.getY(i);
} switch (pMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int idPointerDown = pMotionEvent.getPointerId(indexPointerDown);
final float xPointerDown = pMotionEvent.getX(indexPointerDown);
final float yPointerDown = pMotionEvent.getY(indexPointerDown); this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
}
});
break; case MotionEvent.ACTION_DOWN:
// there are only one finger on the screen
final int idDown = pMotionEvent.getPointerId(0);
final float xDown = xs[0];
final float yDown = ys[0]; this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown, xDown, yDown);
}
});
break; case MotionEvent.ACTION_MOVE:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionMove(ids, xs, ys);
}
});
break; case MotionEvent.ACTION_POINTER_UP:
final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int idPointerUp = pMotionEvent.getPointerId(indexPointUp);
final float xPointerUp = pMotionEvent.getX(indexPointUp);
final float yPointerUp = pMotionEvent.getY(indexPointUp); this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
}
});
break; case MotionEvent.ACTION_UP:
// there are only one finger on the screen
final int idUp = pMotionEvent.getPointerId(0);
final float xUp = xs[0];
final float yUp = ys[0]; this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idUp, xUp, yUp);
}
});
break; case MotionEvent.ACTION_CANCEL:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionCancel(ids, xs, ys);
}
});
break;
} /*
if (BuildConfig.DEBUG) {
Cocos2dxGLSurfaceView.dumpMotionEvent(pMotionEvent);
}
*/
return true;
}

看下 MotionEvent.ACTION_DOWN,调用了Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown

    public void handleActionDown(final int id, final float x, final float y) {
Log.i("Cocos2dxRenderer","-----handleActionDown--");
Cocos2dxRenderer.nativeTouchesBegin(id, x, y);
}

这里的nativeTouchesBegin 是一个jni方法,是现在cocos2d\cocos\platform\android\jni\TouchesJni.cpp里,

private static native void nativeTouchesBegin(final int id, final float x, final float y);
    JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y) {
intptr_t idlong = id;
log("----Info:nativeTouchesBegin id = %d, x=%f, y=%f",id,x,y);
cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &idlong, &x, &y);
}

最后调用GLView::handleTouchesBegin 通过 EventDispatcher::dispatchEvent进行事件的分发,调用事件响应函数,都是C++里完成的,就不再往下分析了。

能力有限,分析有误处请指正。