游戏跟视频最大的区别就是互动,而手游(基于智能手机)主要靠触摸屏幕、重力传感和虚拟键盘等方式实现互动。这里主要记录Cocos2D-x对玩家触屏操作的处理。

在Cocos2D-x中触屏分为单点触屏和多点触屏,下面介绍一下与触屏相关的几个类、触屏事件和流程。

·CCTouch(触屏点类):这个类用于封闭触屏点,通过它的locationInView方法返回当前触屏点CCPoint。它还记录上一个触屏点。

·CCTouchDelegate(触屏代理协议类):它是触屏事件委托,系统捕捉到触屏事件后交由它或者它的子类处理。所以我们在处理触屏事件时,必须继承并实现其接口。看一下CCTouchDelegate的类继承关系图,如下:

   
    这里CCStandardTouchDelegate专门用于处理多点触屏,CCTargetedTouchDelegate专门用于处理单点触屏,它们都是
CCTouchDelegate的子类。
    再看一下CCTouchDelegate定义的接口方法,如下:
class CC_DLL CCTouchDelegate
{
    //单点触屏事件
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent); return false;};//触摸开始调用
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}//触屏移动调用
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}//触屏结束调用
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}//触屏取消调用
    //多点触屏事件
     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}//触摸开始调用
     virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}//触屏移动调用
     virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}//触屏结束调用
     virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}//触屏取消调用
};
   值得一提的是,ccTouchCancelled和ccTouchesCancelled方法很少使用,在接到系统中断通知,需要取消触屏事件时才会调用。
 
·CCTouchDispatcher(触屏事件分发类):这个类实现触屏事件的分发,它相当于是CCTouchDelegate的容器,负责管理多个触屏事件对象,如触屏事件优先级、添加或删除触屏事件。
·CCTouchHandler(触屏事件处理器):它其实就是对CCTouchDelegate的封闭,增加支持触屏事件优先级,优先级越高,分发的时候越容易获得触屏事件响应。
 
  介绍了这么多触屏相关的类,那么用户想要使用触屏事件,应该做哪些操作呢?
  1)继承于CCTouchDelegate类;
  2)添加注册和销毁触屏事件,一般在对象初始化时注册,在对象删除时销毁;
     注册:pDirector->getTouchDispatcher()->addTargetedDelegate(this,0,true)
//addTargetedDelegate方法
void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)
{   
    CCTouchHandler *pHandler = CCTargetedTouchHandler::handlerWithDelegate(pDelegate, nPriority, bSwallowsTouches);
    if (! m_bLocked)
    {
        forceAddHandler(pHandler, m_pTargetedHandlers);
    }
    else
    {
       ... ...
    }
}
//forceAddHandler方法
void CCTouchDispatcher::forceAddHandler(CCTouchHandler *pHandler, CCArray *pArray)
{
    unsigned int u = 0;
 
    CCObject* pObj = NULL;
    CCARRAY_FOREACH(pArray, pObj)
     {
         CCTouchHandler *h = (CCTouchHandler *)pObj;
         if (h)
         {
             if (h->getPriority() < pHandler->getPriority())
             {
                 ++u;
             }
 
             if (h->getDelegate() == pHandler->getDelegate())
             {
                 CCAssert(0, "");
                 return;
             }
         }
     }
 
    pArray->insertObject(pHandler, u);
}
从上面代码知,CCTouchHandler将CCTouchDelegate进行了一次封装,然后CCTouchDispatcher将CCTouchHandler添加到了m_pTargetedHandlers容器中。这里需要注意的是,在注册时有两个参数,一个是nPriority表示触屏优先级(值越小优先级越高),一个是bSwallowsTouches表示是否允许触屏。
     销毁:pDirector->getTouchDispatcher()->removeDelegate(this)
  3)处理触屏事件:实现CCTouchDelegate类接口,在方法中填写触屏事件处理。
     当用户触摸屏幕,CCTouchDispatcher是如何将触屏事件分发给指定的CCTouchDispatcher子类对象进行处理,调用相应的触屏事件呢?
     可以知道CCTouchDispatcher继承于EGLTouchDelegate类。EGLTouchDelegate类是一个接口类,定义如下:
class CC_DLL EGLTouchDelegate
{
public:
    virtual void touchesBegan(CCSet* touches, CCEvent* pEvent) = 0;
    virtual void touchesMoved(CCSet* touches, CCEvent* pEvent) = 0;
    virtual void touchesEnded(CCSet* touches, CCEvent* pEvent) = 0;
    virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent) = 0;
 
    virtual ~EGLTouchDelegate() {}
};
  现在应该弄明白了,当用户触摸屏幕时,系统将触发相应的触屏事件,平台底层会调用CCTouchDispatcher的相应的触屏事件分发方法,将触屏事件分发到指定触屏事件响应对象中,由该对象写成触屏事件的响应处理。
  我们再看一下,CCTouchDispatcher是如何分发,如何找到m_pTargetedHandlers容器里对应的CCTouchHandler呢?还是看代码,如下:
void CCTouchDispatcher::touchesBegan(CCSet *touches, CCEvent *pEvent)
{
    if (m_bDispatchEvents)
    {
        this->touches(touches, pEvent, CCTOUCHBEGAN); //这才是真正的触屏事件分发方法
    }
}
 
  触屏相关的内容差不多就这些了吧,我想现在想要添加触屏事件,应该是一件很轻松和愉快的事。需要提及的是在TestCpp工程的MutiTouchTest测试项有多点触屏的代码实例,如果对多点触屏感兴趣可以研究一下。
