cocos2d-x中层和菜单的触摸控制

首先是层CCLayer,其实CCLayer已经继承了触摸委托类了

class CC_DLL CCLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate


这样一来只要重写它的方法便可处理相应的触摸操作:

class CC_DLL CCLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate
{
public:
    ...
    
    // default implements are used to call script callback if exist
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);

    // default implements are used to call script callback if exist
    virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
    virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
    virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
    virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);
    
    virtual void registerWithTouchDispatcher(void);//注册触摸监听
    
   
    virtual bool isTouchEnabled();//是否开启触摸
    virtual void setTouchEnabled(bool value);//设置该层是否允许触摸
    
    virtual void setTouchMode(ccTouchesMode mode);//设置触摸模式
    virtual int getTouchMode();//获取触摸模式
    
    /** priority of the touch events. Default is 0 */
    virtual void setTouchPriority(int priority)//设置触摸优先级
    virtual int getTouchPriority();//获取触摸优先级

    ...
protected:   
    bool m_bTouchEnabled;//记录是否允许触摸
    ...
    
private:
    ...
    
    int m_nTouchPriority;//记录触摸优先级
    ccTouchesMode m_eTouchMode;//记录触摸模式
    
    ...
};
其实要开启该层的触摸只要调用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);//从分发器中移除,关闭触摸
            }
        }
    }
}
void CCLayer::registerWithTouchDispatcher()
{
    CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();

    // Using LuaBindings
    if (m_pScriptTouchHandlerEntry)//脚本相关
    {
	    if (m_pScriptTouchHandlerEntry->isMultiTouches())
	    {
	       pDispatcher->addStandardDelegate(this, 0);
	       LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptTouchHandlerEntry->getHandler());
	    }
	    else
	    {
	       pDispatcher->addTargetedDelegate(this,
						m_pScriptTouchHandlerEntry->getPriority(),
						m_pScriptTouchHandlerEntry->getSwallowsTouches());
	       LUALOG("[LUA] Add touch event handler: %d", m_pScriptTouchHandlerEntry->getHandler());
	    }
    }
    else
    {
        if( m_eTouchMode == kCCTouchesAllAtOnce ) {//判断是否是标准触摸
            pDispatcher->addStandardDelegate(this, 0);//注册到标准触摸分发器中
        } else {
            pDispatcher->addTargetedDelegate(this, m_nTouchPriority, true);//注册到目标触摸分发器中,默认优先级m_nTouchPriority为0
        }
    }
}
默认情况下层开启的是标准触摸,如果要改成目标触摸,设置该层的触摸模式即可,即调用setTouchMode方法。

当然当层被移除时要从分发器中移除触摸事件,如果有开启触摸的话:

void CCLayer::onExit()
{
    CCDirector* pDirector = CCDirector::sharedDirector();
    if( m_bTouchEnabled )//如果开启了触摸
    {
        pDirector->getTouchDispatcher()->removeDelegate(this);//移除触摸
        // [lua]:don't unregister script touch handler, or the handler will be destroyed
        // unregisterScriptTouchHandler();
    }

    // remove this layer from the delegates who concern Accelerometer Sensor
    if (m_bAccelerometerEnabled)
    {
        pDirector->getAccelerometer()->setDelegate(NULL);
    }

    // remove this layer from the delegates who concern the keypad msg
    if (m_bKeypadEnabled)
    {
        pDirector->getKeypadDispatcher()->removeDelegate(this);
    }

    CCNode::onExit();
}


其次是菜单的触摸操作。菜单是继承自于CCLayerRGBA,而CCLayerRGBA又继承自与CCLayer,所有菜单同样是继承了触摸委托类。

class CC_DLL CCMenu : public CCLayerRGBA
class CC_DLL CCLayerRGBA : public CCLayer, public CCRGBAProtocol

默认情况下,菜单的触摸优先级非常高,是-128,被声明在一个枚举中

enum {
    //* priority used by the menu for the event handler
    kCCMenuHandlerPriority = -128,//菜单默认的触摸优先级
};

菜单的触摸实现几乎跟层的一样,只不过菜单默认是开启触摸的,而层是没有开启,需要手动开启,并也已经重写触摸的4个操作方法

    virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
    virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
    virtual void ccTouchCancelled(CCTouch *touch, CCEvent* event);
    virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
这样一来开发者就无需去处理这些触摸方法,所以在初始化菜单就已经帮我们开启了触摸,设置为目标触摸和并带有吞噬。
bool CCMenu::init()
{
    return initWithArray(NULL);
}

bool CCMenu::initWithArray(CCArray* pArrayOfItems)
{
    if (CCLayer::init())
    {
        setTouchPriority(kCCMenuHandlerPriority);//设置菜单的触摸优先级(kCCMenuHandlerPriority = -128)
        setTouchMode(kCCTouchesOneByOne);//设置菜单的触摸模式为目标触摸,并带有吞噬
        setTouchEnabled(true);//开启触摸

        m_bEnabled = true;//记录已开启触摸
        ...
        
        return true;
    }
    return false;
}
同样,在移除菜单也要把触摸事件从分发器中移除:

void CCMenu::onExit()
{
    if (m_eState == kCCMenuStateTrackingTouch)
    {
        if (m_pSelectedItem)
        {
            m_pSelectedItem->unselected();
            m_pSelectedItem = NULL;
        }
        
        m_eState = kCCMenuStateWaiting;
    }

    CCLayer::onExit();//调用父类的onExit,它会帮菜单将触摸事件从分发器中移除掉,取消掉触摸监听
}

所以只要理解了触摸原理,如何处理这些触摸事件简直就是很easy!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值