Cocos2D-X事件处理机制之触屏事件

原址:http://blog.csdn.net/pj1258/article/details/14521659


游戏主要是玩家和程序的交流。无论你的动画做得多么生动,特效做得如何炫,游戏还是要和玩家进行互动和交

流。在智能手机中,主要的输入操作是通过触摸屏幕、重力感应等方式实现的,而输入文字主要通过虚拟键盘等实现

的。下面就让我们一起来学习触屏事件的使用。

 

 

一、触屏事件

 

      在Cocos2D-X中,继承自触屏代理协议CCTouchDelegate的布景层类CCLayer可以检测触屏事件并调用回调函

数。首先来看CCTouchDelegate类的继承关系,如下图所示。

 

        CCTouchDelegate的子类中,CCStandardTouchDelegate协议是标准的获得多点触摸点的范例,

CCTargetedTouchDelegate不用处理触摸点的集合,它是返回单点的。

       但是需要注意的是,CCTargetedTouchDelegate并没有屏蔽多点触摸,而是将多点离散成了单点,同时传递过来

了。可以在开始触摸的函数中返回true来实现之后获得的触摸点肯定是自己的。此外,我们常用的类是布景层类

CCLayer,也就是说,在布景层类中可以重写ccTouchesBegan等函数获得触屏的信息。

 

 

二、触屏事件监听函数

 

1、在CCDirector类中有如下函数。

<1> addTargetedDelegate(CCTouchDelegate * pDelegate,int nPriority,bool bSwallowsTouches)

作用:在Dispatcher的列表中注册一个触屏事件的委托,用以监听用户的触屏事件。

参数1:触屏事件委托CCTouchDelegate目标。

参数2:优先级(其值越小优先级越高,优先级越高越早被响应)。

参数3:是否拦截触屏事件。

 

     当第3个参数为true时,表示对本次触屏事件进行拦截,也就是说当触屏事件响应了本次触屏委托后,不会再继续

将此触屏事件分发响应到Dispatcher列表中的其他委托中。

     如果CCNode使用了CCTouchDelegate接口,并且注册了触屏委托,那么当用户触摸手机屏幕后,Cocos2D-X会

从当前设备拦截到此事件,并开始遍历Dispatcher的列表,逐一对注册过的CCNode进行响应对应的触屏事件。

 

 

2、一般触屏事件分为三种。

 

<1> bool virtual bool ccTouchBegan(CCTouch * touch,CCEvent * event)

作用:当用户手指第一次触碰到手机屏幕时响应的回调函数。

返回值:bool类型。当返回true时,表示继续响应ccTouchMoved、ccTouchEnded事件;当返回false时,则不再继

响应这两个事件。

 

<2> virtual bool ccTouchMoved(CCTouch * touch,CCEvent * event)

作用:当用户手指在手机屏幕上进行移动(拖动)时响应的回调函数。

 

<3> virtual bool ccTouchEnded(CCTouch * touch,CCEvent * event)

作用:当用户手指在手机屏幕上离开、抬起响应的回调函数。

参数1:CCTouch包含用户触屏点坐标。

 

 

注意:由于CCLayer默认使用了CCTouchDelegate触屏委托,所以继承CCLayer的子类无须再次使用此接口。

 

 

 

三、单点触摸实例

 

1、接下来,让我们以项目实例来实现一个精灵自动移动到用户触屏位置的功能。

 

<1> 首先新建Cocos2D-X项目,取名为“MyCCTouch”,然后在HelloWorldScene.h文件中声明成员函数。

[cpp]  view plain copy
  1. //重写触屏回调函数  
  2.     virtual bool ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event);  
  3.     virtual void ccTouchMoved(cocos2d::CCTouch* touch, cocos2d::CCEvent* event);  
  4.     virtual void ccTouchEnded(cocos2d::CCTouch* touch, cocos2d::CCEvent* event);  
  5.       
  6.     //重写生命周期函数  
  7.     virtual void onEnter();  
  8.     virtual void onExit();  

 

<2> 在HelloWorldScene.cpp文件中的init函数中添加如下所示代码。

[cpp]  view plain copy
  1. bool HelloWorld::init()  
  2. {  
  3.     bool bRet = false;  
  4.     do   
  5.     {  
  6.         CC_BREAK_IF(! CCLayer::init());  
  7.   
  8.         CCSprite * spr = CCSprite::create("Icon.png");  
  9.         spr->setPosition(ccp(150,150));  
  10.         addChild(spr,0,922);  
  11.   
  12.         bRet = true;  
  13.     } while (0);  
  14.   
  15.     return bRet;  
  16. }  

 

<3> 最后在HelloWorldScene.cpp文件中添加如下所示函数。

