Cocos2dx引擎8-事件处理

本文从主要介绍点击事件的处理过程,分别从win32、Android、IOS系统介绍Cocos2dx点击事件处理过程。

1、Win32系统

 AppDelegate::applicationDidFinishLaunching()->GLView::create(…)->GLView::initWithRect(…)
bool GLView::initWithRect(conststd::string& viewName, Rect rect, float frameZoomFactor){
    ………
glfwSetMouseButtonCallback(_mainWindow,
                    GLFWEventHandler::onGLFWMouseCallBack);
………
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

在win32系统中点击事件为鼠标点击事件,使用glfwSetMouseButtonCallback绑定鼠标点击事件的时间处理函数;

static voidonGLFWMouseCallBack(GLFWwindow* window, int button, int action, int modify){
if (_view) _view->onGLFWMouseCallBack(window,button, action, modify);
}
voidGLView::onGLFWMouseCallBack(GLFWwindow* window, int button, int action, intmodify){
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);
        }
    }elseif(GLFW_RELEASE == action) {  //鼠标左键松开时
        if(_captured) {
           _captured = false;
           intptr_t id = 0;
           this->handleTouchesEnd(1, &id, &_mouseX, &_mouseY);
        }
    }
}
………//处理鼠标事件
}

上面的处理方法代码位于cocos2d\cocos\platform\win32\ CCGLView.cpp中;

2、Android系统

public class Cocos2dxGLSurfaceView extends GLSurfaceView {
    ……
    public booleanonTouchEvent(final MotionEvent pMotionEvent) {
        ……….
        switch(pMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
            ……
            caseMotionEvent.ACTION_DOWN:   //按下事件
                this.queueEvent(newRunnable() {    //新起一个线程处理该事件
                    publicvoid run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown
(idDown, xDown,yDown);
                    }
                });
                break;
…………….
            caseMotionEvent.ACTION_UP: //抬起事件
                this.queueEvent(newRunnable() {
                    publicvoid run() {
                        Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp
(idUp, xUp, yUp);
                    }
                });
                break;
…………
        }
        return true;
    }
}

Cocos2dxGLSurfaceView继承View类,实现View中关于触摸屏事件处理函数onTouchEvent,当有触摸屏事件发生时会调用Cocos2dxGLSurfaceView中onTouchEvent方法,在onTouchEvent方法中会区分Down&Up事件,并使用新的线程执行Cocos2dxRenderer类中handleActionDown&handleActionUp方法;

public class Cocos2dxRenderer implements GLSurfaceView.Renderer{
    private static native void nativeTouchesBegin(final int pID, final float pX, final float pY);
    private static native void nativeTouchesEnd(final int pID, final float pX, final float pY);
    public void handleActionDown(finalint pID, final float pX, final float pY) {
        Cocos2dxRenderer.nativeTouchesBegin(pID,pX, pY);
    }
    public voidhandleActionUp(final int pID, final float pX, final float pY) {
        Cocos2dxRenderer.nativeTouchesEnd(pID,pX, pY);
    }
}

在Cocos2dxRenderer类中的handleActionDown&handleActionUp方法会通过JNI调用C++实现的nativeTouchesBegin&nativeTouchesEnd方法;

nativeTouchesBegin&nativeTouchesEnd分别对应

cocos2d\cocos\platform\android\jni\TouchesJni.cpp文件中:

JNIEXPORT voidJNICALL
Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv * env, jobject thiz, jint id, jfloatx, jfloat y) {
       cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1,&id, &x, &y);
    }
JNIEXPORT voidJNICALL
Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd(JNIEnv * env, jobject thiz, jint id, jfloatx, jfloat y) {
       cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1,&id, &x, &y);
}

3、IOS系统

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    ……
    glview->handleTouchesBegin(i,(intptr_t*)ids, xs, ys);
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
   ……
    glview->handleTouchesEnd(i,(intptr_t*)ids, xs, ys);
}

以上方法在cocos2d\cocos\platform\ios\CCEAGLView.mm中实现;

4、Cocs2dx事件处理

上文中handleTouchesBegin和handleTouchesEnd处理在Win32、Android、IOS中是相同的实现,接下来会继续分析;

