转自:http://blog.csdn.net/onerain88/article/details/7550009

一般经常用到的触屏的情况有两种:一种是Layer统一接收触屏消息,然后由程序根据需要分发给不同位置的精灵;另一种情况是自定义一个可以接收触屏消息的Sprite,比如类似于Button功能的Sprite,这就需要在定义Sprite的时候就要定义好触屏所触发的操作!

下面就两种情况分别记录一下基本用法:

1.Layer接收触屏消息

用法很简单,只需要覆写父类的4个方法(可以根据需要,但是ccTouchBegan()是必须要覆写的,并且其返回值对触屏事件的传递有影响,后面会总结),并在init()方法中将其添加到CCTouchDispacher中,代码如下

  1. class TouchableLayer: public CCLayer
  2. {
  3. public:
  4.  
  5. virtual bool init();
  6.  
  7. LAYER_NODE_FUNC(TouchableLayer);
  8.  
  9. virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
  10. virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
  11. virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
  12. virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
  13. };

在Layer的init()中添加如下代码,这个Layer就可以接收到触屏消息了

  1. CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, , true);

如果想通过这种方式判断具体触摸的Sprite或者区域等信息,就需要自己写判断和分发消息的代码了!

2.自定义可以接收触屏消息的Sprite

这种稍微复杂一些,但是还是比较好理解的,首先要先继承CCSprite或者其父类,以满足精灵形状,位置等信息的要求,另外还需要继承触屏事件委托CCTargetedTouchDelegate,CCTargetedTouchDelegate中定义了接收触屏信息的回调虚函数,而这些虚函数,正是我们需要覆写的部分,代码如下

  1. class TouchableSprite: public CCSprite, public CCTargetedTouchDelegate
  2. {
  3.  
  4. public:
  5. TouchableSprite();
  6. virtual ~TouchableSprite();
  7.  
  8. static TouchableSprite *touchSpriteWithFile(const char *file);
  9.  
  10. bool initWithFile(const char *file);
  11.  
  12. virtual void onEnter();
  13. virtual void onExit();
  14.  
  15. CCRect rect();
  16. bool containsTouchLocation(CCTouch *touch);
  17.  
  18. virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
  19. virtual void ccTouchMoved(CCTouch *touch, CCEvent *event);
  20. virtual void ccTouchEnded(CCTouch *touch, CCEvent *event);
  21.  
  22. };

重点在于判断自定义Sprite是否被点击,这时就需要得到精灵所在的矩形了,这时又有两种判断方式

(1)得到触屏所在位置,然后根据精灵所在位置的矩形区域和触屏的点判断是否包含,如果包含,则说明触摸到了Sprite。这里写了一个得到精灵当前所在矩形的方法

  1. CCRect TouchableSprite::rect()
  2. {
  3. CCSize size = getContentSize();
  4. CCPoint pos = getPosition();
  5.  
  6. return CCRectMake(pos.x - size.width / , pos.y - size.height / , size.width, size.height);
  7. }

然后在每次点击的时候都需要将当前触屏位置转换为GL坐标的位置,然后和Sprite所在矩形做包含判断

  1. bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
  2. {
  3. CCPoint touchPoint = touch->locationInView(touch->view());
  4. touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
  5.  
  6. return CCRect::CCRectContainsPoint(rect(), touchPoint);
  7. }

(2)其实cocos2d为我们提供了一种相对简单的方法,但是原理类似,调用CCNode中定义的convertTouchToNodeSpaceAR()方法,将触屏点转化为相对于结点的相对坐标

(ps:由于默认anchor点是中点,所以每一个Sprite上的相对坐标系是从(-width / 2, -height / 2)为左上角点坐标),所以上面的两个方法需要修改一下

  1. CCRect TouchableSprite::rect()
  2. {
  3. CCSize size = getTexture()->getContentSize();
  4.  
  5. return CCRectMake(-size.width / , -size.height / , size.width, size.height);
  6. }
  1. bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
  2. {
  3. return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch));
  4. }

