好记性不如铅笔头

C && C++, cocos2dx, 编程

cocos2dx学习笔记:触摸响应

最近项目中用到了cocos2dx来开发一个基于陀螺仪的demo,忙了半个星期,一边学习一边开发,总算搞了出来。这里备份下开发中学习到的一些cocos2dx知识。

CONTENTS

cocos2dx事件响应源码摘录:

基于版本:2.2.1,代码版权属于cocos原作者。

CCLayer关于事件响应的代码:

setTouchEnabled:

void CCLayer::setTouchEnabled(bool enabled)
{
    if (m_bTouchEnabled != enabled)
    {
        m_bTouchEnabled = enabled;
        if (m_bRunning)
        {
            if (enabled)
            {//注册事件响应
                this->registerWithTouchDispatcher();
            }
            else
            {//去除注册事件响应
                // have problems?
                CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
            }
        }
    }
}

 registerWithTouchDispatcher:

void CCLayer::registerWithTouchDispatcher()
{
    CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();

    // Using LuaBindings
    if (m_pScriptTouchHandlerEntry)
    {//lua相关,先略去
       。。。。。
    }
    else
    {
//从此处可以发现,TouchMode和TouchPriority可以决定注册事件响应的类型。
//而Mode和Priority可以通过get/set设置。
        if( m_eTouchMode == kCCTouchesAllAtOnce ) {
            pDispatcher->addStandardDelegate(this, 0);
        } else {
            pDispatcher->addTargetedDelegate(this, m_nTouchPriority, true);
        }
    }
}
//TouchMode的枚举定义如下:
typedef enum {
 kCCTouchesAllAtOnce,
 kCCTouchesOneByOne,
} ccTouchesMode;

//get set 如下:
void CCLayer::setTouchMode(ccTouchesMode mode)
{
    if(m_eTouchMode != mode)
    {
        m_eTouchMode = mode;
        
		if( m_bTouchEnabled)
        {
			setTouchEnabled(false);
			setTouchEnabled(true);
		}
    }
}

void CCLayer::setTouchPriority(int priority)
{
    if (m_nTouchPriority != priority)
    {
        m_nTouchPriority = priority;
        
		if( m_bTouchEnabled)
        {
			setTouchEnabled(false);
			setTouchEnabled(true);
		}
    }
}

int CCLayer::getTouchPriority()
{
    return m_nTouchPriority;
}

int CCLayer::getTouchMode()
{
    return m_eTouchMode;
}

 代码看到此处,根据前文【 cocos2dx学习笔记:吞噬事件相应 】提到的方法,也可以使用下面代码:

    //CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -210, true);
    
    this->setTouchPriority(-210);
    this->setTouchMode(kCCTouchesOneByOne);
    this->setTouchEnabled(true);
    

CCTouchDispatcher:

void CCTouchDispatcher::touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex)
{
    CCAssert(uIndex >= 0 && uIndex < 4, "");

    CCSet *pMutableTouches;
    m_bLocked = true;

    // optimization to prevent a mutable copy when it is not necessary
     unsigned int uTargetedHandlersCount = m_pTargetedHandlers->count();
     unsigned int uStandardHandlersCount = m_pStandardHandlers->count();
    bool bNeedsMutableSet = (uTargetedHandlersCount && uStandardHandlersCount);

    pMutableTouches = (bNeedsMutableSet ? pTouches->mutableCopy() : pTouches);

    struct ccTouchHandlerHelperData sHelper = m_sHandlerHelperData[uIndex];
    //
    // process the target handlers 1st
    //
    if (uTargetedHandlersCount > 0)
    {
        CCTouch *pTouch;
        CCSetIterator setIter;
        for (setIter = pTouches->begin(); setIter != pTouches->end(); ++setIter)
        {
            pTouch = (CCTouch *)(*setIter);

            CCTargetedTouchHandler *pHandler = NULL;
            CCObject* pObj = NULL;
            CCARRAY_FOREACH(m_pTargetedHandlers, pObj)
            {
                pHandler = (CCTargetedTouchHandler *)(pObj);

                if (! pHandler)
                {
                   break;
                }

                bool bClaimed = false;
                if (uIndex == CCTOUCHBEGAN)
                {
                    bClaimed = pHandler->getDelegate()->ccTouchBegan(pTouch, pEvent);
//如果该触摸began返回true,说明handler开始处理这个事件(,但是不代表handler要吞噬这个事件!!!)
                    if (bClaimed)
                    {
                        pHandler->getClaimedTouches()->addObject(pTouch);
                    }
                } else
//经过测试发现,当一个触摸事件生成之后,从began,到end和cancel,都是同一个对象。
                if (pHandler->getClaimedTouches()->containsObject(pTouch))
                {
                    // moved ended canceled
                    bClaimed = true;

                    switch (sHelper.m_type)
                    {
                    case CCTOUCHMOVED:
                        pHandler->getDelegate()->ccTouchMoved(pTouch, pEvent);
                        break;
                    case CCTOUCHENDED:
                        pHandler->getDelegate()->ccTouchEnded(pTouch, pEvent);
                        pHandler->getClaimedTouches()->removeObject(pTouch);
                        break;
                    case CCTOUCHCANCELLED:
                        pHandler->getDelegate()->ccTouchCancelled(pTouch, pEvent);
                        pHandler->getClaimedTouches()->removeObject(pTouch);
                        break;
                    }
                }

                if (bClaimed && pHandler->isSwallowsTouches())
                {
                    if (bNeedsMutableSet)
                    {
                        pMutableTouches->removeObject(pTouch);
                    }
//注意这里的break,如果目标触摸被响应而且被设置吞噬,那么直接跳出内层循环,后续handler均不能响应这个触摸。
                    break;
                }
            }
        }
    }

    //
    // process standard handlers 2nd
    //
//当目标触摸全部结束之后,将挑剩下的touch事件一次性丢给标准触摸相应。
    if (uStandardHandlersCount > 0 && pMutableTouches->count() > 0)
    {
        CCStandardTouchHandler *pHandler = NULL;
        CCObject* pObj = NULL;
        CCARRAY_FOREACH(m_pStandardHandlers, pObj)
        {
            pHandler = (CCStandardTouchHandler*)(pObj);

            if (! pHandler)
            {
                break;
            }

            switch (sHelper.m_type)
            {
            case CCTOUCHBEGAN:
                pHandler->getDelegate()->ccTouchesBegan(pMutableTouches, pEvent);
                break;
            case CCTOUCHMOVED:
                pHandler->getDelegate()->ccTouchesMoved(pMutableTouches, pEvent);
                break;
            case CCTOUCHENDED:
                pHandler->getDelegate()->ccTouchesEnded(pMutableTouches, pEvent);
                break;
            case CCTOUCHCANCELLED:
                pHandler->getDelegate()->ccTouchesCancelled(pMutableTouches, pEvent);
                break;
            }
        }
    }

    if (bNeedsMutableSet)
    {
        pMutableTouches->release();
    }

    //
    // Optimization. To prevent a [handlers copy] which is expensive
    // the add/removes/quit is done after the iterations
    //
    m_bLocked = false;
。。。。。。
。。。。。。
}

 

发表评论

18 − 15 =

此站点使用 Akismet 来减少垃圾评论。了解我们如何处理您的评论数据