cocos2dx 3.0 触摸机制

在cocos2dx 3.0版本号中,废弃了以往2.x版本号的写法,我们先来看一下Layer.h中的一段代码

/* Callback function should not be deprecated, it will generate lots of warnings.
        Since 'setTouchEnabled' was deprecated, it will make warnings if developer overrides onTouchXXX and invokes setTouchEnabled(true) instead of using EventDispatcher::addEventListenerWithXXX.
    */
        //单点触摸
        virtual bool onTouchBegan(Touch *touch, Event *unused_event); 
    virtual void onTouchMoved(Touch *touch, Event *unused_event); 
    virtual void onTouchEnded(Touch *touch, Event *unused_event); 
    virtual void onTouchCancelled(Touch *touch, Event *unused_event);
        //多点触摸
    virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event);

单点触摸:(即仅仅有注冊的Layer才干接收触摸事件)

onTouchBegan:假设返回true:本层的兴许Touch事件能够被触发,并阻挡向后层传递

假设返回false,本层的兴许Touch事件不能被触发,并向后传递

简单点来说,假设

1.Layer 仅仅有一层的情况:

virtual bool onTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

a.返回false,则ccTouchMoved(),ccTouchEnded()不会再接收到消息

b.返回true,则ccTouchMoved(),ccTouchEnded()能够接收到消息

2.Layer 有多层的情况:

virtual bool onTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

a.返回false,则本层的onTouchMoved(),onTouchEnded()不会再接收到消息,可是本层之下的其他层会接收到消息

b.返回true,则本层的onTouchMoved(),onTouchEnded()能够接收到消息,可是本层之下的其他层不能再接收到消息

单点触摸简单使用方法:

在Layer中加入例如以下代码,重写onTouchxxx函数

        auto dispatcher = Director::getInstance()->getEventDispatcher();
        auto listener = EventListenerTouchOneByOne::create();
        listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan,this);
        listener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved,this);
        listener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded,this);
        listener->setSwallowTouches(true);//不向下传递触摸
        dispatcher->addEventListenerWithSceneGraphPriority(listener,this);

listener->setSwallowTouches(true),不向下触摸,简单点来说,比方有两个sprite ,A 和 B,A在上B在下(位置重叠),触摸A的时候,B不会受到影响

listener->setSwallowTouches(false)反之,向下传递触摸,触摸A也等于触摸了B

多点触摸点单使用方法(多个Layer获取屏幕事件):

        auto dispatcher = Director::getInstance()->getEventDispatcher();
        auto listener1 = EventListenerTouchAllAtOnce::create();
        listener1->onTouchesBegan = CC_CALLBACK_2(GameLayer::onTouchesBegan,this);
        listener1->onTouchesMoved = CC_CALLBACK_2(GameLayer::onTouchesMoved,this);
        listener1->onTouchesEnded = CC_CALLBACK_2(GameLayer::onTouchesEnded,this);
        dispatcher->addEventListenerWithSceneGraphPriority(listener1,this);

或者setTouchEnabled(true),然后重写layer的onTouchsxxx函数

关于eventDispatcher:

  • 获取方法:

  • auto dispatcher = Director::getInstance()->getEventDispatcher();

事件监听器包括下面几种:

  • 触摸事件 (EventListenerTouch)
  • 键盘响应事件 (EventListenerKeyboard)
  • 加速记录事件 (EventListenerAcceleration)
  • 鼠标响应事件 (EventListenerMouse)
  • 自己定义事件 (EventListenerCustom)

    以上事件监听器统一由 _eventDispatcher 来进行管理。

优先权:

1.优先级越低,越先响应事件

2.假设优先级同样,则上层的(z轴)先接收触摸事件

有两种方式将 事件监听器 listener1 加入到 事件调度器_eventDispatcher 中:

void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
    void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)

代码展开一下:

void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
    CCASSERT(listener && node, "Invalid parameters.");
    CCASSERT(!listener->isRegistered(), "The listener has been registered.");
    
    if (!listener->checkAvailable())
        return;
    
    listener->setSceneGraphPriority(node);
    listener->setFixedPriority(0);
    listener->setRegistered(true);
    
    addEventListener(listener);
}
void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
{
    CCASSERT(listener, "Invalid parameters.");
    CCASSERT(!listener->isRegistered(), "The listener has been registered.");
    CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
    
    if (!listener->checkAvailable())
        return;
    
    listener->setSceneGraphPriority(nullptr);
    listener->setFixedPriority(fixedPriority);
    listener->setRegistered(true);
    listener->setPaused(false);

    addEventListener(listener);
}

(1)addEventListenerWithSceneGraphPriority 的事件监听器优先级是0,并且在 addEventListenerWithFixedPriority 中的事件监听器的优先级不能够设置为 0,由于这个是保留给 SceneGraphPriority 使用的。

(2)另外,有一点很重要,FixedPriority listener加入完之后须要手动remove,而SceneGraphPriority listener是跟node绑定的,在node的析构函数中会被移除。

移除方法:

dispatcher->removeEventListener(listener);