3.触屏传递顺序

另外需要主要的是

  1. virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);

方法,其返回值是对此触屏消息有影响的,简单来说,如果返回false,表示不处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,而交由后续接收触屏消息的对象处理;如果返回true,表示会处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,并且消耗掉此触屏消息。

总结如下:

1.CCLayer 只有一层的情况:

virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

a.返回false,则ccTouchMoved(),ccTouchEnded()不会再接收到消息
b.返回true,则ccTouchMoved(),ccTouchEnded()可以接收到消息
 
2.CCLayer 有多层的情况:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
a.返回false,则本层的ccTouchMoved(),ccTouchEnded()不会再接收到消息,但是本层之下的其它层会接收到消息
b.返回true,则本层的ccTouchMoved(),ccTouchEnded()可以接收到消息,但是本层之下的其它层不能再接收到消息
 
3.有自定义接收触摸消息的精灵的情况:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
a.返回false,则此精灵的ccTouchMoved(),ccTouchEnded()不会再接收到消息,而此精灵所在的层会接收到触摸消息(如果精灵所在层没有设置接收触摸消息,则向下传递)
b.返回true,则此精灵的ccTouchMoved(),ccTouchEnded()会继续接收消息,并消耗此消息(即不再向所在层和其他层传递)

4.自定义触屏事件

1、判断触摸点是否在指定区域内

HelloWorldScene.h

  1. public:
  2. CCRect mPlayBounds;
  3.  
  4. virtual void registerWithTouchDispatcher();
  5. virtual bool ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event);

HelloWorldScene.cpp

删除bool HelloWorld::init()下do代码块中的所有代码,替换为:

  1. CC_BREAK_IF(! CCLayer::init());
  2. CCSize size = CCDirector::sharedDirector()->getWinSize();
  3. //实例化一个精灵
  4. CCSprite *mMainMenu = CCSprite::create("items.png", CCRectMake(, , , ));
  5. CC_BREAK_IF(!mMainMenu);
  6. //设置精灵的位置
  7. mMainMenu->setPosition(ccp(size.width / , size.height / ));
  8. this->addChild(mMainMenu);
  9.  
  10. //绘制一个矩形
  11. mPlayBounds = CCRectMake(size.width / - , size.height / + , , );
  12. //设置为可触摸
  13. this->setTouchEnabled(true);
  14.  
  15. bRet = true;

添加两个函数:

  1. void HelloWorld::registerWithTouchDispatcher()
  2. {
  3. //注册触摸监听
  4. CCDirector* pDirector = CCDirector::sharedDirector();
  5. pDirector->getTouchDispatcher()->addTargetedDelegate(this, , true);
  6. }
  7.  
  8. bool HelloWorld::ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event)
  9. {
  10. //取得触摸点
  11. CCPoint location = touch->getLocationInView();
  12. //将触摸点转换为GL坐标系的点
  13. location = CCDirector::sharedDirector()->convertToGL(location);
  14.  
  15. //如果触摸点在矩形范围内则执行代码,切换场景
  16. if (mPlayBounds.containsPoint(location))
  17. {
  18. CCScene *scene = SecondScene::scene();
  19. CCDirector::sharedDirector()->replaceScene(CCTransitionJumpZoom::create(1.0f,scene));
  20. }
  21. return true;
  22. }

