zoukankan      html  css  js  c++  java
  • Cocos2d-x MultipleTouch & CCControllButton's confusion

    在cocos2dx的程序设计中有时候会遇到需要多点触摸的功能,下面先介绍一下在cocos2dx中多点触摸的一般规则,然后介绍我遇到的一个有关多点触摸的情景的解决方案。


    (一)使用多点触摸规则:

    关于多点触摸在TestCPP中有一个例子展示,通过这个例子就可以知道多点触摸是如何使用的了。

    简单说一下步骤:

    ①开启多点触摸

    在ios文件夹中的AppController.mm文件的

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中:

     

    [__glView setMultipleTouchEnabled:true]; 

    ②注册触摸事件( StandardDelegate )

    a)可以在onEnter方法中: CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);

    b)也可以重写: virtual void registerWithTouchDispatcher(void); 在这个方法中:

    CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this0);

    而且注意要在init方法中: setTouchEnabled(true);

    为什么呢?因为在init方法中,setTouchEnabled(true); 会自动回调 registerWithTouchDispatcher 方法。


    ③触摸事件委托方法

    virtual void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
        virtual void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
        virtual void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
        virtual void ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);


    在每一个委托方法中,可以用下面的遍历方法,获取每一个触摸点的信息。

    CCSetIterator iter = pTouches->begin();
        
        for (; iter != pTouches->end(); iter++)
        {
            CCTouch* pTouch = (CCTouch*)(*iter);
            CCPoint location = pTouch->getLocation();
            
        }



    (二)一个类似多点触摸情景解决方法

    情景介绍:在layer中,需要按住某一个按键,然后在按键保持按下的时候,执行某一个事件(也是要触摸屏幕执行的),如果松开按键,那么执行这个事件结束。

    A)那么我的第一个反应就是使用多点触摸,理论上是可以解决的,但是感觉判断起来有点繁琐,所有暂时放弃了这个解决方法。

    B)我就想到要CCMenu item 或者 CCControllButton 这类的“按键” 实现,当按键 保持按下 的时候,那么就可以判断它的状态(isSelected),在一个定时器方法中判断按键的状态,根据这个状态值,就可以进行相应处理,恩,这样似乎简单了许多。


    注意:在这个情景中其实也是多点触摸的,注意到按键按下是一个触摸点,然后在执行某一个事件,也是要触摸屏幕执行,那么又是一个触摸点。那么我们同样要开启多点触摸,这一点很重要。

    然而,如果我们 在按键按下的时候执行的事件,只是需要一个触摸点,那么注册为 TargetedDelegate 就可以了;如果需要多个触摸点,那么注册为 StandardDelegate。


    ①首先用到 CCMenuItem

    在这类按键中 有两个 属性:

    bool m_bSelected;
    bool m_bEnabled;


    确定按键是否选中,和是否可用。

    那么在这个情景中,我们使用 它的是否选中 这个属性,通过 virtualbool isSelected(); 方法就可以获取到这个属性的值。

    在定时器方法中:

     if (item->isSelected()) {
            CCLOG("selected");
        }
        else
        {
            CCLOG("unselected");
        }

    ②然后再试一下 CCControllButton


    A)首先注意CCControllButton 中的触摸优先级是 1 ,所以 layer 注册的接收触摸事件优先级 就必须 大于等于 1.

    下面看看为什么CCControllButton 中的触摸优先级是 1:

    CCControllButton 是继承自:CCControl 

    在 CCControl 中的init 方法中:

    bool CCControl::init()
    {
        if (CCLayer::init())
        {
            //this->setTouchEnabled(true);
            //m_bIsTouchEnabled=true;
            // Initialise instance variables
            m_eState=CCControlStateNormal;
            setEnabled(true);
            setSelected(false);
            setHighlighted(false);
    
            // Set the touch dispatcher priority by default to 1
            this->setTouchPriority(1);
            // Initialise the tables
            m_pDispatchTable = new CCDictionary(); 
            // Initialise the mapHandleOfControlEvents
            m_mapHandleOfControlEvent.clear();
            
            return true;
        }
        else
        {
            return false;
        }
    }


    注意到了吧:

    // Set the touch dispatcher priority by default to 1

    this->setTouchPriority(1);

    B) CCControllButton 中检测按键是否选中的状态 是使用 isHighlighted 方法,而不是 isSelected() .很奇怪吧!奋斗

    在CCMenuItem 中是用 isSelected ,那么理论上,在 CCControllButton 也是类似的。

    下面分析一下问题:

    我们 CCControllButton 继承 CCControl ,而 CCControl 继承 CCLayerRGBA ,那么说到底,其实 CCControllButton 就是继承自 

    CCLayer。

    那么肯定是要在 触摸事件的回调方法中 对CCControllButton的状态进行设置的。

    可以发现:

     

    virtual void setEnabled(bool enabled);
        virtual void setSelected(bool enabled);
        virtual void setHighlighted(bool enabled);

    居然,有一个 setHighlighted方法,这个和 setSelected 方法有什么区别呢? 两个方法所对应的属性应该都是在button选中的吧!疑问


    带着疑问,继续-----

    我们找到触摸事件的回调方法(只显示前两个touch began 和 moved 方法):

     

    bool CCControlButton::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
    {
        if (!isTouchInside(pTouch) || !isEnabled() || !isVisible() || !hasVisibleParents() )
        {
            return false;
        }
        
        for (CCNode *c = this->m_pParent; c != NULL; c = c->getParent())
        {
            if (c->isVisible() == false)
            {
                return false;
            }
        }
        
        m_isPushed = true;
        this->setHighlighted(true);
        sendActionsForControlEvents(CCControlEventTouchDown);
        return true;
    }
    
    void CCControlButton::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
    {    
        if (!isEnabled() || !isPushed() || isSelected())
        {
            if (isHighlighted())
            {
                setHighlighted(false);
            }
            return;
        }
        
        bool isTouchMoveInside = isTouchInside(pTouch);
        if (isTouchMoveInside && !isHighlighted())
        {
            setHighlighted(true);
            sendActionsForControlEvents(CCControlEventTouchDragEnter);
        }
        else if (isTouchMoveInside && isHighlighted())
        {
            sendActionsForControlEvents(CCControlEventTouchDragInside);
        }
        else if (!isTouchMoveInside && isHighlighted())
        {
            setHighlighted(false);
            
            sendActionsForControlEvents(CCControlEventTouchDragExit);        
        }
        else if (!isTouchMoveInside && !isHighlighted())
        {
            sendActionsForControlEvents(CCControlEventTouchDragOutside);        
        }
    }


    终于有点发现了,原来,都是只用到了  setHighlighted 设置button的是否选中状态,根本就和 setSelected 没有半点关系,难怪,我们只能用 isHighlighted 方法来检测 button 的是否选中状态了。


    到这里,似乎问题就结束了。但是我内心有一个深深的好奇:为什么要设多一个这样用处不是很大的 setSelected 方法呢?或者说,setHighlighted 方法抢占了 setSelected 本该有的作用呢?

    我在 官方网站论坛上,发了一个帖子,欢迎大神回复指导一下:点击打开链接


    其实我为他们找到了两个可能的理由:

    ① CCMenuItem 和 CCControllButton 这两个类是不同的两个程序员编写的,他们之间缺少交流,所以导致了这个差异。但是这个很明显对我们来说是一个潜在的坑呀!敲打


    CCControllButton 提供 setSelected 是为了给我们提供一个手动设置 按键是否选中状态 的方法。但是这样的方法实际过程中,用处大吗?,大吗?敲打


    好咯,大致就是这么些个内容了,关于最后的问题,欢迎大神指导。吐舌头






  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3435885.html
Copyright © 2011-2022 走看看