游戏跟视频最大的区别就是互动,而手游(基于智能手机)主要靠触摸屏幕、重力传感和虚拟键盘等方式实现互动。这里主要记录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. Android Studio快捷键switch case 轻松转换为if else

    Android Studio快捷键switch case 轻松转换为if else 今天碰到的问题,没有找到资料,后面找到了方法,这个记下来,转载请注明出处:http://www.cnblogs.co ...

  2. java环境变量配置

    1.打开我的电脑--属性--高级--环境变量 2.新建系统变量JAVA_HOME 和CLASSPATH 变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.7.0 ...

  3. WebStorm调试node.js

    直接上图:

  4. Sql获取数据集中各类型中的最大值(最新值)

    select * from  (    SELECT t.*,ROW_NUMBER() over (partition by t.pid order by t.op_time desc) num    ...

  5. POJ2472106 miles to Chicago

    106 miles to Chicago Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3931   Accepted: 1 ...

  6. DOM based XSS Prevention Cheat Sheet(DOM Based XSS防御检查单)

    本文为翻译版本,原文请查看 https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet 介绍 谈到XSS攻击,有三种公认的 ...

  7. Web Service 通过BinaryFormatter序列化和反序列化泛型List

    1.序列化和反序列化的扩展方法如下: using System; using System.Collections.Generic; using System.Linq; using System.T ...

  8. WM (Constants)

    Create page WM (Constants)   Summary WM_* Constants and their definitions or descriptions and what c ...

  9. bootstrap-按钮样式

    <div class="container"> <!-- 按钮的背景色 --> <div class="row"> < ...

  10. 第五节:什么导致Finalize方法被调用

    Finalize方法在垃圾回收结束时被调用,下面有5种事件会导致开始垃圾回收 1.第0代已满    第0代已满,垃圾回收会自动开始.该事件是目前导致Finalize方法被调用的最常见的一种方式,因为虽 ...