cocos2d-x触屏事件(单点触屏)的更多相关文章

  1. HTML5学习总结-09 拖放和手机触屏事件

    一 拖放 拖放(Drag 和 drop)是 HTML5 标准的组成部分.拖放是一种常见的特性,即抓取对象以后拖到另一个位置.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 课程参考 ht ...

  2. cocos2dx基础篇(7) 触碰事件

    cocos2dx游戏引擎的重点是在于移动设备的跨平台开发,而移动设备上的游戏大部分都是通过屏幕触碰来进行的.比如主菜单的按钮触碰,打飞机中飞机的触碰移动,都需要用到触碰操作.想一想之前讲的菜单按钮CC ...

  3. 转:Android随笔之——使用Root权限实现后台模拟全局按键、触屏事件方法(类似按键精灵)

    本文转载自CSDN的jzj1993,原文连接:http://blog.csdn.net/jzj1993/article/details/39158865 有时我们需要使用安卓实现在后台模拟系统按键,比 ...

  4. JS的Touch事件们,触屏时的js事件

    丫的,终于找到了JS在平板电脑上的事件!!!   iphone.ipod Touch.ipad触屏时的js事件   1.Touch事件简介   pc上的web页面鼠标会产生onmousedown.on ...

  5. (转)js的左右滑动触屏事件

    原文:http://blog.sina.com.cn/s/blog_6a0a183f0100zsfk.html (2012-01-20 08:55:53) 转载▼ 标签: 移动设备 触屏事件 杂谈 分 ...

  6. html5 touch事件实现触屏页面上下滑动(二)

    五一小长假哪都没去,睡了三天,今天晕晕沉沉的投入工作了,但还是做出了一点点效果 上周用html5的touch事件把简单的滑动做出来了,实现了持续页面上下滑动的效果,参考之前 的文章及代码html5 t ...

  7. [IOS]自定义长触屏事件

    写一个Demo来自定义一个长触屏事件,自定义长按手势. 实现步骤: 1.创建一个自定义手势类,命名为LongPressGestureRecognizer,在创建的时候继承UIGestureRecogn ...

  8. js触屏事件

    js的左右滑动触屏事件,主要有三个事件:touchstart,touchmove,touchend.这三个事件最重要的属性是 pageX和 pageY,表示X,Y坐标. touchstart在触摸开始 ...

  9. 移动端touch触屏滑动事件、滑动触屏事件监听!

    一.触摸事件 ontouchstart.ontouchmove.ontouchend.ontouchcancel 目前移动端浏览器均支持这4个触摸事件,包括IE.由于触屏也支持MouseEvent,因 ...

随机推荐

  1. 想使用 MongoDB ,你应该了解这8个方面!

    应用性能高低依赖于数据库性能,MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.MongoDB 是一个介于关系数据库和非关 ...

  2. Python中文全攻略

    原文链接:http://blog.csdn.net/mayflowers/archive/2007/04/18/1568852.aspx 1.        在Python中使用中文 在Python中 ...

  3. ORMBase对象/关系型数据库映射在MVC中的应用(二)

    3.DataBase基类,查询方法返回值是List<T>,并且是分页的,ThePart.dll版本2.0中封装了一个PageInfo类,作为分页的类型.这种方法很机械,也很狗血..建议大家 ...

  4. Storm技术结合

    http://pan.baidu.com/s/1mhzj5XI?qq-pf-to=pcqq.group#path=%252F

  5. tomcat 端口被占用

    找到占用8080端口的是PID为 2392的进程,于是 ctrl +shift+esc ,然后将这个进程结束掉.

  6. 【NOIP 2014 DAY1 T3】飞扬的小鸟(DP)

    题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...

  7. Linux使用wake_up_interruptible()唤醒注册到等待队列上的进程

    http://blog.sina.com.cn/s/blog_4770ef020101h48l.html     功能:唤醒注册到等待队列上的进程 原型:     #include     void ...

  8. USB 枚举过程详解

    Windows 对USB设备的枚举过程流程图如图1所示: 图1 WP8的USB功能只支持一个配置,三个接口,也就是分别有如下的字段: 设备描述符的bNumConfigurations=1, 配置描述符 ...

  9. Android 透明Button

    1.是制作9-patch的图片,这样能够匹配文字内容的长短. 2.是指定按钮样式背景,即定制drawable的xml文件,这样做的好处不用图片做背景,节省空间. 定制透明样式的按钮.直接看代码: dr ...

  10. WIP_DISCRETE_JOBS.STATUS_TYPE

    WIP_DISCRETE_JOBS.STATUS_TYPE Value Meaning 7 Cancelled 8 Pending Bill Load 9 Failed Bill Load 10 Pe ...