您的位置:首页 > 移动开发 > Cocos引擎

戏谈cocos2d-x 2.0.4 Touch

2014-04-10 14:10 375 查看
先把跟Touch相关的类列一下:
EAGLView
CCEGLView
CCEGLViewProtocol
EGLTouchDelegate
CCTouchDispatcher
CCTouchHandler
CCStandardTouchHandler
CCTargetedTouchHandler
CCTouchDelegate
CCTargetedTouchDelegate
CCStandardTouchDelegate
CCLayer
CCTouch

EAGLView
真正的view Cocosd-x已经把各个平台的view已经封装成EAGLView.在EAGLView中含有

1. -(void)touchesBegan:(NSSet *)touches
withEvent:(UIEvent *)event 2. -
(void)touchesMoved:(NSSet *)touches
withEvent:(UIEvent *)event 3. -
(void)touchesEnded:(NSSet *)touches
withEvent:(UIEvent *)event 4. -
(void)touchesCancelled:(NSSet *)touches
withEvent:(UIEvent *)event

上诉四个方法能直接监听反馈用户的点击事件。同时能获取点击的坐标,以及有几个手指点击移动,再分别通过调用CCEGLViewProtocol的以下四个方法

1.virtual
void handleTouchesBegin(int
num, int ids[],
float xs[],
float ys[]);

2.virtual
void handleTouchesMove(int
num, int ids[],
float xs[],
float ys[]);

3. virtual void handleTouchesEnd(int num, int ids[], float xs[], float ys[]);

4.virtual
void handleTouchesCancel(int
num, int ids[],
float xs[],
float ys[]);

将touches***方法中的信息传递到handleTouches***方法中.(其中通过cocos2d::CCEGLView::sharedOpenGLView()->handleTouches***(i,
ids, xs, ys)来调用以上四个方法,sharedOpenGLView返回的是CCEGLView,由于CCEGLView是CCEGLViewProtocol的子类,不过handleTouches***这些方法的主要逻辑处理还是在CCEGLViewProtocol处理的)。CCEGLViewProtocol类中有个EGLTouchDelegate*
m_pDelegate属性,在handleTouches***方法中主要是把触摸点point放到CCTouch中,再把其放入CCSet中。通过m_pDelegate->touches***(&set,
NULL)方法将CCSet信息传递给CCTouchDispatcher。关于CCTouchDispatcher这个类,她可是出生于名门世家-EGLTouchDelegate,EGLTouchDelegate有四个我们熟悉的方法也就是:

1.virtual
void touchesBegan(CCSet*
touches, CCEvent* pEvent) =
0;

2.virtual
void touchesMoved(CCSet*
touches, CCEvent* pEvent) =
0;

3.virtual
void touchesEnded(CCSet*
touches, CCEvent* pEvent) =
0;

4.virtual
void touchesCancelled(CCSet*
touches, CCEvent* pEvent) =
0;

CCEvent继承于CCObject,关于CCTouch他也是继承于CCObject,她能获取

1.CCPoint getLocation() const;

2.CCPoint getPreviousLocation() const;

3.CCPoint getStartLocation() const;

4.CCPoint getDelta() const;

5.CCPoint getLocationInView() const;

6.CCPoint getPreviousLocationInView() const;

7.CCPoint getStartLocationInView() const;

上诉四个方法都是虚函数,真正的实现方法都在CCTouchDispatcher中,但是在CCTouchDispatcher中的上诉四个方法其实也没干了什么大不了的事情,他们都做了相同的事情就是统一回调了CCTouchDispatcher中的void
CCTouchDispatcher::touches(CCSet
*pTouches, CCEvent *pEvent,
unsigned
int uIndex)方法,根据uIndex来区分是Began呢还是Moved等相关事件,所以上面讲了一堆,其实真正干事情的就只有CCTouchDispatcher中的touches方法,通过这个方法把触摸事件分发出去,那怎么分发事件的呢?说道这,咱还是得回顾下其他知识。



先聊聊CCTouchDelegate吧,这位老祖宗还真是祖宗。它有一堆的虚函数

/*******CCTargetedTouchDelegate 单点触摸*****/

1.virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent); return false;};

2.virtual
void ccTouchMoved(CCTouch
*pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch);
CC_UNUSED_PARAM(pEvent);}

3.virtual
void ccTouchEnded(CCTouch
*pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch);
CC_UNUSED_PARAM(pEvent);} 4.virtual
void ccTouchCancelled(CCTouch
*pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch);
CC_UNUSED_PARAM(pEvent);}

/**********CCStandardTouchDelegate****多点触摸***********/

5.virtual
void ccTouchesBegan(CCSet
*pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches);
CC_UNUSED_PARAM(pEvent);} 6.virtual
void ccTouchesMoved(CCSet
*pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches);
CC_UNUSED_PARAM(pEvent);} 7.virtual
void ccTouchesEnded(CCSet
*pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches);
CC_UNUSED_PARAM(pEvent);} 8.virtual
void ccTouchesCancelled(CCSet
*pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches);
CC_UNUSED_PARAM(pEvent);}



上诉CCTargetedTouchDelegate以及CCStandardTouchDelegate都是CCTouchDelegate的子类,分别对应于单点触摸以及多点触摸。当然CCTouchDelegate的子类还有CCLayer。CCLayer含有他爸的全部方法,也就是单点触摸,多点触摸的方法她都有了。当然不能同时响应单点触摸以及多点触摸,其实多点触摸也就包含了单点触摸。CCLayer是通过ccTouchesMode这个结构来区分单点触摸以及多点触摸的-kCCTouchesAllAtOnce/kCCTouchesOneByOne.