[cpp]  view plain copy
  1. void HelloWorld::onEnter(){  
  2.       
  3.     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);  
  4.     CCLayer::onEnter();  
  5. }  
  6.   
  7. void HelloWorld::onExit(){  
  8.       
  9.     CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);  
  10.     CCLayer::onExit();  
  11. }  
  12.   
  13. bool HelloWorld::ccTouchBegan(CCTouch* touch, CCEvent* event)  
  14. {  
  15.     CCLOG("ccTouchBegan");  
  16.     return true;  
  17. }  
  18.   
  19. void HelloWorld::ccTouchMoved(CCTouch* touch, CCEvent* event){  
  20.     CCLOG("ccTouchMoved");  
  21. }  
  22.   
  23. void HelloWorld::ccTouchEnded(CCTouch* touch, CCEvent* event)  
  24. {  
  25.     CCLOG("ccTouchEnded");  
  26.     //获取离开屏幕时对应的坐标  
  27.     CCPoint point = touch->getLocation();  
  28.       
  29.     //获取到精tag=922的精灵  
  30.     CCSprite* sp = (CCSprite*)this->getChildByTag(922);  
  31.     //暂停所有动作  
  32.     sp->stopAllActions();  
  33.     //执行move动作到用户离开时的位置  
  34.     sp->runAction(CCMoveTo::create(1, point));  
  35. }  


对于以上代码需要着重讲解的有4点:

<1> 重写了生命周期函数onEnter与onExit,主要用于注册和移除委托。

     因为委托一般都是成对出现的,有注册就要对应有移除。如果你想对一个CCNode进行委托监听,那么创建本类时

就可以进行监听了,而当本类退出时也可以对应删除其监听。

      所以一般情况下,推荐大家将触屏事件的注册与移除代码都写在onEnter与onExit中。如果注册的委托不及时移除

掉,就有可能造成程序的异常退出

 

<2> 以上代码中,我们将精灵move逻辑写在触屏监听用户手指离开的函数ccTouchEnded中进行处理,其原因是考虑

用户体验。

        很多用户在手指第一次触摸屏幕时并不是有目的性的、或者说是尝试性地去触碰屏幕,那么如果系统很快响应了

这些用户的错误操作逻辑,用户就会比较反感,所以一般情况下,例如按钮等我们只在用户离开屏幕时进行响应。当

然,这些细微的用户体验也会根据不同类型的游戏进行改进。

 

<3> 由于Cocos2D-X是基于OpenGL ES实现的,所以在CCTouch中保存用户触屏坐标,位置是3D坐标系中的坐标,

所以需要将其转换成2D坐标。当然,Cocos2D-X也在CCTouch中为开发者提供了转换坐标的函数getLocation进行2D

坐标点的转换。

 

<4> 在上面的示例项目中,在精灵进行runAction之前,我先调用了这个精灵的stopAllActions()函数,将停止此精灵的

所有动作。很多时候游戏中的精灵会有很多不同的动作需要执行,为了防止在运行新的动作时上一个动作可能还没暂

停的情况,所以这里先对所有动作进行一个停止的操作。主要原因是当精灵同时runAction两个不同的动作时,会出现

乱掉的情况。

 

 

2、示例效果图

 

精灵会随着屏幕的点击到达指定的位置。

 

 

 

 

四、多触点事件

 

       我们学习了触屏的监听,其监听委托类为CCTargetedTouchDelegate,此接口属于单点触屏的监听委托;对于多

触点,其委托类为CCStandardTouchDelegate。

      不论是CCTargetedTouchDelegate,还是CCStandardTouchDelegate,都是CCTouchDelegate的子类,而

CCLayer默认继承了CCTouchDelegate接口,所以CCLayer的子类无须再重新使用这些接口。

 

多触点委托中的回调函数如下所示:

[cpp]  view plain copy
  1. virtual void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  
  2.     virtual void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  
  3.     virtual void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  


    其中分别对应为用户按下、移动(拖动)、抬起(离开屏幕)3种事件。在这个回调函数中,第一个参数不再是

CCTouch,而是CCTouch的集合。


遍历所有触点位置的方式如下所示:

 

[cpp]  view plain copy
  1. CCSetIterator iter = pTouches->begin();  
  2.     for (; iter != pTouches->end(); iter++)  
  3.     {  
  4.         CCTouch* pTouch = (CCTouch*)(*iter);  
  5.         CCPoint location = pTouch->getLocation();  
  6.     }  

 

 


CCTouch 有如下所示函数:

<1> int getID()

作用 :得到当前触点的下标(从0开始计数)。


在多触点委托监听时,需要注意以下3点问题:

<1> setTouchEnabled(true),开启多触点监听务必调用此函数。