voidGLViewProtocol::handleTouchesBegin(int num, intptr_t ids[], float xs[], floatys[]){   //点击按下时执行
    intptr_t id = 0;
    float x = 0.0f;
    float y = 0.0f;
    int unusedIndex = 0;
    EventTouch touchEvent;
    for (int i = 0; i < num; ++i)//遍历所有的触摸点,若多点触摸则需要
    {
        id = ids[i];
        x = xs[i];
        y = ys[i];
        //在本地Touch字典中查询该touch是否已经存在
        auto iter = g_touchIdReorderMap.find(id);
        // 如果是一个新Touch
        if (iter == g_touchIdReorderMap.end())
        {
            unusedIndex = getUnUsedIndex();//获取新Touch标记符
            ……
            //收集Touch信息
            Touch* touch =g_touches[unusedIndex] = new Touch();
            touch->setTouchInfo(unusedIndex,(x - _viewPortRect.origin.x) / _scaleX,
                                     (y -_viewPortRect.origin.y) / _scaleY);

            CCLOGINFO("x = %f y =%f", touch->getLocationInView().x, touch->getLocationInView().y);
            //将当前Touch添加入Touch查询字典中
           g_touchIdReorderMap.insert(std::make_pair(id, unusedIndex));
           touchEvent._touches.push_back(touch);
        }
    }
    ……
    touchEvent._eventCode =EventTouch::EventCode::BEGAN;
    auto dispatcher =Director::getInstance()->getEventDispatcher();
   dispatcher->dispatchEvent(&touchEvent);//分发Touch事件
}

在handleTouchesBegin中:

(1)查询点击是否已经存在

(2)若点击记录中不存在当前点击,则收集点击信息,分发TouchBegin事件

在过程(1)中单点点击中传入的ids={0},点击事件是存储在touchIdReorderMap[0]位置,这么做事防止出现点击同一个位置时未释放前,出现点击其他位置从而调用handleTouchesBegin;

voidGLViewProtocol::handleTouchesEnd(int num, intptr_t ids[], float xs[], floatys[]){ //点击释放时执行
   handleTouchesOfEndOrCancel(EventTouch::EventCode::ENDED, num, ids, xs,ys);
}
void GLViewProtocol::handleTouchesOfEndOrCancel(EventTouch::EventCodeeventCode, int num, intptr_t ids[], float xs[], float ys[])
{
    intptr_t id = 0;
    float x = 0.0f;
    float y = 0.0f;
    EventTouch touchEvent;
    for (int i = 0; i < num; ++i) //遍历所有的触摸点,若多点触摸则需要
    {
        id = ids[i];
        x = xs[i];
        y = ys[i];
        //查询该释放事件对应的点击事件是否存在
        auto iter =g_touchIdReorderMap.find(id);
       ……
        Touch* touch =g_touches[iter->second];
        if (touch) {
           touch->setTouchInfo(iter->second,(x - _viewPortRect.origin.x) / _scaleX,
                                (y -_viewPortRect.origin.y) / _scaleY);
           touchEvent._touches.push_back(touch);
            g_touches[iter->second] =nullptr;
            removeUsedIndexBit(iter->second);
            g_touchIdReorderMap.erase(id);//移除已经释放点击事件
        }
        ……
    }
   ……
    touchEvent._eventCode = eventCode;
    auto dispatcher =Director::getInstance()->getEventDispatcher();
   dispatcher->dispatchEvent(&touchEvent);//派发点击释放事件

    for(auto& touch : touchEvent._touches) {//释放点击
        touch->release();
    }
}

在handleTouchesOfEndOrCancel中:

(1)查询点击是否已经存在

(2)若点击记录存在点击,则收集点击信息,分发TouchEnd事件

因为在单点点击中传入的ids={0},只有查询到该点击事件存在才会执行释放操作,最后会将点击事件从g_touchIdReorderMap移除,保证在调用ToucheEnd之前一定有TouchBegin。

时间: 2024-10-13 22:16:59

Cocos2dx引擎8-事件处理的相关文章

Cocos2dx引擎优化(1) ---音效系统

Cocos2dx提供的音频库位于CocosDenshion中,其接口由SimpleAudioEngine定义,提供了基本的背景音乐和音效播放. SimpleAudioEngine的实现是夸平台的, 在windows平台上由mci相关API实现; 在android平台上透过JNI,调用android sdk 中的AudioPlayer实现;而在IOS平台上由Cocoa sdk里的Core-Audio实现.但SimpleAudioEngine并不适用于大部分游戏情境,它在Android上的实现需要直

Cocos2dx引擎优化(2) ---自定义资源包系统

