cocos2dx-3.0(26) CC_CALLBACK介绍及屏蔽Touch(暂停、开始)的方法

~~~~我的生活,我的点点滴滴!!


在介绍CC_CALLBACK_X功能之前,我们需要学习一下c++11 的几个新特性 std::function std::bind,总结了一些,先学习学习 狂点这里


我们假设你已经了解点上面的知识,我们来开始学习cocos2d-x 3.0的回调函数绑定新用法,先由helloWorld里面的关闭按钮引起我们的话题 :

	auto closeItem = MenuItemImage::create("0.png", "1.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
	closeItem->setPosition(Point(400,50));

	auto menu = Menu::create(closeItem, NULL);
	menu->setPosition(Point::ZERO);
	this->addChild(menu);

是不是和2.x的不同,我们不管2.x是怎么用的,反证3.x这个新用法是非常好用的,我们进入CC_CALLBACK_1里面看看到底是什么货色

// new callbacks based on C++11
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)

用到了std::bind,##__VA_ARGS__是可变参数宏,std::placeholders之类为占位符,我们发现CC_CALLBACK_1 _2 _3 分别是1-3个事先不绑定参数,和N个可变参数的绑定(##__VA_ARGS__),而且要注意到其中 不指定回调函数参数  和  指定回调函数参数  的顺序,注意不事先指定的在前,事先指定的在后

我们先粗俗的这样理解一下,如果要绑定的回调函数不带参数 那就使用 CC_CALLBACK_0 如果带有1个就使用CC_CALLBACK_1,依次类推下去,我们看看他怎么和function结合起来用的,看下MenuItemImage::create的声明

/** creates a menu item with a normal and selected image with a callable object */
    static MenuItemImage* create(const std::string&normalImage, const std::string&selectedImage, const ccMenuCallback& callback);
最后一个参数是回调的声明,我们去看看

typedef std::function<void(Ref*)> ccMenuCallback;

所以最后直白点就是下面代码

std::function<void(Ref*)> ccMenuCallback = std::bind(&HelloWorld::menuCloseCallback, this, std::placeholders::_1);

我们会疑问,那个事先未绑定的参数是在什么时候传进去的了。我们调试跟踪,在下面这一段代码里面设置进去

在他的直属父类里面,由触摸结束 onTouchEnded 里调用

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();
}
  _selectedItem->activate(); 这个activate()为虚函数,他会调用自己的实现

void MenuItem::activate()
{
    if (_enabled)
    {
        if( _callback )
        {
			_callback(this);
        }
#if CC_ENABLE_SCRIPT_BINDING
        if (kScriptTypeNone != _scriptType)
        {
            BasicScriptData data(this);
            ScriptEvent scriptEvent(kMenuClickedEvent,&data);
            ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent);
        }
#endif
    }
}

_callback(this)在这里设置了。我们可以把回调函数里面添加两参数,反正是我自己的定义的,来验证一下。

	//我们随便添加三个参数,看看对不对,我们在里面只打印输出一下
    void menuCloseCallback(cocos2d::Ref* pSender, int a, int b, int c);


然后我们改一下代码

auto closeItem = MenuItemImage::create("0.png", "1.png", 
					std::bind(&HelloWorld::menuCloseCallback, this, std::placeholders::_1, 3, 4, 5));

	closeItem->setPosition(Point(400,50));

	auto menu = Menu::create(closeItem, NULL);
	menu->setPosition(Point::ZERO);
	this->addChild(menu);

输出:

menuClose a = 3, b = 4, c = 5

只要确定把不先绑定的放前面,确定的放后面,就行了。


好了,简简单单的把CC_CALLBACK说完了,以后在补充吧。


接下来讲一下怎么添加一个空白Layer层来实现类似于游戏中“暂停”等功能?

实现起来不难,网上搜搜也有很多方法,其他的方法我这里不说,我只想知道通过添加一个空白层到最上面的方法,下面先看代码:


#include "SwallowTouch.h"


SwallowTouch *SwallowTouch::Create(Color4B &color, float width, float height)
{
	SwallowTouch *ret = new SwallowTouch();

	if( ret && ret->init(color, width, height) )
	{
		ret->autorelease();

		return ret;
	}

	CC_SAFE_DELETE(ret);

	return nullptr;
}

bool SwallowTouch::init(const Color4B& color, GLfloat width, GLfloat height)
{
	if( !LayerColor::initWithColor(color, width, height) )
	{
		return false;
	}

	auto listener = EventListenerTouchOneByOne::create();
	//设置吞噬Touches
	listener->setSwallowTouches(true);
	//简单的lambda表达式设置返回值为true,必须返回true,这样才能有效
	listener->onTouchBegan = [](Touch* touch, Event* event)
	{
		return true;
	};
	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

	return true;
}

继承一个LayerColor,当然可以继承Layer,这里我是为了方便设置颜色来显示是否我的“吞噬层”设置成功与否,然后在init里面添加触摸及触摸吞噬(这里我突然豁然开朗了,以前遇到过一个问题,触摸机制没写在Layer层里面后会产生两次触摸,这里算是明白了),

最后只需要在使用的时候,设置他的zOrder值比当前所有的精灵的zOrder都大就ok了,看下面使用代码:

SwallowTouch *st = SwallowTouch::Create(Color4B(0,0,0,100), 200,300);
        st->setPosition(Point(visibleSize.width * 0.5, visibleSize.height * 0.5));
        //设置一个很大的zOrder
        this->addChild(st, 10000);

这样就实现了屏蔽此层下面所有的触摸了。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值