<2> 在CCDirector类中添加多触点委托事件代码:

 

[cpp]  view plain copy
  1. CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(CCTouchDelegate* pDelegate,int nPriority)  

 


注意:多触点的委托注册放在onEnter的生命函数中会造成程序异常退出。默认都重写如下函数:

 

[cpp]  view plain copy
  1. virtual void registerWithTouchDispatcher(void);  

 

将多触点委托注册放在此函数中进行注册,用以指明此委托类型为多触点委托监听。


<3> 开启IOS多触点支持功能。

在IOS设备中,默认多触点是关闭的,如果我们想要在IOS设备中使用多触点,就需要开启多触点的支持。



五、多触点触摸实例


1、首先新建Cocos2D-X项目,取名为“MyMutiTouch”,然后在HelloWorldScene.h文件中声明成员函数。

 

[cpp]  view plain copy
  1. //重写多触点回调函数  
  2.     virtual void registerWithTouchDispatcher(void);  
  3.     virtual void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  
  4.     virtual void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  
  5.     virtual void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);  
  6.   
  7.     //生命周期函数  
  8.     virtual void onExit();  

 

 

2、在HelloWorldScene.cpp文件中的init函数中添加如下所示代码。

 

[cpp]  view plain copy
  1. bool HelloWorld::init()  
  2. {  
  3.     bool bRet = false;  
  4.     do   
  5.     {  
  6.         CC_BREAK_IF(! CCLayer::init());  
  7.   
  8.         //开启多触点监听务必调用此函数  
  9.         setTouchEnabled(true);  
  10.       
  11.         CCSprite * sp1 = CCSprite::create("Icon.png");  
  12.         sp1->setColor(ccc3(255, 255, 0));//便于区分  
  13.         CCSprite * sp2 = CCSprite::create("Icon.png");   
  14.         sp1->setPosition(ccp(150,100));  
  15.         sp2->setPosition(ccp(150,200));   
  16.         addChild(sp1,0,91);  
  17.         addChild(sp2,0,92);  
  18.   
  19.         bRet = true;  
  20.     } while (0);  
  21.   
  22.     return bRet;  
  23. }  

 

 

3、最后在HelloWorldScene.cpp文件中添加如下所示函数。

 

[cpp]  view plain copy
  1. //注册多触点的委托监听  
  2. void HelloWorld::registerWithTouchDispatcher(void){  
  3.     CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);  
  4. }  
  5.   
  6. //用户手指第一次触碰  
  7. void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){  
  8.     CCSetIterator iter = pTouches->begin();  
  9.     for (; iter != pTouches->end(); iter++)  
  10.     {  
  11.         CCTouch* pTouch = (CCTouch*)(*iter);  
  12.         CCPoint location = pTouch->getLocation();  
  13.         if(pTouch->getID()==0){//第一个触点  
  14.             CCSprite * sp1 = (CCSprite*)this->getChildByTag(91);  
  15.             sp1->setPosition(location);              
  16.         }else if(pTouch->getID()==1){//第二个触点  
  17.             CCSprite * sp2= (CCSprite*)this->getChildByTag(92);  
  18.             sp2->setPosition(location);  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. //用户手指进行移动或者拖拽  
  24. void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){  
  25.     CCSetIterator iter = pTouches->begin();  
  26.     for (; iter != pTouches->end(); iter++)  
  27.     {  
  28.         CCTouch* pTouch = (CCTouch*)(*iter);  
  29.         CCPoint location = pTouch->getLocation();  
  30.         if(pTouch->getID()==0){//第一个触点  
  31.             CCSprite * sp1 = (CCSprite*)this->getChildByTag(91);  
  32.             sp1->setPosition(location);  
  33.         }else if(pTouch->getID()==1){//第二个触点  
  34.             CCSprite * sp2= (CCSprite*)this->getChildByTag(92);  
  35.             sp2->setPosition(location);  
  36.         }  
  37.     }  
  38. }  
  39.   
  40. //用户手指抬起  
  41. void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent){  
  42.     CCSetIterator iter = pTouches->begin();  
  43.     for (; iter != pTouches->end(); iter++)  
  44.     {  
  45.         CCTouch* pTouch = (CCTouch*)(*iter);  
  46.         CCPoint location = pTouch->getLocation();  
  47.         CCLOG("pTouch  触摸点 %i 的坐标: x:%f,y:%f",pTouch->getID(),location.x,location.y);  
  48.     }  
  49. }  
  50.   
  51. //删除多触点的委托监听  
  52. void HelloWorld::onExit(){  
  53.     CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);  
  54.     CCLayer::onExit();  
  55. }  

 

 

4、示例效果图


以上示例代码主要实现随着不同用户多个触摸点位置的移动,其各精灵位置也不断移动。


