cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析
(一) 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
- @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 (其实GLView并没有重写父类的handleTouchesBegin方法,所以android下的触发事件,最后是通过GLViewProtocol类的handleTouchesBegin方法进行处理的). 通过 EventDispatcher::dispatchEvent进行事件的分发,调用事件响应函数,都是C++里完成的,就不再往下分析了。
附注:
C++里对事件的分发机制是通过Event,EventListener和EventDispatcher三个主要类完成的,具体详见cocos2d-x 源码分析 : EventDispatcher、EventListener、Event 源码分析 (新触摸机制,新的NotificationCenter机制).
(二) 上面针对的是Android平台下,其他系统事件通知到cocos2dx的流程,在desktop和ios下的流程类似,都有相应平台下的处理文件接收系统事件,如下:
- /home/yangxt/document/cocos2d-x-3.2/cocos/platform/CCGLViewProtocol.cpp:
- : void GLViewProtocol::handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[])
- /home/yangxt/document/cocos2d-x-3.2/cocos/platform/CCGLViewProtocol.h:
- : 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:
- : cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(, &id, &x, &y);
- /home/yangxt/document/cocos2d-x-3.2/cocos/platform/desktop/CCGLView.cpp:
- : this->handleTouchesBegin(, &id, &_mouseX, &_mouseY);
- /home/yangxt/document/cocos2d-x-3.2/cocos/platform/ios/CCEAGLView.mm:
- : 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 first
- const GLubyte* glVersion = glGetString(GL_VERSION);
- if ( utils::atof((const char*)glVersion) < 1.5 )
- {
- char strComplain[] = {};
- 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 = ;
- this->handleTouchesBegin(, &id, &_mouseX, &_mouseY);
- }
- }
- else if(GLFW_RELEASE == action)
- {
- if (_captured)
- {
- _captured = false;
- intptr_t id = ;
- this->handleTouchesEnd(, &id, &_mouseX, &_mouseY);
- }
- }
- }
- //Because OpenGL and cocos2d-x uses different Y axis, we need to convert the coordinate here
- float 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)----启动渲染流程 博文分析中可以看到的.
cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析的更多相关文章
- cocos2d-x 事件分发机制 ——加速计事件监听
加速计事件监听机制 在上一篇中介绍了cocos2d-x中的触摸事件机制,这篇来介绍下游戏中也常常常使用到的加速计事件,这些都是游戏中的常常要用到的. 移动设备上一个非常重要的输入源是设备的方向.大多数 ...
- cocos2d-x 事件分发机制 ——触摸事件监听
cocos2d-x 3.0 出来已经好久了,也已经用3.0写了几个小游戏,感觉3.0的事件触发机制太赞了,随这里总结一下.也算是对知识的一种回顾和加深理解. 3.0的事件分发机制中.须要也只须要通过创 ...
- 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher
一.简介 最近马三换了一家大公司工作,公司制度规范了一些,因此平时的业余时间多了不少.但是人却懒了下来,最近这一个月都没怎么研究新技术,博客写得也是拖拖拉拉,周六周天就躺尸在家看帖子.看小说,要么就是 ...
- 本以为精通Android事件分发机制,没想到被面试官问懵了
文章中出现的源码均基于8.0 前言 事件分发机制不仅仅是核心知识点更是难点,并且还是View的一大难题滑动冲突解决方法的理论基础,因此掌握好View的事件分发机制是十分重要的. 一.基本认识 1. 事 ...
- Android事件分发机制源码分析
Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...
- Android面试收集录6 事件分发机制
转自:秋招面试宝典. 一. 基础认知 1.1 事件分发的对象是谁? 答:事件 当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件). Touch事件相关细节(发 ...
- Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
Android事件分发机制可以说是我们Android工程师面试题中的必考题,弄懂它的原理是我们避不开的任务,所以长痛不如短痛,花点时间干掉他,废话不多说,开车啦 Android事件分发机制的发生在Vi ...
- 浅谈Android中的事件分发机制
View事件分发机制的本质就是就是MotionEvent事件的分发过程,即MotionEvent产生后是怎样在View之间传递及处理的. 首先介绍一下什么是MotionEvent.所谓MotionEv ...
- cocos2d-x游戏引擎核心之五——触摸事件和触摸分发器机制
一.触摸事件 为了处理屏幕触摸事件,Cocos2d-x 提供了非常方便.灵活的支持.在深入研究 Cocos2d-x 的触摸事件分发机制之前,我们利用 CCLayer 已经封装好的触摸接口来实现对简单的 ...
随机推荐
- 咖啡之约--体验 SourceAnywhere
http://www.damingsoft.com/campaign/school-campaign-coffee-code.aspx 必备技能:代码版本控制 不论你是菜鸟还是大牛,想要获得高薪水和高 ...
- 微信小程序无法获取UnionId的情况及处理
问题背景:做了微信小程序,一切都还正常,但是最后体验版放出去时,却发现很多用户无法绑定用户,后台返回:参数非法.经过多方排查,发现是微信拿到的code请求返回的数据里没有UnionId,也就是接口返回 ...
- Morris图表使用小记
挺好用的,碰到几个问题,有的是瞎试解决了的: 1.我想折线图能够响应单击事件,即点击某个节点后,就能加载进一步的信息,帮助没找到,参照另外一个地方的写法,居然支持事件 Morris.Line({ el ...
- 微软BI 之SSRS 系列 - 如何在 MDX 查询中获取有效的 MEMBER 成员属性作为参数传递
这篇小文章的来源是 天善问答,比如在报表中要根据点击某一个成员名称然后作为参数传递给自身报表或者下一张报表,这个在普通的 SQL 查询中没有任何问题.但是在 MDX 中查询是有区别的,比如在 MDX ...
- Ubuntu中安装和配置 Java JDK,并卸载自带OpenJDK(以Ubuntu 14.04为例)
1.下载jdk-7u67-linux-x64.tar.gz 2.用ftp客户端工具filezilla上传到ubuntu的合适文件夹.如果如果不能上传到指定文件夹可能是文件夹权限不足,修改文件夹可执行权 ...
- 配置Windows Server 2008/2012/2016允许2个用户同时远程桌面
Windows Server 系列服务器默认情况下只能支持一个用户远程,如果第二个人远程上去之后会直接把前面一个登录用户踢掉.在日常工作中如果有多个人需要同时远程过去工作,会很不方面. 网上很多教程讲 ...
- 服务端怎样暴露IBinder接口对象
服务端怎样暴露IBinder接口对象: package com.example.mydownload; import android.app.Service; import android.conte ...
- C# 重启exe
休夸此地分天下 c# 关闭和重启.exe程序 Process[] myprocess = Process.GetProcessesByName("a"); )//判断如果存在 { ...
- JAVA和JAVAC 命令行
转自:http://www.blogjava.net/pdw2009/archive/2008/06/12/207413.html?opt=admin javac和java命令行中的-classpat ...
- Fluent动网格【4】:DEFINE_CG_MOTION宏实例
DEFINE_CG_MOTION宏通常用于定义刚体部件的运动.本文以一个简单的案例描述DEFINE_CG_MOTION的使用方法. 案例描述 本次计算的案例如图所示.在计算域中有一个刚体块(图中的小正 ...