研究到cocos2d-x触摸这一块了,3.0和2.0相比已经有了很大的不同,使用更加方便和容易理解了。

直接进入正题,解释下,标题中3个用法的区别

通常来说,应用程序中更多使用的是单点触摸,为了简化单点触摸的处理,cocos2dx将一个触摸事件分为单点触摸和多点触摸两种类型,相应的对应单点和多点两种订阅者类型

EventListenerTouchAllAtOnce分为四种状态,开始触摸,移动,结束,取消,

每一个状态的回调函数都包含当前所有处于该种状态的触摸点,开发者需要使用触摸点的ID来区分每一个触摸点

EventListenerTouchOneByOne则相反,他将触摸某个状态的多个触摸点分为多次事件通知 ,他也分为四种状态,开始触摸,移动,结束,取消。

不同的地方是他的开始触摸方法 onTouchBegan返回值为bool,并且onTouchBegan是必须实现的,否则将收不到任何触摸事件通知,而EventListenerTouchAllAtOnce的onTouchBegan没有返回值,他的实现与否不影响后续状态的回调。

下面就牵扯到了返回true与false的问题。

onTouchBegan的返回值用来告诉EventDispatcher是否应该讲触摸点后续的触摸状态传递给订阅者。如果为false,onTouchMoved

onTouchEnded和onTouchCancelled,将接受不到任何回调。

但是注意的是,这个返回值只对当前订阅者有效,对后续订阅者的回调是控制不了的。比如

Node A 订阅了 EventListenerTouchOneByOne和 EventListenerTouchAllAtOnce两种触摸类型,前者的onTouchBegan返回false,那么当点击了NodeA的时候(就是一点一抬,不涉及移动),触发了点击事件,那么执行的顺序为这个

1 EventListenerTouchOneByOne:onTouchBegan

2EventListenerTouchAllAtOnce:onTouchBegan

3EventListenerTouchAllAtOnce:onTouchEnd,

说明false只控制了EventListenerTouchOneByOne类型的订阅,对于Node订阅的EventListenerTouchAllAtOnce类型,控制不了,该怎么走还是怎么走。

再比如:

NodeA订阅了EventListenerTouchOneByOne,NodeB也订阅了EventListenerTouchOneByOne,并且NodeA的localZ小于NodeB的localZ,NodeA的onTouchBegan返回false,NodeB的onTouchBegan返回true,当触发点击事件之后,执行顺序为

1  NodeA  EventListenerTouchOneByOne:onTouchBegan

2  NodeB  EventListenerTouchOneByOne:onTouchBegan

3 NodeB  EventListenerTouchOneByOne:onTouchEnd

说明NodeA的false只对订阅者nodeA起作用,对NodeB不起作用

这就是false的用法,如果想让当前订阅者继续往后面的状态传递,就返回true,不想让其传递,就返回false。

这种情况一般用在比如你点击了屏幕,但是坐标并没有落在某个sprite的可显示区域的上面,那么就返回false,反之返回true。比如下面得代码

bool isPointInNode(Vec2 pt, Node* node)

{

    Vec2 locationInNode = node->convertToNodeSpace(pt);

   cocos2d::Size s = node->getContentSize();

    cocos2d::Rect rect = cocos2d::Rect(, , s.width, s.height);

    if (rect.containsPoint(locationInNode))

    {

        return true;

    }

    return false;

}

       touchOneByOneListener->onTouchBegan = [&](Touch* touch, Event* event){

  auto target = static_cast<Sprite*>(event->getCurrentTarget());

                if (this->isPointInNode(touch->getLocation(), target))

                {

                    target->setOpacity();

                    return true;

                }

   return false;

          };

下面再说说setSwallowTouches的作用

当我们希望阻止一个触摸点向后面的订阅者继续分发,那么可以使用setSwallowTouches(true)来实现。

注意,swallowTouches设置需要在onTouchBegan返回true的时候才有效.

例如Sprite 和Sprite2都加到了同一个Node上,SpriteA后加,也就是SpriteA会先收到触摸事件,他们都订阅了EventListenerTouchOneByOne和

EventListenerTouchAllAtOnce

,如下代码

static const int TAG_BLUE_SPRITE = ;
static const int TAG_BLUE_SPRITE2 = ; auto touchOneByOneListener = EventListenerTouchOneByOne::create();
touchOneByOneListener->setSwallowTouches(true); touchOneByOneListener->onTouchBegan = [&](Touch* touch, Event* event){ return true; }; touchOneByOneListener->onTouchEnded = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
target->setOpacity(); }; auto touchAllAtOnceListener = EventListenerTouchAllAtOnce::create();
touchAllAtOnceListener->onTouchesBegan = [=](const std::vector<Touch*>& touches, Event* event){ }; touchAllAtOnceListener->onTouchesEnded = [=](const std::vector<Touch*>& touches, Event* event){ }; Sprite* sprite;
Sprite* sprite2; sprite = Sprite::create("CyanSquare.png");
sprite->setTag(TAG_BLUE_SPRITE);
addChild(sprite, ); sprite2 = Sprite::create("YellowSquare.png");
sprite2->setTag(TAG_BLUE_SPRITE2);
addChild(sprite2, ); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchOneByOneListener->clone(), sprite);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchAllAtOnceListener->clone(), sprite); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchOneByOneListener->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchAllAtOnceListener->clone(), sprite2); sprite->setPosition(,);
sprite2->setPosition(,);