作为cocos2d-x的小白,目前只能一步一步的学习,上面有关多点触控的例子可以参照test中的MutiTouchTest,会有完整的代码!


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: cocos2d-x 4. 学习之路 cocos2d-x是一款开源的跨平台游戏引擎,支持多种平台,包括iOS、Android、Windows、Mac OS X等。cocos2d-x 4.是最新版本,相比之前版本,它有很多新特性和改进,如增强的渲染性能、更好的3D支持、更好的物理引擎等。 如果你想学习cocos2d-x 4.,可以从以下几个方面入手: 1. 学习基础知识:了解cocos2d-x的基本概念、架构和工作原理,掌握cocos2d-x的编程语言和开发环境。 2. 学习API:熟悉cocos2d-x的API,包括场景管理、精灵、动画、音频、物理引擎等。 3. 学习示例代码:通过阅读和分析cocos2d-x的示例代码,了解如何使用cocos2d-x开发游戏。 4. 学习实践:通过实践开发小游戏,掌握cocos2d-x的开发流程和技巧,提高自己的编程能力。 总之,学习cocos2d-x 4.需要一定的时间和耐心,但只要你有兴趣和热情,相信你一定能够掌握它。 ### 回答2: cocos2d-x是一个强大的游戏引擎,可用于开发移动和桌面游戏。随着cocos2d-x更新至4.0版本,它的功能得到了大幅升级。如果你想学习cocos2d-x 4.0,以下是一些重要的步骤和建议。 1. 更改代码结构 cocos2d-x 4.0中启用了新的代码结构,旨在更好地实现模块化和解耦。新代码结构包括Core、Renderer、2d等模块,使代码更易于维护和升级。要理解新代码结构,请先阅读cocos2d-x官方文档,并针对各个模块学习和熟悉其API。 2. 学习新功能 cocos2d-x 4.0中引入了许多新功能,例如Shader、Render Queue等。学习新功能是非常必要的,因为它们将改变以前的游戏开发模式。了解这些新功能的实现原理,并在自己的项目中应用它们,有助于提高游戏性能和质量。 3. 学习C++11 cocos2d-x 4.0开始支持C++11标准,这意味着你可以使用C++11的新特性来编写更好的代码。要理解C++11的特性,建议通读一遍C++11的官方标准,并尝试在cocos2d-x项目中使用这些新特性。 4. 实战练习 最后,实战练习是学习任何技能的关键。为了更好地学习cocos2d-x 4.0,建议你尝试开发自己的游戏项目。通过尝试解决实际问题,你能更好地理解cocos2d-x的API,并在实践中掌握游戏开发的技术。 总而言之,学习cocos2d-x 4.0需要掌握新的代码结构、新的功能和C++11标准,并通过实际项目实战练习来加深理解。这需要一定的时间和耐心,但只要你认真学习、实践和不断尝试,必定能够取得成功。 ### 回答3: cocos2d-x 4.0是目前市面上非常流行的开源游戏开发引擎,在游戏开发领域有着较为广泛的应用。然而,学习cocos2d-x 4.0需要付出一定的努力和时间。以下是我对cocos2d-x 4.0学习之路的一些经验和建议。 1. 学习基础知识 在开始学习cocos2d-x 4.0之前,我们需要了解一些基础知识,比如C++语言、OpenGL ES等,这些都是cocos2d-x 4.0的底层实现技术。掌握这些基础知识会让我们从事游戏开发时更加得心应手。 2. 学习文档 学习cocos2d-x 4.0需要阅读官方文档,这些文档详细介绍了引擎的各个方面,而且是学习的最佳资料。文档里包括了引擎的安装、使用、开发以及调试等。建议大家先从官网下载文档,并且仔细阅读。 3. 实践和开发 掌握了基础知识以及学习了文档之后,最好的方式就是通过实践和开发来加深对cocos2d-x 4.0的理解。通过实际开发游戏来体验引擎的使用,这样能够更深刻的理解引擎的机制以及遇到的各种问题该如何解决。同时,通过找到一些相近的问题,并通过查阅文档、代码实现等方式来解决问题,可以增强自己的技术水平。 4. 参与社区 cocos2d-x 4.0的官方论坛以及社区非常活跃,里面的开发者也有着丰富的经验和技术,在学习中可以多向论坛、社区里的大牛请教,获得更多的技术指导,同时也可以参与讨论,提出自己的问题和思考来获得反馈,这样可以更快地提高自己的技术。 总之,学习cocos2d-x 4.0需要耐心和对游戏开发的热情。只有通过不断的学习与实践,我们才能最终掌握这个优秀的游戏开发引擎,从而创建属于自己的游戏作品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值