把游戏中的资源文件(纹理,模型,材质,音乐,配置xml,json,脚本)打包有很多好处,也成为MMO开发的基本常识.对资源进行打包可以带来以下好处: . 增加游戏资源和脚本破解的难度.大多游戏制作公司都不希望自己花高昂代价制作的资料被人全盘爬过去使用,更不忍受逻辑脚本完全暴露在同行的面前. . 自定义的资源包比访问散文件资源有更快的查找和读取速度,消耗更少的系统资源,如文件句柄. . 自定义资源包可以提供更简单可用的文件存取API.加解密和压缩方案. . 一般来说,打包的资源也会比散文件形式的资

Cocos2d-x学习笔记(十六)--------&gt;Cocos2d-x引擎中的网格地图

网格地图 2D游戏网格地图介绍: 在网格地图游戏中,地图由称为"瓷砖"(tile)的一小组图片相互排列组成.这些图片放在一个整体的网格中.得到一个令人信服的游戏场景.网格地图技术为开发者提供了很多便利,使用很少的网格图片元素,就可以组成非常大的场景地图,而且这些大场景并不会浪费硬件资源.而且根据网格元素的不同,可以得到多种多样的场景地图. 网格地图主要分为两大类: 第一类是90度网格地图(Orthogonal Tilemap),这类地图都是使用正方形或者长方形的瓷砖(Tile)组成的,

cocos2dx基础篇(4)——浅析cocos2dx引擎目录

通过前面几节的学习,相信大家都已经配置好了VS+cocos2dx2.2.3的环境,并且成功运行了官方的案例HelloWorld. 一.窥探文件目录 要想学好cocos2dx,首先就需要对引擎目录下的各个文件有所了解.接下来,就让我们先来分析一下cocos2dx2.2.3引擎的文件目录吧. 从目录中我们主要了解一下一下几个文件: cocos2dx:cocos2d-x引擎的核心部分,存放了引擎的大部分源文件. CocosDenshion:声音模块相关源文件. Debug.win32:在Windows

送给刚刚开始学cocos2d-x引擎 移植Android的同学

刚刚开始学cocos2-x,仅仅是按照教程把已经安了一般Android的开发环境的eclipse重新升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 参考博客 D:\cocos2d-x\cocos2d-x-2.2.3\cocos2dx\platform\third_party\android\prebuilt 说说大概的过程: 下载ndk插件,ndk包,cdt插件.最开始我按照书上的下载了cocos2d-x 2.0.1,希望跟书上统一起来,这样以后学习的时候可以参考书上的也不会遇到太

Android Cocos2dx引擎 prv.ccz/plist/so等优化缓存文件,手把手ida教你逆向project反编译apk库等文件

前段时间在 Android play 上看到一个非常牛逼的 3D 动态天气预报,效果真的非常炫.二话不说动手 dex2jar.bat/apktool 发现这并没 有什么卵用,在核心的地方看见 native 字段果断放弃了治疗,立刻转向 so 的逆向project.发现了cocos2dx so 引擎,搜噶.我就说 嘛这么炫酷的效果, Android 源代码是做不了的.即使达到了这样的程度,预计性能也特别不好.由于那个动态效果是不会循环播放 的,也就是不会反复.是自己绘制的依据资源文件,在反编译的

Cocos2dx引擎11-OpenGLES渲染之Shader准备

Cocos2dx底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集,针对手机,PDA和游戏主机等嵌入式设备而设计.该API有Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. OpenGL ES是从OpenGL剪裁或定制过来了,去除了glBegin/glEnd,四边形(GL_QUADS),多边形(GL_PO

Cocos2d-x学习笔记—事件处理机制

Cocos2d-x学习笔记-事件处理机制 一:事件处理机制 一个事件由触发到完成响应,主要由以下三部分组成: 事件分发器EventDispatcher: 事件类型EventTouch.EventKeyboard等: 事件监听器EventListenerTouch.EventListenerKeyboard等. 在Cocos2d-x v3.x中,关于事件的东西,无非就是围绕上述的三个部分展开来的,掌握了上述的三个部分,也就掌握了Cocos2d-x v3.x中事件处理的精髓. (1)事件分发器: 事

Cocos2dx引擎12-OpenGLES渲染之LayerColor

在前面微博中讲述了Cocos2dx引擎OpenGL渲染准备Shader方面,本博客中将使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerColor元素到游戏中: autolayerColor = LayerColor::create(Color4B(255, 0, 0, 255), 100, 100); layerColor->setPosition(100,100); this->addChild(layerColor); 下面是Laye