(一) Android平台下:

cocos2dx 版本3.2,先导入一个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

    @Overrideprotected 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() {// FrameLayoutViewGroup.LayoutParams framelayout_params =new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);mFrameLayout = new FrameLayout(this);mFrameLayout.setLayoutParams(framelayout_params);// Cocos2dxEditText layoutViewGroup.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);// Cocos2dxGLSurfaceViewthis.mGLSurfaceView = this.onCreateView();// ...add to FrameLayoutmFrameLayout.addView(this.mGLSurfaceView);// Switch to supported OpenGL (ARGB888) mode on emulatorif (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 bitsif(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事件的处理过程.

@Overridepublic boolean onTouchEvent(final MotionEvent pMotionEvent) {//Log.d(TAG, "------onTouchEvent action=----"+pMotionEvent.getAction());// these data are used in ACTION_MOVE and ACTION_CANCELfinal 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() {@Overridepublic void run() {Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);}});break;case MotionEvent.ACTION_DOWN:// there are only one finger on the screenfinal int idDown = pMotionEvent.getPointerId(0);final float xDown = xs[0];final float yDown = ys[0];this.queueEvent(new Runnable() {@Overridepublic void run() {Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown, xDown, yDown);}});break;case MotionEvent.ACTION_MOVE:this.queueEvent(new Runnable() {@Overridepublic 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() {@Overridepublic void run() {Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);}});break;case MotionEvent.ACTION_UP:// there are only one finger on the screenfinal int idUp = pMotionEvent.getPointerId(0);final float xUp = xs[0];final float yUp = ys[0];this.queueEvent(new Runnable() {@Overridepublic void run() {Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idUp, xUp, yUp);}});break;case MotionEvent.ACTION_CANCEL:this.queueEvent(new Runnable() {@Overridepublic 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 (其实GLView并没有重写父类的handleTouchesBegin方法,所以android下的触发事件,最后是通过GLViewProtocol类的handleTouchesBegin方法进行处理的). 通过 EventDispatcher::dispatchEvent进行事件的分发,调用事件响应函数,都是C++里完成的,就不再往下分析了。

附注:

C++里对事件的分发机制是通过Event,EventListener和EventDispatcher三个主要类完成的,具体详见cocos2d-x 源码分析 : EventDispatcher、EventListener、Event 源码分析 (新触摸机制,新的NotificationCenter机制) .

[转自]cocos2dx android平台事件系统解析

(二) 上面针对的是Android平台下,其他系统事件通知到cocos2dx的流程,在desktop和ios下的流程类似,都有相应平台下的处理文件接收系统事件,如下:

/home/yangxt/document/cocos2d-x-3.2/cocos/platform/CCGLViewProtocol.cpp:237: void GLViewProtocol::handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[])/home/yangxt/document/cocos2d-x-3.2/cocos/platform/CCGLViewProtocol.h:163:     virtual void handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[]);/home/yangxt/document/cocos2d-x-3.2/cocos/platform/android/jni/TouchesJni.cpp:35:         cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &id, &x, &y);/home/yangxt/document/cocos2d-x-3.2/cocos/platform/desktop/CCGLView.cpp:555:                 this->handleTouchesBegin(1, &id, &_mouseX, &_mouseY);/home/yangxt/document/cocos2d-x-3.2/cocos/platform/ios/CCEAGLView.mm:411:     glview->handleTouchesBegin(i, (intptr_t*)ids, xs, ys);

从上面可以看出,android下的系统调用最后是调用到了TouchesJni.cpp文件下的触摸事件.也即本文第(一)部分所分析的结果.如果在ios平台下,可以看到是通过CCEAGLView.mm文件处理的.ios下这里不做过多分析. 而desktop平台下,直接通过CCGLView.cpp处理.下面看看desktop平台下的处理过程:

我们可以在GLView.cpp下找到下面的方法:

bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)
{setViewName(viewName);_frameZoomFactor = frameZoomFactor;glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);_mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,rect.size.height * _frameZoomFactor,_viewName.c_str(),_monitor,nullptr);glfwMakeContextCurrent(_mainWindow);glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);setFrameSize(rect.size.width, rect.size.height);// check OpenGL version at firstconst GLubyte* glVersion = glGetString(GL_VERSION);if ( utils::atof((const char*)glVersion) < 1.5 ){char strComplain[256] = {0};sprintf(strComplain,"OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",glVersion);MessageBox(strComplain, "OpenGL version too old");return false;}initGlew();// Enable point size by default.
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);return true;
}

glfwCreateWindow方法里面就完成了窗口的创建以及其他的一些初始化工作,并且也设置了鼠标,键盘等一下响应回调函数,这里,我们看看glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);的回调函数:

void GLView::onGLFWMouseCallBack(GLFWwindow* window, int button, int action, int modify)
{if(GLFW_MOUSE_BUTTON_LEFT == button){if(GLFW_PRESS == action){_captured = true;if (this->getViewPortRect().equals(Rect::ZERO) || this->getViewPortRect().containsPoint(Vec2(_mouseX,_mouseY))){intptr_t id = 0;this->handleTouchesBegin(1, &id, &_mouseX, &_mouseY);}}else if(GLFW_RELEASE == action){if (_captured){_captured = false;intptr_t id = 0;this->handleTouchesEnd(1, &id, &_mouseX, &_mouseY);}}}//Because OpenGL and cocos2d-x uses different Y axis, we need to convert the coordinate herefloat cursorX = (_mouseX - _viewPortRect.origin.x) / _scaleX;float cursorY = (_viewPortRect.origin.y + _viewPortRect.size.height - _mouseY) / _scaleY;if(GLFW_PRESS == action){EventMouse event(EventMouse::MouseEventType::MOUSE_DOWN);event.setCursorPosition(cursorX, cursorY);event.setMouseButton(button);Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);}else if(GLFW_RELEASE == action){EventMouse event(EventMouse::MouseEventType::MOUSE_UP);event.setCursorPosition(cursorX, cursorY);event.setMouseButton(button);Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);}
}