-------------------------------------------------------------------------------------------------------------------

注:本人在本博客的原创文章采用创作共用版权协议http://creativecommons.org/licenses/by-nc-sa/2.5/cn/), 要求署名、非商业用途和保持一致。要求署名包含注明我的网名及文章来源(我的博客地址:http://www.cnblogs.com/binbingg)。

[原创]cocos2d-x研习录-第三阶 特性之触屏的更多相关文章

  1. [原创]cocos2d-x研习录-第三阶 特性之按键与虚拟键盘

    Cocos2D-x引擎支持按键事件,它能检测设备的键盘输入并处理相应的事件.而基于不同操作系统的移动设备,可供用户操作的按键数量和功能都存在差异.   Cocos2D-x使用CCKeypadDeleg ...

  2. [原创]cocos2d-x研习录-第三阶 特性之物理引擎

    游戏物理引擎是指在游戏中涉及物理现象的逻辑处理,它用于模拟现实世界的各种物理规律(如赛车碰撞.子弹飞行.物体掉落等),让玩家能够在游戏中有真实的体验. Cocos2D-x中支持Box2D和Chipmu ...

  3. [原创]cocos2d-x研习录-第三阶 特性之粒子系统

    我想接触过游戏引擎的同学,对粒子系统应该不会陌生.它用于解决由大量按一定规则运动(变化)的微小物质在计算机上的生成和显示问题.粒子系统在游戏中有着非常广泛的应用,可以模拟很多现象,如火花.爆炸.烟雾. ...

  4. [原创]cocos2d-x研习录-第三阶 特性之瓦片地图集

    由于一张大的世界地图或背景图片往往可以由屈指可数的几种地形来表示,每种地形对应于一张小的图片,我们称这些小的地形图片为瓦片.把这些瓦片拼接在一起,组合成一个完整的地图,这就是瓦片地图集的基本原理. C ...

  5. [原创]cocos2d-x研习录-第三阶 特性之调度器

    在游戏中,经常会周期执行一些检测.操作或更新一些数据等,我们称之为调度.Cocos2D-x中将调度封装为类CCScheduler,方便在游戏开发中使用.我们一起来学习一下,CCScheduler具有哪 ...

  6. [原创]cocos2d-x研习录-第三阶 特性之动作

    在前面的Cocos2D-x的概念类中,我们了解到节点类CCNode.导演类CCDirector.场景类CCScene.布景层类CCLayer和精灵类CCSprite等,这些类都是构成游戏画面的基本元素 ...

  7. [原创]cocos2d-x研习录-第三阶 特性之加速度传感器

    智能手机的游戏与应用中,也经常会用到加速传感器事件来丰富用户的体验,比如飞翔的企鹅(英文AirPenguin)游戏就是通过加速度传感器来控制角色的移动和跳跃方向.下面学习Cocos2D-x中如何使用加 ...

  8. [原创]cocos2d-x研习录-第三阶 多分辨率适配器

    在移动终端(智能手机)平台下开发游戏一般都会涉及到屏幕多分辨率适配问题,原因是手机款式多种多样,不同的款式存在有不同的尺寸,即使尺寸相同又可能存在不同的分辨率. 手机屏幕尺寸:指手机屏幕对角线长度. ...

  9. [原创]cocos2d-x研习录-第三阶 背景音乐和音效

    在游戏中,音效是一个不可或缺的部分,它可以为我们的游戏增加效果.音效在游戏中一般分为长时间的背景音乐和短促的特效音乐.Cocos2D-x支持多种常见音乐格式(mp3.wav等). Cocos2D-x提 ...

随机推荐

  1. [Git] 怎么使用Git让代码回到以前的某个节点

    我们可以使某个文件回到以前的某个节点,也可以使整个文件夹下面的文件都回到以前的某个节点,下面只介绍某个文件的,全部的类似. 按步骤操作完成后本地你选中的文件会变成红色,此时的代码还是原来的代码,但是G ...

  2. 安装solidity遇见的问题——unused variable 'returned'

    在编译安装solidity的过程中遇见了一个很奇怪的问题 webthree-umbrella/libethereum/libethereum/Executive.cpp: In member func ...

  3. linux文件复制与权限赋值

    文件file内容赋值到file2中 1. cp  file1  file2 2. cat file1 > file2 3. cat < file1 > file2 4. dd if= ...

  4. mysql 配置 utf8 依然乱码

    mysql 乱码问题排除方案: 1.检查数据库及数据表是不是utf8字符集 2.查看一下jdbc.properties配置的数据库url 是否配置了characterEncoding=UTF-8或者在 ...

  5. jquery异步加载json格式的数据

    1.直接使用$.getJSON()方法是加载不了与静态界面同级别的本地的json后缀的文件. 2.解决办法:将json后缀的文件改为js后缀,这样就相当于加载了一个js文件. 解决办法:用$.getS ...

  6. SAP模块常用增强总结{转载}

    MM模块: 采购订单增强: BADI :ME_GUI_PO_CUST ME_PROCESS_PO_CUST 物料凭证增强: BADI:MB_DOCUMENT_BADI USER-EXIT:MBCF00 ...

  7. hdu 1532(最大流)

    Drainage Ditches Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. Hilbert space

    Definition A Hilbert space H is a real or complex inner product space that is also a complete metric ...

  9. docker 会这些也够

    $ sudo systemctl start docker $ sudo systemctl stop docker $ sudo systemctl restart docker If you wa ...

  10. JVM-并发-线程安全与锁优化

    线程安全与锁优化 1.线程安全 (1)当多个线程访问一个对象时,如果不考虑这些线程在执行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获 ...