欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

cocos2dx-3.0(26) CC

程序员文章站 2022-05-03 21:34:45
...

~~~~我的生活,我的点点滴滴!! 在介绍CC_CALLBACK_X功能之前,我们需要学习一下c11 的几个新特性 std::function std::bind,总结了一些,先学习学习 狂点这里 我们假设你已经了解点上面的知识,我们来开始学习cocos2d-x 3.0的回调函数绑定新用法,先由h

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


在介绍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 ccMenuCallback;

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

std::function 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);

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