cocos脏话过滤_Cocos2d-x 3.0 点击交互的四种处理

虽然重写了底层的dispatch,但对这层的使用影响并不大。我们同样需要重写:

//单点响应

virtual bool onTouchBegan(Touch* touch, Event  *event) override;

virtual void onTouchMoved(Touch* touch, Event  *event) override;

virtual void onTouchEnded(Touch* touch, Event  *event) override;

virtual void onTouchCancelled(Touch *touch, Event *event) override;

//多点响应

virtual bool onTouchesBegan(Touch* touch, Event  *event) override;

virtual void onTouchesMoved(Touch* touch, Event  *event) override;

virtual void onTouchesEnded(Touch* touch, Event  *event) override;

virtual void onTouchesCancelled(Touch *touch, Event *event) override;

//单点响应

virtual bool onTouchBegan(Touch* touch, Event *event) override;

virtual void onTouchMoved(Touch* touch, Event *event) override;

virtual void onTouchEnded(Touch* touch, Event *event) override;

virtual void onTouchCancelled(Touch *touch, Event *event) override;

//多点响应

virtual bool onTouchesBegan(Touch* touch, Event *event) override;

virtual void onTouchesMoved(Touch* touch, Event *event) override;

virtual void onTouchesEnded(Touch* touch, Event *event) override;

virtual void onTouchesCancelled(Touch *touch, Event *event) override;

重写这些函数来对layer的点击做处理。当然,我们需要:

setTouchEnabled(true)。

setTouchEnabled(true)。

此外有个小改动。对于单点触控响应,可以调用:

//设置为单点响应

setTouchMode(Touch::DispatchMode::ONE_BY_ONE);

//设置为多点响应(默认)

setTouchMode(Touch::DispatchMode::ALL_AT_ONCE);

//设置为单点响应

setTouchMode(Touch::DispatchMode::ONE_BY_ONE);

//设置为多点响应(默认)

setTouchMode(Touch::DispatchMode::ALL_AT_ONCE);

进行设置,而不需要再用设置Delegate的方式来做了。

3、TouchEvent响应

这是新加入的响应方式。它主要是使用在UIWidget上的。可以将其看做是函数回调的一个扩展,为更多的响应处理提供可能。使用方法大致是:

//声明

void touchButton(Object* object,TouchEventType type);

//挂接到控件上

uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));

//实现

void HelloWorld::touchButton(Object* object,TouchEventType type)

{

LabelTTF* label;

switch (type)

{

case TouchEventType::TOUCH_EVENT_BEGAN:

label = static_cast(getChildByTag(11));

label->setString("按下按钮");

break;

case TouchEventType::TOUCH_EVENT_MOVED:

label = static_cast(getChildByTag(11));

label->setString("按下按钮移动");

break;

case TouchEventType::TOUCH_EVENT_ENDED:

label = static_cast(getChildByTag(11));

label->setString("放开按钮");

break;

case TouchEventType::TOUCH_EVENT_CANCELED:

label = static_cast(getChildByTag(11));

label->setString("取消点击");

break;

default:

break;

}

}

//声明

void touchButton(Object* object,TouchEventType type);

//挂接到控件上

uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));

//实现

void HelloWorld::touchButton(Object* object,TouchEventType type)

{

LabelTTF* label;

switch (type)

{

case TouchEventType::TOUCH_EVENT_BEGAN:

label = static_cast(getChildByTag(11));

label->setString("按下按钮");

break;

case TouchEventType::TOUCH_EVENT_MOVED:

label = static_cast(getChildByTag(11));

label->setString("按下按钮移动");

break;

case TouchEventType::TOUCH_EVENT_ENDED:

label = static_cast(getChildByTag(11));

label->setString("放开按钮");

break;

case TouchEventType::TOUCH_EVENT_CANCELED:

label = static_cast(getChildByTag(11));

label->setString("取消点击");

break;

default:

break;

}

}

因为所有的UIWidget都要添加到UILayer上,而UILayer通常作为UI的Widget都会在最上层,所以可以“基本上”认为这种使用方式会优先于其他方式处理点击消息。因为UILayer也会有层级的改变,比如它和MenuItem之间的关系。所以说“基本上”。

4、Listener消息响应方式

这种实现也是新加入的。它更像是点击的一个层次过滤器。点击时,在listener队里中进行过滤。每一个listener检查自己保存的touch消息响应是否会被触发。一层一层过滤,最后在到Layer的touch消息响应。

我觉得它的设计的初衷是为任意sprite提供一套自己制定的点击响应。但这样的实现仍然要写很多条件判断,没有能够控件化。可能我的理解有些偏差,欢迎讨论。

它被设计成一个全局点击响应控制。具体的用法大致是这样:

//auto dispatcher = EventDispatcher::getInstance();

//  auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE);

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

auto myListener = EventListenerTouchOneByOne::create();

//如果不加入此句消息依旧会向下传递

myListener->setSwallowTouches(true);

myListener->onTouchBegan = [=](Touch* touch,Event* event)

{

//some check

if (pass)

{

return true;

}

return false;

};

myListener->onTouchMoved = [=](Touch* touch,Event* event)

{

//do something

};

myListener->onTouchEnded = [=](Touch* touch,Event* event)

{

//do something

};

dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1);

dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2);

//auto dispatcher = EventDispatcher::getInstance();

//auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE);

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

auto myListener = EventListenerTouchOneByOne::create();

//如果不加入此句消息依旧会向下传递

myListener->setSwallowTouches(true);

myListener->onTouchBegan = [=](Touch* touch,Event* event)

{

//some check

if (pass)

{

return true;

}

return false;

};

myListener->onTouchMoved = [=](Touch* touch,Event* event)

{

//do something

};

myListener->onTouchEnded = [=](Touch* touch,Event* event)

{

//do something

};

dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1);

dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2);

其原理是在dispatcher中检查listener列表,例如myListener或加进来的其他listener。然后每个listener检查自己中的Item看能否达到检查条件,例如:mySprite1,mySprite2。然后执行相应的操作。但这样的话,当控件很多的时候,每一次事件都进行这种双链表的检查操作不知会不会影响些性能?

3、实例

光说不练假把式,于是就动手写了一个上面的Demo:

点击背景区域可以移动整个场景,点击蓝色小方块可以半透明移动它,点击蓝色按钮可以更改文字,显示状态。点击右下角按钮退出程序。

项目配置可参照:

4、总结

根据不同的交互需要,选择不同的实现方式,会更有利于我们的维护和扩展,相应例子可以在下面下载。

Demo下载:http://download.csdn.net/detail/fansongy/6399291 不要资源分,觉得好劳烦点下 “顶” ~

Demo For Beta2 下载:http://download.csdn.net/detail/fansongy/6892047

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值