可以看到,在GLView里面直接处理窗口鼠标事件,并通过dispatchEvent将事件分发给cocos2dx. cocos2dx里面的事件分发这里也不作过多阐述.

附注:

上面对事件分发机制的分析中,我们可以看到,GLViewProtocol类实际负责了窗口级别的功能管理和实现, 包括:坐标和缩放管理, 画图工具,按键事件,而这些正是cocos2d-x游戏引擎核心(3.x)----启动渲染流程 博文分析中可以看到的.

转载于:https://www.cnblogs.com/yyxt/p/5516419.html

cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析...相关推荐

  1. Android 系统(199)---Android事件分发机制详解

    Android事件分发机制详解 前言 Android事件分发机制是Android开发者必须了解的基础 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全.思路不清晰.无源码分析. ...

  2. Android的事件分发机制

    前言 Android事件分发机制是Android开发者必须了解的基础 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化等等 今天,我将把 ...

  3. Android系统分析之带着问题看事件分发机制

    Android 触摸事件分发机制? Android系统分析之带着问题看事件分发机制 一 事件分发机制 1 什么是事件分发机制? 1.1 什么是事件? 答:当用户触摸屏幕时,每一次的点击,按下,移动,抬 ...

  4. 一文读懂Android View事件分发机制

    Android View 虽然不是四大组件,但其并不比四大组件的地位低.而View的核心知识点事件分发机制则是不少刚入门同学的拦路虎.ScrollView嵌套RecyclerView(或者ListVi ...

  5. 浅谈Android事件分发机制

    在Android实际开发过程中经常会遇到View之间的滑动冲突,如ScrollView与Listview.RecyclerView之间的嵌套使用.在很好的解决此类问题之前,我们应深入的了解Androi ...

  6. Android 事件分发机制

    Android 事件分发机制  demo验证:  https://blog.csdn.net/hty1053240123/article/details/77866302 目录 1.基础认知 2.事件 ...

  7. iOS 事件分类及事件分发机制

       什么是事件分发机制,当用户触碰屏幕后,其事件的传递过程被称作事件的分发,IOS的事件分发机制大致原理与Android及其相似.该事件传递过程往往都是由父控件一步一步向其子控件进行分发的. 事件分 ...

  8. Android6.0源码解读之ViewGroup点击事件分发机制

    本篇博文是Android点击事件分发机制系列博文的第三篇,主要是从解读ViewGroup类的源码入手,根据源码理清ViewGroup点击事件分发原理,明白ViewGroup和View点击事件分发的关系 ...

  9. Android 的触摸反馈以及事件分发机制

    在Android系统中,当你点击App某个按钮从你按下到抬起到底发生了什么? 要想解释这个问题首先需要了解Android的几个事件类型. Android 的事件类型分为以下四种: 1.MotionEv ...

  10. cocos2d-x 事件分发机制

    新事件分发机制:在2.x 版本事件处理时,将要触发的事件交给代理(delegate)处理,再通过实现代理里面的onTouchBegan等方法接收事件,最后完成事件的响应.而在新的事件分发机制中,只需通 ...

最新文章

  1. 有必要做 Code Review 吗???
  2. linux c 删除 文件 第一行
  3. 关于ViewGroup中requestDisallowInterceptTouchEvent的用法
  4. javascript技巧参考
  5. sentinel 时间窗口的实现
  6. linux启动流程——initrd和initramfs
  7. InfluxDb系列:几个关键概念(主要是和关系数据库做对比)
  8. 动词ing基本用法_哪些动词后面只能接动名词背诵口诀
  9. CPython 解释器 与 VC 编译器版本对应关系
  10. C++14::lambda函数的类型
  11. NSAssert与assert断言
  12. 【原版教材•中英对照】复合材料(第三版)— Krishan Chawla所著的广泛使用的教科书
  13. alpha-beta剪枝算法
  14. MyQQ框架火山SDK
  15. 显示器接口_显示器接口 - CNZHIQIANG
  16. 清理Windows Temp目录下的cab*文件
  17. 大唐:我家阁楼通公主府(二)
  18. 单片机编程软件很简单(17),Keil单片机编程软件之编译、链接
  19. TextCNN文本分类实现(主要是CNN模型的使用)
  20. php 热敏打印,从PHP打印到POS打印机

热门文章

  1. iOS开发之控制器之间传值
  2. VC++开发数字图像处理系统2
  3. Div图片垂直居中的方法
  4. 使用WinIO库实现保护模式下的IO和内存读写(_inp,_outp)
  5. 地球会随着人口增加而变重吗
  6. 常见的简单的无监督学习算法总结
  7. Nginx 场景应用
  8. 轻松搭建Redis缓存高可用集群
  9. 【shell 练习5】编写简单的多级菜单
  10. ef core中使用code first