注意我们设置 touchOneByOneListener->setSwallowTouches(true);

默认是false,通过设置了true,那么就可以阻止一个触摸点继续向后面的订阅者继续分发,

当点击事件触发后,执行顺序如下

1 spriteA  touchOneByOneListener->onTouchBegan

2  spriteA  touchOneByOneListener->onTouchEnd

因为spriteA的touchOneByOneListener->setSwallowTouches(true);他会阻止此后所有事件的分发,无论是spriteA自己的订阅类型EventListenerTouchAllAtOnce以及SpriteB的所有订阅类型。

这里说的一个应用的地方比如,spriteA订阅了单点触摸和多点触摸,但是他只想进行单点触摸的回调,而不想进行多点触摸的回调,那么就可以设置ontouchbegin返回true,并设置setSwallowTouches(true),这样就可以阻止多点触摸事件的分发。

最后说的是stopPropagation,他和setSwallowTouches类似,也是阻止触摸点后面订阅者的事件分发,但是不同的是setSwallowTouches阻止的很彻底,他会阻止后面所有状态的分发,began,end,cancelled,moved,并且必须ontouchbegan返回true才会起作用,而stopPropagation只是阻止某个状态的分发,比如move状态等。

stopPropagation只是停止当前当次触摸状态下的所有分发,例如Moved状态会触发多次,则第二次不受前一次的影响。某个状态也不会影响另一个状态的分发,例如move不影响end状态的分发,所有这些只需要明白,每个状态每次分发都是一次独立的事件通知

举例子如下:

static const int TAG_BLUE_SPRITE = ;
static const int TAG_BLUE_SPRITE2 = ; auto touchOneByOneListener = EventListenerTouchOneByOne::create();
touchOneByOneListener->setSwallowTouches(false); touchOneByOneListener->onTouchBegan = [&](Touch* touch, Event* event){ auto target = static_cast<Sprite*>(event->getCurrentTarget());
if(target->getTag() == TAG_BLUE_SPRITE2)
{
printf("sprite2单点触摸--ontouchbegan\n");
}
else{
printf("sprite单点触摸--ontouchbegan\n");
}
// event->stopPropagation();
return true; }; touchOneByOneListener->onTouchEnded = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
if(target->getTag() == TAG_BLUE_SPRITE2)
{
printf("sprite2单点触摸--ontouchend\n");
}
else{
printf("sprite单点触摸--ontouchend\n");
} }; auto touchAllAtOnceListener = EventListenerTouchAllAtOnce::create();
touchAllAtOnceListener->onTouchesBegan = [=](const std::vector<Touch*>& touches, Event* event){ auto target = static_cast<Sprite*>(event->getCurrentTarget());
if(target->getTag() == TAG_BLUE_SPRITE2)
{
printf("sprite2多点触摸--ontouchbegan\n");
}
else{
printf("sprite多点触摸--ontouchbegan\n");
} }; touchAllAtOnceListener->onTouchesEnded = [=](const std::vector<Touch*>& touches, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
if(target->getTag() == TAG_BLUE_SPRITE2)
{
printf("sprite2多点触摸--ontouchend\n");
}
else{
printf("sprite多点触摸--ontouchend\n");
} }; Sprite* sprite;
Sprite* sprite2; sprite = Sprite::create("CyanSquare.png");
sprite->setTag(TAG_BLUE_SPRITE);
addChild(sprite, ); sprite2 = Sprite::create("YellowSquare.png");
sprite2->setTag(TAG_BLUE_SPRITE2);
addChild(sprite2, ); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchOneByOneListener->clone(), sprite);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchAllAtOnceListener->clone(), sprite); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchOneByOneListener->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchAllAtOnceListener->clone(), sprite2); sprite->setPosition(,);
sprite2->setPosition(,);

执行代码结果如下

sprite2单点触摸--ontouchbegan

sprite单点触摸--ontouchbegan

sprite2多点触摸--ontouchbegan

sprite多点触摸--ontouchbegan

sprite2单点触摸--ontouchend

sprite单点触摸--ontouchend

sprite2多点触摸--ontouchend

sprite多点触摸--ontouchend

这个结果很容易理解,就是没有阻止事件的分发,一切都是按计划进行

如果 event->stopPropagation()的注释去掉,那么执行结果如下:

sprite2单点触摸--ontouchbegan

