zoukankan      html  css  js  c++  java
  • 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);











  • 相关阅读:
    leetcode1161
    leetcode1160
    校招真题练习034 倒水(贝壳)
    校招真题练习033 音乐列表(贝壳)
    校招真题练习032 连续相同字符串(头条)
    校招真题练习031 三支球队比分(头条)
    leetcode1144
    ArrayQueue(队列)
    LinkQueue(链队)
    快速幂
  • 原文地址:https://www.cnblogs.com/fzll/p/3954606.html
Copyright © 2011-2022 走看看