cocos2dx TouchDispatcher

本文详细解析了Cocos2d-x中的触控分发机制,包括CCTouchDispatcher的工作原理、触控优先级设定及触摸事件的处理流程。介绍了如何设置触摸层的优先级,并解释了新版中采用的绘制顺序进行触控分发的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

touch分发器:

在Layer::onEnter中设置setTouchEnabled之前,

需要设置TouchMode,区别是调用ccTouchBegan(CCTouch* touch, CCEvent* event)与ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);

或者在Layer中重载registerWithTouchDispatcher自己设置


CCTouchDispatcher

CCTouchDispatcher就相当于观察者模式中的发布者,它本身的名字起的就很直观了,分发器嘛。其中包含有添加和移除观察者(订阅者),然后在方法touchesBegan、touchesMoved、touchesEnded、touchesCancelled中分别调用了方法

void touches(CCSet *pTouchesCCEvent *pEventunsigned int uIndex)

在这个方法中通过CCTouchHandler的对象调用继承自触摸协议CCTouchDelegate的触摸对象(观察者)中的相应协议:ccTouchBegan。。。等等。如:

   CCTargetedTouchHandler *pHandler = NULL;

            CCObject* pObj = NULL;

            CCARRAY_FOREACH(m_pTargetedHandlers, pObj)

            {

                pHandler = (CCTargetedTouchHandler *)(pObj);

 

                if (! pHandler)

                {

                   break;

                }

 

                bool bClaimed = false;

                if (uIndex == CCTOUCHBEGAN)

                {.................

///////////////////////////////////////////////////////////////////////////////////

void CCTouchDispatcher::touchesMoved(CCSet *touchesCCEvent *pEvent)

{

    if (m_bDispatchEvents)

    {

        this->touches(touchespEventCCTOUCHMOVED);

    }

}

每个touchesXXX方法会传进touches方法中一个枚举值,touches方法根据这个枚举值来做相应的逻辑处理。

    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;

                    }

 

// 如果该触摸层设置了吞噬触摸,在该触摸层处理完触摸事件后,就把捕捉到的触摸点移除出触摸点集合pMutableTouches中

// 下面优先比它低的触摸层则接受不到该触摸点并不会作出形影的触摸处理

                if (bClaimed && pHandler->isSwallowsTouches())

                {

                    if (bNeedsMutableSet)

                    {

                        pMutableTouches->removeObject(pTouch);

                    }

 

                    break;

                }

 

 

这套机制的优点和缺点都很明显。有点是比较灵活,使用者可以根据需要设置触摸层的触摸优先级和是否吞噬触摸。缺点是开发者需要自己控制各个响应元素的touch priority,需要做一些代码的处理以及前期的优先级规划。其他大部分的引擎使用的是渲染的顺序来进行触摸事件侧分发,zOrder越大,触摸优先级越高。

而且cocos2d-x的消息分发并不会看touch是否发生在响应元素的响应区域范围内与否,只根据priority顺序来传递。例如button无论多小,只要优先级够高,总能最早响应到touch消息。

每增加一个触摸层到触摸层数组中的时候,都会首先根据该层的触摸优先级来把该触摸层插入到数组中的相应位置,注意这个方法是先根据传进去的触摸层传到CCTargetedTouchHandler的方法handlerWithDelegate中,这个方法返回一个CCTargetedTouchHandler对象,这里用基类指针指向他,然后把这个触摸处理对象pHandler添加到触摸处理对象数组m_pTargetedHandlers中:

void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegateint nPrioritybool bSwallowsTouches)

{    

    CCTouchHandler*pHandler= CCTargetedTouchHandler::handlerWithDelegate(pDelegatenPrioritybSwallowsTouches);

    if (! m_bLocked)

    {

        forceAddHandler(pHandler, m_pTargetedHandlers);

    }

    else

    {

        /* If pHandler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and return.

         * Refer issue #752(cocos2d-x)

         */

        if (ccCArrayContainsValue(m_pHandlersToRemove, pDelegate))

        {

            ccCArrayRemoveValue(m_pHandlersToRemove, pDelegate);

            return;

        }

        

        m_pHandlersToAdd->addObject(pHandler);

        m_bToAdd = true;

    }

}

void CCTouchDispatcher::forceAddHandler(CCTouchHandler *pHandlerCCArray *pArray)

