cocos2d-x3.0 触控机制和动作解析

本文介绍了Cocos2d-x3.0中引入的lambda表达式及其在触控机制中的应用。相较于2.x版本,3.0的事件处理可能看似更复杂,但提供了更多的灵活性。你可以选择直接继承并覆盖事件处理方法,或者使用自定义的方式。文章提到了`EventManager::onTouchBegan`等方法的使用,并提醒这是一年前的内容,仅作参考,不再维护。
摘要由CSDN通过智能技术生成

        想要使用新的触控机制,最好先要了解一下,lambda表达式。

        C++ 11引入了lambda表达式,所以Cocos2d-x3.0也应用了lambda表达式。
        由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:

        auto f = [](int a, int b){return a > b;};

       比如,

      auto closeItem = MenuItemImage::create(  
                                        "CloseNormal.png",  
                                        "CloseSelected.png",  
                                        CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));  
                                          
void HelloWorld::menuCloseCallback(Object* sender)  
{  
    Director::getInstance()->end();  
}  
        使用了lambda后

      auto closeItem = MenuItemImage::create(  
                                        "CloseNormal.png",  
                                        "CloseSelected.png",  
                                        [](Object* sender)  
                    {  
                        Director::getInstance()->end();//直接在这里添加按钮要调用的代码  
                    });  
        引用: Lambda

        3.0新的触控机制

首先创建三个Sprite

    //Create a "one by one" touch event listener (processes one touch at a time)
    auto listener1 = EventListenerTouchOneByOne::create();
    // When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
    listener1->setSwallowTouches(true);

    // Example of using a lambda expression to implement onTouchBegan event callback function
    listener1->onTouchBegan = [](Touch* touch, Event* event){
        // event->getCurrentTarget() returns the *listener's* sceneGraphPriority node.
        auto target = static_cast<Sprite*>(event->getCurrentTarget());

        //Get the position of the current point relative to the button
        Point locationInNode = target->convertToNodeSpace(touch->getLocation());
        Size s = target->getContentSize();
        Rect rect = Rect(0, 0, s.width, s.height);

        //Check the click area
        if (rect.containsPoint(locationInNode))
        {
            log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
            target->setOpacity(180);
            return true;
        }
        return false;
    };

    //Trigger when moving touch
    listener1->onTouchMoved = [](Touch* touch, Event* event){
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        //Move the position of current button sprite
        target->setPosition(target->getPosition() + touch->getDelta());
    };

    //Process the touch end event
    listener1->onTouchEnded = [=](Touch* touch, Event* event){
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        log("sprite onTouchesEnded.. ");
        target->setOpacity(255);
        //Reset zOrder and the display sequence will change
        if (target == sprite2)
        {
            sprite1->setZOrder(100);
        }
        else if(target == sprite1)
        {
            sprite1->setZOrder(0);
        }
    };


    //Add listener
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);

        _eventDispatcher是Node的一个属性,使用它来管理当前节点(Scene, Layer和Sprite)不同事件的分配。
        注意:上面的例子中在第二次以后调用addEventListenerWithSceneGraphPriority使用clone()方法是因为每一个事件监听器只能被添加一次,   addEventListenerWithSceneGraphPriority函数和addEventListenerWithFixedPriority函数会在添加事件监听器时设置一个已注册标识,一旦设置了标识,就不能再用于注册事件监听了。
        还有一个需要注意的:如果是固定优先值的监听器添加到一个节点(addEventListenerWithFixedPriority),那当这个节点被移除时必须同时手动移除这个监听器,但是添加场景图优先监听器到节点(addEventListenerWithSceneGraphPriority)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除。

        新的触碰制

        乍看之下新的事件处理机制好像比2.x版本的事件机制更加繁琐。但是在旧版本中,当你继承了一个被代理的类,例如一个定义了onTouchBegan()方法的类,那你的事件处理将会进入这些被代理的方法里。

        新的事件机制移除掉了代理的事件处理逻辑,将事件处理封装到监听器里,通过以下步骤来实现监听逻辑:
一个sprite可以将事件监听器添加到SceneGraphPriority的事件派发器(场景图优先事件派发器),一个事件触发时,回调函数将按它们的绘制次序来调用,即在场景前的优先调用;
        处理事件逻辑时,根据不同的情景来调用回调(识别点击区域,设置点击元素的透明度)来播放点击效果。


        FixedPriority和SceneGraphPriority
        事件派发器通过优先权来决定先执行哪个监听器。
        FixedPriority 整形值。低权值的事件监听器将优于高权值的事件监听器
        SceneGraphPriority Node的指针。Node的z顺序高的(绘制于顶部的)节点将优于z顺序低的节点。这将保证了诸如触碰事件的自顶向下传播


        如果你不喜欢这个方法,那么还有另一个方法供你选择

    // 创建一个事件监听器 OneByOne 为单点触摸  
    auto listener1 = EventListenerTouchOneByOne::create();  
    //设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没  
    //当设置为true时,在 onTouchBegan 中会执行相应的判断,以决定其返回值是 false 还是 true,  
    //用来处理触摸事件是否依据显示的顺序关系向后传递。  
    listener1->setSwallowTouches(true);  
  
    //在这里明确的定义出了开始触摸的函数  
    listener1->onTouchBegan = CC_CALLBACK_2(EventManager::onTouchBegan, this);  
    listener1->onTouchEnded = CC_CALLBACK_2(EventManager::onTouchEnded, this);  
    listener1->onTouchMoved = CC_CALLBACK_2(EventManager::onTouchMoved, this);  
  
    //CC_CALLBACK说明  
    //CC_CALLBACK_0  0个参数  
    //CC_CALLBACK_1  1个参数  
    //CC_CALLBACK_2  2个参数  
    //.................   
  
  
    // 添加监听器    
    //有一点非常重要,FixedPriority listener添加完之后需要手动remove,  
    //而SceneGraphPriority listener是跟node绑定的,在node的析构函数中会被移除  
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);  
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);  
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
        

         这个和上一段作用是相同的,不过这个比较自定义一点,上边的一段明显比较官方一点,大家用哪个,都是可以的。但是,比如

    bool EventManager::onTouchBegan(Touch* touch, Event* event)

        这些东西,是需要在.h文件定义的。


最后说明下**********************这篇文章为1年前所编辑,所以只时发布了出去,不会提供任何维护,而且,东西也挺简单的大家看看就算了

        


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值