上篇触摸机制讲解中提到过存在两个按钮同时响应的问题。

问题描述

我们一般使用EventListenerTouchOneByOne注册触摸事件,但是这里的触摸消息是按顺序依次响应的,当你在屏幕中同时点击了两个按钮(A和B),彼此没有交集,触摸机制会依次触发两次触摸消息,一次按钮A的触摸消息,另一次按钮B的触摸消息。重要的是依次触发消息,每次触摸消息都会执行按钮A和按钮B的回调函数,根据回调函数里面的区域判断当前的触摸消息点击到了哪个按钮。这样按钮A和按钮B的回调函数会各执行两次,即使对每个按钮设置setSwallowtouches(true),也只对点击到按钮的那次触摸消息有作用。因为setSwallowtouches只在onTouchBegan返回true的时候才生效。假设按钮A的触摸优先级高,当处理按钮A的触摸消息时,区域判断返回true,触摸会被吞噬,按钮B不会被触发,但是处理按钮B的触摸消息时,按钮A的区域判断失败,setSwallowtouches不会执行,接着执行按钮B的回调函数。因此,两个按钮同时响应了。再提一点是,android上面是这样的,但是ios上,是不会同时响应两个按钮,这个可能跟操作系统有关吧。。

menu的实现方式

引擎中的Menu类已经对这种情况做了处理,可以参考一下如何下代码,具体思路是在触摸回调中加入一个状态的判定。开始处理一个触摸消息后,在执行onTouchBegan后,一直到onTouchEnd结束调用之前,禁用其他按钮的触摸。

bool Menu::onTouchBegan(Touch* touch,Event* event)
{
    if (_state != Menu::State::WAITING || ! _visible || !_enabled)
    {
        return false;
    }
    
    for (Node *c = this->_parent; c != nullptr; c = c->getParent())
    {
        if (c->isVisible() == false)
        {
            return false;
        }
    }
    
    _selectedItem = this->getItemForTouch(touch);
    if (_selectedItem)
    {
        _state = Menu::State::TRACKING_TOUCH;
        _selectedItem->selected();
        
        return true;
    }
    
    return false;
}

void Menu::onTouchEnded(Touch* touch,Event* event)
{
    CCASSERT(_state == Menu::State::TRACKING_TOUCH,"[Menu ccTouchEnded] -- invalid state");
    this->retain();
    if (_selectedItem)
    {
        _selectedItem->unselected();
        _selectedItem->activate();
    }
    _state = Menu::State::WAITING;
    this->release();
}
_state 变量就是为了防止按钮同时响应的状态变量,如果当前有按钮不是处在Menu::State::WAITING状态时,就说明有按钮正在响应,不处理当前的触摸消息。但是,这同样会引入一个问题,当一个scene的不同layer中有多个menu呢,那也会导致处于不同的menu的按钮同时响应。规避办法就要看开发者如何设计了,又或者一个scene共同一个menu。。

自定义按钮类的实现方式

项目中也有很多自定义按钮类的时候,一般会使用起来会比menu类更方便,更直接。自己封装的按钮类一般都会导致上述问题,尤其是当封装的按钮的种类过多时,要支持.9的,又要支持两张图片合成的,等等。所以这里提供一个解决思路,也是参照menu的实现方式。
自定义一个buttonmanger单例类,用来做点击的状态判定,当有按钮在执行触摸期间,禁止其他按钮执行,包括menu类型的按钮。
class ButtonManager;
static ButtonManager* m_instance = nullptr;
class ButtonManager
{
public:
    ButtonManager();
    ~ButtonManager();
    
    static ButtonManager* getInstance()
    {
        if (!m_instance)
        {
            m_instance = new ButtonManager();
        }
        return m_instance;
    }
    
    static void release()
    {
        if (m_instance)
        {
            delete m_instance;
            m_instance = nullptr;
        }
    }

private:

	CC_SYNTHESIZE(bool,m_bIsClickEnable,IsClickEnable);
    
private:
    
    std::vector<WWButton*>  m_allButtons;
    
};
很简单的buttonManager类,都不需要cpp文件,根据m_bIsClickEnable变量来判断当前按钮状态即可。

使用方法

bool WWButton::onTouchBegan(cocos2d::Touch *touch,cocos2d::Event *unused_event)
{
	if (!m_bEnable)
	{
		return false;
	}

	if (!ButtonManager::getInstance()->getIsClickEnable())
	{
		return false;
	}

	if (!containTouch(touch))
	{
		return false;
	}

	ButtonManager::getInstance()->setIsClickEnable(false);
    return true;
}

void WWButton::onTouchEnded(cocos2d::Touch *touch,cocos2d::Event *unused_event)
{
    ButtonManager::getInstance()->setIsClickEnable(true);
}
WWButton是一个按钮基类,只要继承此类,扩展的子类都不用担心按钮同时响应的问题。

cocos2dx 3.2 解决触摸事件中两个按钮同时响应的问题的更多相关文章

  1. HTML5实现直播间评论滚动效果的代码

    这篇文章主要介绍了HTML5实现直播间评论滚动效果的代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. HTML5 input新增type属性color颜色拾取器的实例代码

    type 属性规定 input 元素的类型。本文较详细的给大家介绍了HTML5 input新增type属性color颜色拾取器的实例代码,感兴趣的朋友跟随脚本之家小编一起看看吧

  3. amazeui模态框弹出后立马消失并刷新页面

    这篇文章主要介绍了amazeui模态框弹出后立马消失并刷新页面,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. 移动HTML5前端框架—MUI的使用

    这篇文章主要介绍了移动HTML5前端框架—MUI的使用的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. 前端监听websocket消息并实时弹出(实例代码)

    这篇文章主要介绍了前端监听websocket消息并实时弹出,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. HTML5之消息通知的使用(Web Notification)

    通知可以说是web中比较常见且重要的功能,私信、在线提问、或者一些在线即时通讯工具我们总是希望第一时间知道对方有了新的反馈。本篇文章主要介绍了HTML5之消息通知的使用(Web Notification),感兴趣的小伙伴们可以参考一下

  8. HTML5中的Web Notification桌面通知功能的实现方法

    这篇文章主要介绍了HTML5中的Web Notification桌面通知功能的实现方法,需要的朋友可以参考下

  9. HTML5仿微信聊天界面、微信朋友圈实例代码

    小编最近开发一个基于html5开发的一个微信聊天前端界面,功能很全面,下面小编给大家分享实例代码,需要的朋友参考下

  10. HTML5的postMessage的使用手册

    HTML5提出了一个新的用来跨域传值的方法,即postMessage,这篇文章主要介绍了HTML5的postMessage的使用手册的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部