讲了半天的CCTouchDelegate以及子类,那它怎么跟CCTouchDispatcher勾搭上啊,其实很简单,就只需要到CCTouchDispatcher注册一下。接下来重点将下CCLayer是怎么注册的。CCLayer藏的很深,她仅仅就是让我们通过CCLayer::setTouchEnabled(bool
enabled)这个方法设置下是否能触摸,她就去乖乖的到CCTouchDispatcher注册去了。

下***体看看setTouchEnabled做了啥事情吧,他去找了CCLayer中的registerWithTouchDispatcher()这个方法,在这个方法中,他会去到CCDirector中找到CCTouchDispatcher(CCTouchDispatcher*
pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher()),其实CCTouchDispatcher在CCDirector的初始化中,他就生出来了。找到CCTouchDispatcher后也就方便了,通过ccTouchesMode这个值判断是去注册单点呢,还是多点呢,CCLayer中ccTouchesMode默认值是kCCTouchesAllAtOnce。具体方法:pDispatcher->addStandardDelegate(this,
0);//标准多点触摸。pDispatcher->addTargetedDelegate(this,
m_nTouchPriority,
true);//正统的单点触摸,注意这个true,这玩意就是个火药桶,如果他是true的时候,你一玩完,就偷偷的把CCSet中的CCTouch给释放了,具体要看证据还是得在CCTouchDispatcher中的touches才能看到,当然他仅仅只针对单点触摸,谁叫你单点啊。

好了现在也注册到CCTouchDispatcher了,也是属于有身份的合法公民了,跟着政府就好。那现在我们就看这个政府CCTouchDispatcher是怎么管理这个触摸小国家的吧。CCTouchDispatcher管理这个国家也不是亲力亲为的,她也请了外援CCTouchHandler,这个Handler还拖家带口的,有两个亲儿子CCStandardTouchHandler以及CCTargetedTouchHandler。

CCTouchHandler主要干的啥事情呢?保存CCTouchDelegate以及priority这两个东东。CCTouchDelegate就不需要怎么说了,他到CCTouchDispatcher一报到,CCTouchDispatcher二话不说,把CCTouchDelegate以及CCTouchDelegate的priority直接扔给CCTouchHandler,给打包下。当然CCTouchHandler也不是蛮干,先看看CCTouchDelegate你是CCTargetedTouchDelegate还是CCStandardTouchDelegate呀,CCTouchHandler验明了CCTouchDelegate的身份之后自己也不直接上去,而是叫自己的儿子CCStandardTouchHandler以及CCTargetedTouchHandler两个活宝上去打包的。打包方法:

1.static
CCTouchHandler* handlerWithDelegate(CCTouchDelegate
*pDelegate, int nPriority);//在该方法中会调用initWithDelegate

2.virtual
bool initWithDelegate(CCTouchDelegate
*pDelegate, int nPriority);

对了关于上面两个方法对于CCStandardTouchHandler以及CCTargetedTouchHandler都有不同的个性化,特别是CCTargetedTouchHandler,谁叫他打包的是CCTargetedTouchDelegate呀,CCTargetedTouchDelegate这玩意有个bSwallowsTouches,是否吞了该触摸。也就是在上文讲到的true,在addTargetedDelegate中如果将bSwallowsTouches设为true,则当你触发完事件后,她就把你从触发的点上删除。所以此处CCTargetedTouchHandler针对CCTargetedTouchDelegate的特殊需求,也得满足不是,我就把你的bSwallowsTouches一并打包和CCTouchDelegate以及nPriority。CCTouchHandler通过两个乖儿子,把CCTouchDelegate相关属性一并打包,就去向CCTouchDispatcher总理报到了。这到哪报到呢,就是上文说的void
CCTouchDispatcher::addStandardDelegate(CCTouchDelegate
*pDelegate, int nPriority)以及void
CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate
*pDelegate, int nPriority,
bool bSwallowsTouches)这两个方法啊。在这两个方法中都能将打包好的CCTouchHandler,通过forceAddHandler这个方法,把她分别提交给m_pStandardHandlers以及m_pTargetedHandlers两个CCArray*大官人那,哪天CCTouchDispatcher想找哪个CCTouchHandler的时候,直接找两个大官人就好。好了上面说了一堆终于把CCTouchDelegate跟CCTouchDispatcher不得不说的事情说完了。

终于得做点事情了,前面也谈到了当有触摸事件来的时候,不管是Began还是Moved啥的,一并都去void
touches(CCSet *pTouches,
CCEvent *pEvent,
unsigned
int uIndex);这个办事处。这地方也就相当于总理大衙门-中南海,不管是触摸的消息CCSet,还是CCTouchHandler都得在这交代的一清二百。上文所说的m_pStandardHandlers以及m_pTargetedHandlers通过遍历找到CCTouchHandler,然后将CCTouchHandler总理处理的结果传递到下面各个小罗罗上。

1.pHandler->getDelegate()->ccTouchBegan(pTouch,
pEvent);

2.pHandler->getDelegate()->ccTouchesBegan(pMutableTouches,
pEvent);

pHandler->getDelegate()也就是被打包封装的CCTouchDispatcher,现在就是被解绑了而已。

好了,说到这关于细说touch事情也差不多结束了。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: