(一) 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机制).

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

(二) 上面针对的是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的过程浅析的更多相关文章

  1. cocos2d-x 事件分发机制 ——加速计事件监听

    加速计事件监听机制 在上一篇中介绍了cocos2d-x中的触摸事件机制,这篇来介绍下游戏中也常常常使用到的加速计事件,这些都是游戏中的常常要用到的. 移动设备上一个非常重要的输入源是设备的方向.大多数 ...

  2. cocos2d-x 事件分发机制 ——触摸事件监听

    cocos2d-x 3.0 出来已经好久了,也已经用3.0写了几个小游戏,感觉3.0的事件触发机制太赞了,随这里总结一下.也算是对知识的一种回顾和加深理解. 3.0的事件分发机制中.须要也只须要通过创 ...

  3. 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher

    一.简介 最近马三换了一家大公司工作,公司制度规范了一些,因此平时的业余时间多了不少.但是人却懒了下来,最近这一个月都没怎么研究新技术,博客写得也是拖拖拉拉,周六周天就躺尸在家看帖子.看小说,要么就是 ...

  4. 本以为精通Android事件分发机制,没想到被面试官问懵了

    文章中出现的源码均基于8.0 前言 事件分发机制不仅仅是核心知识点更是难点,并且还是View的一大难题滑动冲突解决方法的理论基础,因此掌握好View的事件分发机制是十分重要的. 一.基本认识 1. 事 ...

  5. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  6. Android面试收集录6 事件分发机制

    转自:秋招面试宝典. 一. 基础认知 1.1 事件分发的对象是谁? 答:事件 当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件). Touch事件相关细节(发 ...

  7. Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

    Android事件分发机制可以说是我们Android工程师面试题中的必考题,弄懂它的原理是我们避不开的任务,所以长痛不如短痛,花点时间干掉他,废话不多说,开车啦 Android事件分发机制的发生在Vi ...

  8. 浅谈Android中的事件分发机制

    View事件分发机制的本质就是就是MotionEvent事件的分发过程,即MotionEvent产生后是怎样在View之间传递及处理的. 首先介绍一下什么是MotionEvent.所谓MotionEv ...

  9. cocos2d-x游戏引擎核心之五——触摸事件和触摸分发器机制

    一.触摸事件 为了处理屏幕触摸事件,Cocos2d-x 提供了非常方便.灵活的支持.在深入研究 Cocos2d-x 的触摸事件分发机制之前,我们利用 CCLayer 已经封装好的触摸接口来实现对简单的 ...

随机推荐

  1. [CGAL]带岛多边形三角化

    CGAL带岛多边形三角化,并输出(*.ply)格式的模型 模型输出的关键是节点和索引 #include <CGAL/Triangulation_vertex_base_with_id_2.h&g ...

  2. yolov3源码darknet在vscode下调试

    1. 安装配置: https://pjreddie.com/darknet/yolo/ darknet文件夹下make命令搞定: 2. 配置vscode 打开安装好的vscode并安装扩展C/C++( ...

  3. tensorflow之数据读取探究(2)

    tensorflow之tfrecord数据读取 Tensorflow关于TFRecord格式文件的处理.模型的训练的架构为: 1.获取文件列表.创建文件队列:http://blog.csdn.net/ ...

  4. Excel分组快速自动填充编号

    在Excel自动填充很简单,但如果按分组等条件进行填充就有点麻烦了 说麻烦可能是你并没有搞清楚到底如何才能实现你的需求   下图是客户提供的Excel数据,我需要将下面的数据导入到数据库中,因为客户在 ...

  5. python3用BeautifulSoup用limit来获取指定数量的a标签

    # -*- coding:utf-8 -*- #python 2.7 #XiaoDeng #http://tieba.baidu.com/p/2460150866 #标签操作 from bs4 imp ...

  6. shell变量的截取总结

    #shell变量的截取 Shell中的${}.##和%% 假设定义了一个变量为: 代码如下: file=/dir1/dir2/dir3/my.file.txt //变量的删除 可以用${ }分别替换得 ...

  7. Vue中CSS模块化最佳实践

    Vue风格指南中介绍了单文件组件中的Style是必须要有作用域的,否则组件之间可能相互影响,造成难以调试. 在Vue Loader Scope CSS和Vue Loader CSS Modules两节 ...

  8. 【Android】解析Android的路径

    目录结构: contents structure [+] 内部路径 外部路径 Assets目录 Android中的路径主要分为内部路径和外部路径. 一.内部路径 常见的内部存储路径有: File f1 ...

  9. SQL Server 数据库基础笔记分享(下)

    前言 本文是个人学习SQL Server 数据库时的以往笔记的整理,内容主要是对数据库的基本增删改查的SQL语句操作和约束,视图,存储过程,触发器的基本了解. 注:内容比较基础,适合入门者对SQL S ...

  10. MySQL权限和用户安全

    MySQL访问控制分为两个阶段阶段1: 检查用户是否可以连接到mysql server 阶段2: 检查用户执行的sql是否已经被授权