想要使用新的触控机制,最好先要了解一下,lambda表达式。
C++ 11引入了lambda表达式,所以Cocos2d-x3.0也应用了lambda表达式。
由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:
auto f = [](int a, int b){return a > b;};
比如,
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
void HelloWorld::menuCloseCallback(Object* sender)
{
Director::getInstance()->end();
}
使用了lambda后
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
[](Object* sender)
{
Director::getInstance()->end();//直接在这里添加按钮要调用的代码
});
引用:
Lambda
3.0新的触控机制
首先创建三个Sprite
//Create a "one by one" touch event listener (processes one touch at a time)
auto listener1 = EventListenerTouchOneByOne::create();
// When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
listener1->setSwallowTouches(true);
// Example of using a lambda expression to implement onTouchBegan event callback function
listener1->onTouchBegan = [](Touch* touch, Event* event){
// event->getCurrentTarget() returns the *listener's* sceneGraphPriority node.
auto target = static_cast<Sprite*>(event->getCurrentTarget());
//Get the position of the current point relative to the button
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
//Check the click area
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
target->setOpacity(180);
return true;
}
return false;
};
//Trigger when moving touch
listener1->onTouchMoved = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
//Move the position of current button sprite
target->setPosition(target->getPosition() + touch->getDelta());
};
//Process the touch end event
listener1->onTouchEnded = [=](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
log("sprite onTouchesEnded.. ");
target->setOpacity(255);
//Reset zOrder and the display sequence will change
if (target == sprite2)
{
sprite1->setZOrder(100);
}
else if(target == sprite1)
{
sprite1->setZOrder(0);
}
};
//Add listener
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
_eventDispatcher是Node的一个属性,使用它来管理当前节点(Scene, Layer和Sprite)不同事件的分配。
注意:上面的例子中在第二次以后调用addEventListenerWithSceneGraphPriority使用clone()方法是因为每一个事件监听器只能被添加一次, addEventListenerWithSceneGraphPriority函数和addEventListenerWithFixedPriority函数会在添加事件监听器时设置一个已注册标识,一旦设置了标识,就不能再用于注册事件监听了。
还有一个需要注意的:如果是固定优先值的监听器添加到一个节点(addEventListenerWithFixedPriority),那当这个节点被移除时必须同时手动移除这个监听器,但是添加场景图优先监听器到节点(addEventListenerWithSceneGraphPriority)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除。
新的触碰制
乍看之下新的事件处理机制好像比2.x版本的事件机制更加繁琐。但是在旧版本中,当你继承了一个被代理的类,例如一个定义了onTouchBegan()方法的类,那你的事件处理将会进入这些被代理的方法里。
新的事件机制移除掉了代理的事件处理逻辑,将事件处理封装到监听器里,通过以下步骤来实现监听逻辑:一个sprite可以将事件监听器添加到SceneGraphPriority的事件派发器(场景图优先事件派发器),一个事件触发时,回调函数将按它们的绘制次序来调用,即在场景前的优先调用;
处理事件逻辑时,根据不同的情景来调用回调(识别点击区域,设置点击元素的透明度)来播放点击效果。
FixedPriority和SceneGraphPriority
事件派发器通过优先权来决定先执行哪个监听器。
FixedPriority 整形值。低权值的事件监听器将优于高权值的事件监听器
SceneGraphPriority Node的指针。Node的z顺序高的(绘制于顶部的)节点将优于z顺序低的节点。这将保证了诸如触碰事件的自顶向下传播
如果你不喜欢这个方法,那么还有另一个方法供你选择
// 创建一个事件监听器 OneByOne 为单点触摸
auto listener1 = EventListenerTouchOneByOne::create();
//设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
//当设置为true时,在 onTouchBegan 中会执行相应的判断,以决定其返回值是 false 还是 true,
//用来处理触摸事件是否依据显示的顺序关系向后传递。
listener1->setSwallowTouches(true);
//在这里明确的定义出了开始触摸的函数
listener1->onTouchBegan = CC_CALLBACK_2(EventManager::onTouchBegan, this);
listener1->onTouchEnded = CC_CALLBACK_2(EventManager::onTouchEnded, this);
listener1->onTouchMoved = CC_CALLBACK_2(EventManager::onTouchMoved, this);
//CC_CALLBACK说明
//CC_CALLBACK_0 0个参数
//CC_CALLBACK_1 1个参数
//CC_CALLBACK_2 2个参数
//.................
// 添加监听器
//有一点非常重要,FixedPriority listener添加完之后需要手动remove,
//而SceneGraphPriority listener是跟node绑定的,在node的析构函数中会被移除
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
这个和上一段作用是相同的,不过这个比较自定义一点,上边的一段明显比较官方一点,大家用哪个,都是可以的。但是,比如
bool EventManager::onTouchBegan(Touch* touch, Event* event)
这些东西,是需要在.h文件定义的。
最后说明下**********************这篇文章为1年前所编辑,所以只时发布了出去,不会提供任何维护,而且,东西也挺简单的大家看看就算了