• cocos2dx android平台事件系统解析


    对于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方法,是现在cocos2dcocosplatformandroidjniTouchesJni.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++里完成的,就不再往下分析了。

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

  • 相关阅读:
    Unity动态批处理和静态批处理学习
    Mac下Unity使用Jenkins自动化打包
    Mac 环境环境下安装Git与使用(码云)
    MySQL: 6、MySQL语句
    MySQL: 5、MySQL索引、视图、存储过程
    MySQL: 4、多表、外键、数据库设计
    MySQL: 3、SQL语言 ②约束、事务
    MySQL: 2、SQL语言 ①概念、分类
    MySQL: 1、MySQL基础
    Mac 系统下如何显示和隐藏文件
  • 原文地址:https://www.cnblogs.com/gamesky/p/4310342.html
Copyright © 2020-2023  润新知