sprite2单点触摸--ontouchend

sprite2多点触摸--ontouchend

sprite多点触摸--ontouchend

这个的解释为:

sprite2的touchbegan先回调,然后stopprpagation,之后关于touchbegan的状态的事件分发就会停止,也就是sprite的touchbegan不会执行了,

而sprite的单点触摸的touchbegan不执行,那么sprite的单点触摸的其余状态也不会执行,但是sprite的多点触摸的touchbegan不执行,不影响多点触摸的其他状态的执行,所以sprite就执行了一个多点触摸的ontouchend

以上就是对这三种用法的简单解释,如果需要查看其工作原理,还是要深入到源码中,进行了解。

												

cocos2d-x中false,setSwallowTouches,stopPropagation的区别的更多相关文章

  1. e.preventDefault()和e.stopPropagation()以及return false的作用和区别

    前段时间开发中,遇到一个父元素和子元素都有事件时,发现会出现事件冒泡现象,虽然知道ev.stopPropagation()和ev.preventDefault()其中一个是阻止事件冒泡和阻止默认行为, ...

  2. JS中isPrototypeOf 和hasOwnProperty 的区别 ------- js使用in和hasOwnProperty获取对象属性的区别

    JS中isPrototypeOf 和hasOwnProperty 的区别 1.isPrototypeOf isPrototypeOf是用来判断指定对象object1是否存在于另一个对象object2的 ...

  3. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  4. 【jQuery】【转】jQuery中的trigger和triggerHandler区别

    trigger(event, [data]) 在每一个匹配的元素上触发某类事件. 这个函数也会导致浏览器同名的默认行为的执行.比如,如果用trigger()触发一个'submit',则同样会导致浏览器 ...

  5. jsp中两种include的区别【转】

    引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...

  6. jquery中attr和prop的区别、 什么时候用 attr 什么时候用 prop (转自 芈老头 )

    jquery中attr和prop的区别. 什么时候用 attr 什么时候用 prop   在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这 ...

  7. jQuery中.attr()和.prop()的区别

    之前学习jQuery的时候,学习到了两种取得标签的属性值的方法:一种是elemJobj.attr(),另一种是elemJobj.prop().而在学习JS的时候,只有一种方法elemObj.getAt ...

  8. jquery中attr和prop的区别(转)

    在网络上看到这样一篇关于jquery中attr和prop的区别文章,觉得不错,所以转载了. 在jQuery 1.6中,.attr()方法查询那些没有设置的属性,则会返回一个undefined.如果你要 ...

  9. hibernate中@Entity和@Table的区别

    Java Persistence API定义了一种定义,可以将常规的普通Java对象(有时被称作POJO)映射到数据库.这些普通Java对象被称作Entity Bean.除了是用Java Persis ...

随机推荐

  1. Hibernate 抓取策略fetch-1 (select join subselect)

    原文 :http://4045060.blog.51cto.com/4035060/1088025 部分参考:http://www.cnblogs.com/rongxh7/archive/2010/0 ...

  2. JS代码实现网站设为首页加入收藏功能

    <script language="javascript"> //加入收藏 function AddFavorite(sURL, sTitle) { try { win ...

  3. bzoj4705: 棋盘游戏

    Description 有一个N*M的棋盘,初始每个格子都是白色的. 行操作是指选定某一行,将这行所有格子的颜色取反(黑白互换). 列操作是指选定某一列,将这列所有格子的颜色取反. XX进行了R次行操 ...

  4. makefile详解 嵌套执行make,定义命令包

    嵌套执行make 在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而 ...

  5. IE浏览器的兼容模式代码细节解读

    兼容性对于网页设计师来说非常重要.虽然最好是建立一个完全不需依赖任何网页浏览器特性或功能的网站,但是有时候这是不可能实现的.而文件兼容模式能将网页限制在某个特定版本的IE中.可以使用 X-UA-Com ...

  6. Maven打包web工程成WAR

    其实不一定要通过Goals:package来打war包,直接run as maven bulid也行:

  7. 开发高峰时的CPU使用率

  8. UDP程序设计

        UDP是不可靠的连接,广泛应用于各种聊天工具     使用UDP发送的信息,对方不一定会接收到.所有的信息使用数据报的形式发送出去,这就要求客户端要始终等待服务器发送的信息才能进行接收.在Ja ...

  9. VC++、MFC、COM和ATL的区别

    今天看到的,感觉不错.转载了 一.什么是MFC 微软基础类(Microsoft Foundation Classes),实际上是微软提供的,用于在C++环境下编写应用程序的一个框架和引擎,VC++是W ...

  10. POJ 4047 Garden 线段树 区间更新

    给出一个n个元素的序列,序列有正数也有负数 支持3个操作: p x y 0.p=0时,把第x个的值改为y 1.p=1时,交换第x个和第y个的值 2.p=2时,问区间[x,y]里面连续k个的子序列的最大 ...