{

    unsigned int u = 0;

 

    CCObject* pObj = NULL;

    CCARRAY_FOREACH(pArray, pObj)

     {

         CCTouchHandler *h = (CCTouchHandler *)pObj;

         if (h)

         {

 // 根据触摸优先级找到合适的位置,将触摸层插入到触摸层数组中

             if (h->getPriority() < pHandler->getPriority())

             {

                 ++u;

             }

 

             if (h->getDelegate() == pHandler->getDelegate())

             {

 // 不能重复添加同一个触摸层到触摸层数组中

                 CCAssert(0, "");

                 return;

             }

         }

     }

 

    pArray->insertObject(pHandler, u);

}

然后在touches方法中取出数组中元素的时候,就是直接从触摸层集合(数组)中的第一个触摸层开始分发,意思就是触摸优先级最高的层首先会接收到触摸信息,也就是上面说的不管你这个触摸层大小有多大。

分发器中还有一个方法用来设置触摸层的优先级:setPriority():

void CCTouchDispatcher::setPriority(int nPriorityCCTouchDelegate *pDelegate)

{

    CCAssert(pDelegate != NULL"");

 

    CCTouchHandler *handler = NULL;

 

    handler = this->findHandler(pDelegate);

 

    CCAssert(handler != NULL"");

    if (handler->getPriority() != nPriority)

    {

        handler->setPriority(nPriority);

        this->rearrangeHandlers(m_pTargetedHandlers);

        this->rearrangeHandlers(m_pStandardHandlers);

    }

}

首先去找这个触摸层:

CCTouchHandlerCCTouchDispatcher::findHandler(CCTouchDelegate *pDelegate)

{

    CCObject* pObj = NULL;

    CCARRAY_FOREACH(m_pTargetedHandlers, pObj)

    {

        CCTouchHandler* pHandler = (CCTouchHandler*)pObj;

        if (pHandler->getDelegate() == pDelegate)

        {

            return pHandler;

        }

    }

 

    CCARRAY_FOREACH(m_pStandardHandlers, pObj)

    {

        CCTouchHandler* pHandler = (CCTouchHandler*)pObj;

        if (pHandler->getDelegate() == pDelegate)

        {

            return pHandler;

        }

    } 

 

    return NULL;

}

还是一贯的顺序,先从触摸处理对象中获取目标触摸层,开始查找,找到的话,就返回,否则转到标准触摸层中查找,找到则返回,找不到就返回NULL。然后出现一个断言。

找到后,先判断这个层的优先级是否和现在设置的优先级相等,相等的话就不再去把触摸层数组中的所有触摸层重新排序了。否则,重新排序触摸层数组。

最新版的cocos2d-x3.0将会采用绘制顺序来分发触摸事件,即绘制顺序的逆序遍历,也就是从游戏世界中的最上层的物件开始接受事件。


注:setTouchPriority设置对象的响应等级,例如在某个panelA里的一个panelB,panel屏蔽了触摸事件并设置的响应等级为N,如果panelB想响应触摸事件,那么panelB调用setTouchPriority设置一个比panelA等级高的响应即可


内容概要:本文针对国内加密货币市场预测研究较少的现状,采用BP神经网络构建了CCi30指数预测模型。研究选取2018年3月1日至2019年3月26日共391天的数据作为样本,通过“试凑法”确定最优隐结点数目,建立三层BP神经网络模型对CCi30指数收盘价进行预测。论文详细介绍了数据预处理、模型构建、训练及评估过程,包括数据归一化、特征工程、模型架构设计(如输入层、隐藏层、输出层)、模型编译与训练、模型评估(如RMSE、MAE计算)以及结果可视化。研究表明,该模型在短期内能较准确地预测指数变化趋势。此外,文章还讨论了隐层节点数的优化方法及其对预测性能的影响,并提出了若干改进建议,如引入更多技术指标、优化模型架构、尝试其他时序模型等。 适合人群:对加密货币市场预测感兴趣的研究人员、投资者及具备一定编程基础的数据分析师。 使用场景及目标:①为加密货币市场投资者提供一种新的预测工具和方法;②帮助研究人员理解BP神经网络在时间序列预测中的应用;③为后续研究提供改进方向,如数据增强、模型优化、特征工程等。 其他说明:尽管该模型在短期内表现出良好的预测性能,但仍存在一定局限性,如样本量较小、未考虑外部因素影响等。因此,在实际应用中需谨慎对待模型预测结果,并结合其他分析工具共同决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值