视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
cocos2dx-3.0(26)CC
2020-11-09 07:55:02 责编:小采
文档


~~~~我的生活,我的点点滴滴!! 在介绍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);

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





下载本文
显示全文
专题