cocos2d-x自定义可点击/可处理事件/可接受触屏消息的Sprite
2013-06-27 15:15
561 查看
本篇大部分摘自/article/1385646.html(写的好清楚)
一般经常用到的触屏的情况有两种:一种是Layer统一接收触屏消息,然后由程序根据需要分发给不同位置的精灵;另一种情况是自定义一个可以接收触屏消息的Sprite,比如类似于Button功能的Sprite,这就需要在定义Sprite的时候就要定义好触屏所触发的操作!
首先要先继承CCSprite或者其父类,以满足精灵形状,位置等信息的要求,另外还需要继承触屏事件委托CCTargetedTouchDelegate,CCTargetedTouchDelegate中定义了接收触屏信息的回调虚函数,而这些虚函数,正是我们需要覆写的部分,代码如下
重点在于判断自定义Sprite是否被点击,这时就需要得到精灵所在的矩形了,这时又有两种判断方式
(1)得到触屏所在位置,然后根据精灵所在位置的矩形区域和触屏的点判断是否包含,如果包含,则说明触摸到了Sprite。这里写了一个得到精灵当前所在矩形的方法
可以使用getLocation()取代上面那两句代码,cocos2d-x相关源码如下:
(2)其实cocos2d为我们提供了一种相对简单的方法,但是原理类似,调用CCNode中定义的convertTouchToNodeSpaceAR()方法,将触屏点转化为相对于结点的相对坐标
关于事件处理还可以参考本文
http://blog.linguofeng.com/archive/2012/09/12/cocos2d-x-touch.html
可以借鉴该文点击事件处理方法
其它处理方法,可以借鉴CCTableView
http://blog.csdn.net/xzongyuan/article/details/9177421
方法,其返回值是对此触屏消息有影响的,简单来说,如果返回false,表示不处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,而交由后续接收触屏消息的对象处理;如果返回true,表示会处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,并且消耗掉此触屏消息。
最后,要在进入时候添加触屏接口
一般经常用到的触屏的情况有两种:一种是Layer统一接收触屏消息,然后由程序根据需要分发给不同位置的精灵;另一种情况是自定义一个可以接收触屏消息的Sprite,比如类似于Button功能的Sprite,这就需要在定义Sprite的时候就要定义好触屏所触发的操作!
1.Layer接收触屏消息(请参考原文)
总结下就是:在layer中的sprite,他们可能会处于同一层,那么,最重要的就是怎么把事件传递给希望处理事件的sprite。方法就是通过优先级去“接收事件”,如果不处理,ccTouchBegin的返回值就设置为false,如果处理,就设置为true,表示拦截此消息。这样,事件就不会往更低优先级的sprite传递了。2.自定义可以接收触屏消息的Sprite
我比较感兴趣的是自定义Sprite。首先要先继承CCSprite或者其父类,以满足精灵形状,位置等信息的要求,另外还需要继承触屏事件委托CCTargetedTouchDelegate,CCTargetedTouchDelegate中定义了接收触屏信息的回调虚函数,而这些虚函数,正是我们需要覆写的部分,代码如下
class TouchableSprite: public CCSprite, public CCTargetedTouchDelegate { public: TouchableSprite(); virtual ~TouchableSprite(); static TouchableSprite *touchSpriteWithFile(const char *file); bool initWithFile(const char *file); virtual void onEnter(); virtual void onExit(); CCRect rect(); bool containsTouchLocation(CCTouch *touch); virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event); virtual void ccTouchMoved(CCTouch *touch, CCEvent *event); virtual void ccTouchEnded(CCTouch *touch, CCEvent *event); };
重点在于判断自定义Sprite是否被点击,这时就需要得到精灵所在的矩形了,这时又有两种判断方式
(1)得到触屏所在位置,然后根据精灵所在位置的矩形区域和触屏的点判断是否包含,如果包含,则说明触摸到了Sprite。这里写了一个得到精灵当前所在矩形的方法
CCRect TouchableSprite::rect() { CCSize size = getContentSize(); CCPoint pos = getPosition(); return CCRectMake(pos.x - size.width / 2, pos.y - size.height / 2, size.width, size.height); }然后在每次点击的时候都需要将当前触屏位置转换为GL坐标的位置,然后和Sprite所在矩形做包含判断
bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch) { CCPoint touchPoint = touch->locationInView(touch->view()); //这里由于版本更新,改为touch->getLoactionInView() touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint); return CCRect::CCRectContainsPoint(rect(), touchPoint); }转载作者补充:
可以使用getLocation()取代上面那两句代码,cocos2d-x相关源码如下:
// returns the current touch location in screen coordinates CCPoint CCTouch::getLocationInView() const { return m_point; } // returns the current touch location in OpenGL coordinates CCPoint CCTouch::getLocation() const { return CCDirector::sharedDirector()->convertToGL(m_point); }这里要提下坐标系统,getLocationInView获取的是屏幕坐标,不同设备坐标系统不同,例如ios是左上角为原点。而cocos2d-x是左下角为原点。所以在cocos2d-x中做运算时候,要转为GL坐标系,即cocos2d-x默认的“可视屏幕的坐标系统”。
(2)其实cocos2d为我们提供了一种相对简单的方法,但是原理类似,调用CCNode中定义的convertTouchToNodeSpaceAR()方法,将触屏点转化为相对于结点的相对坐标
CCRect TouchableSprite::rect() { CCSize size = getTexture()->getContentSize(); return CCRectMake(-size.width / 2, -size.height / 2, size.width, size.height); } bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch) { return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch)); }
关于事件处理还可以参考本文
http://blog.linguofeng.com/archive/2012/09/12/cocos2d-x-touch.html
可以借鉴该文点击事件处理方法
void MyLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) { // 单点 CCTouch *pTouch = (CCTouch*)(pTouches->anyObject()); // 所有点 for(CCSetIterator iterTouch = pTouches->begin(); iterTouch != pTouches->end(); iterTouch++) { CCTouch *pCurTouch = (CCTouch*)(*iterTouch); } // 获取点在视图中的坐标(左上角为原点) CCPoint touchLocation = pTouch->getLocationInView(); // 把点的坐标转换成OpenGL坐标(左下角为原点) touchLocation = CCDirector::sharedDirector()->convertToGL(touchLocation); // 把OpenGL的坐标转换成CCLayer的坐标 CCPoint local = convertToNodeSpace(touchLocation) // 大小为100x100,坐标为(0, 0)的矩形 CCRect * rect = CCRectMake(0, 0, 100, 100); // 判断该坐标是否在rect矩形内 bool flag = rect.containsPoint(local) if(flag) { // 回调 } else { // 不执行 } }
其它处理方法,可以借鉴CCTableView
http://blog.csdn.net/xzongyuan/article/details/9177421
触屏传递顺序
另外需要主要的是virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
方法,其返回值是对此触屏消息有影响的,简单来说,如果返回false,表示不处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,而交由后续接收触屏消息的对象处理;如果返回true,表示会处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,并且消耗掉此触屏消息。
最后,要在进入时候添加触屏接口
void TouchableSprite::onEnter(){ CCSprite::onEnter(); CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true); } void TouchableSprite::onExit(){ CCSprite::onExit(); CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); }
相关文章推荐
- 【COCOS2D-X 备注篇】cocos2dx 获取手机截屏等意外取消触屏事件的处理方法! 推荐
- C++自定义ClistCtrl控件响应数据项的点击事件&&消息反射的原理
- 接受屏幕点击事件 然后自己分发处理
- 自定义View想使用Scroller实现滑动效果,但是事件接收出现问题,只收到ACTION_DOWN,而无法收到ACTION_MOVE, ACTION_UP等消息的处理
- cocos2d-x基本知识点:事件处理机制之触屏事件1
- iOS开发-UI控件:自定义UITableViewCell 上的多个按钮点击事件处理
- cocos2d-x 自定义Touch事件处理类
- cocos2d js 给sprite增加按钮点击事件
- cocos2d-x处理点击事件的机制
- Cocos2D-X事件处理机制之触屏事件
- Cocos2d-X 事件处理机制之触屏事件(单点触屏+多点触屏)
- Android自定义TextView中的超链接点击事件处理
- 点击TextView中链接,自定义处理事件
- Cocos2d-x html5笔记 - 点击事件的处理
- Cocos2d-x CCNotificationCenter 通知中心 自定义消息事件
- cocos2d之触屏事件处理机制(2.x和3.x的变化)
- 【COCOS2D-X 备注篇】cocos2dx 获取手机截屏等意外取消触屏事件的处理方法!
- 自定义UITableViewCell 上按钮点击事件处理
- cocos2d-x遇到的触屏处理事件问题
- 自定义UITableViewCell 上的多个按钮点击事件处理