1、演示场景优先事件监听示例:
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
origin.y + closeItem->getContentSize().height / 2));
auto removeAllTouchItem = MenuItemFont::create("删除所有的触摸监听器",
[this](Ref* sender) {
auto senderItem = static_cast<MenuItemFont*>(sender);
senderItem->setString("触摸监听器删除成功");
_eventDispatcher->removeEventListenersForType(EventListener::Type::TOUCH_ONE_BY_ONE);
});
removeAllTouchItem->setPosition(visibleSize.width / 2, visibleSize.height * 0.2);
auto menu = Menu::create(removeAllTouchItem, closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu);
auto title = Label::createWithSystemFont("单点触摸(场景优先)测试", "", 64);
title->setPosition(visibleSize.width / 2, visibleSize.height * 0.9);
this->addChild(title);
auto subtitle = Label::createWithSystemFont("请单击或拖动滑块", "", 32);
subtitle->setPosition(visibleSize.width / 2, visibleSize.height * 0.8);
this->addChild(subtitle);
auto sprite1 = Sprite::create("CyanSquare.png");
sprite1->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2) + Vec2(-80, 80));
addChild(sprite1, 10);
auto sprite2 = Sprite::create("MagentaSquare.png");
sprite2->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
addChild(sprite2, 20);
auto sprite3 = Sprite::create("YellowSquare.png");
sprite3->setPosition(Vec2(0, 0));
sprite2->addChild(sprite3, 1);
// ①创建一个单点触摸事件监听器,处理触摸事件逻辑
auto listener1 = EventListenerTouchOneByOne::create();
// 设置是否向下传递触摸
listener1->setSwallowTouches(true);
// 通过 lambda 表达式 直接实现触摸事件的响应函数
listener1->onTouchBegan = [](Touch* touch, Event* event) {
// 获得当前事件触摸的目标对象
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// 获得当前的触摸点
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
// 获得触摸对象的ContentSize
Size s = target->getContentSize();
// 获得位置矩形
Rect rect = Rect(0, 0, s.width, s.height);
// 如果位置矩形包含触摸点
if (rect.containsPoint(locationInNode))
{
log("onTouchBegan... x = %f, y = %f", locationInNode.x, locationInNode.y);
// 设置透明度
target->setOpacity(180);
// 表明用户触摸事件已经被处理,后续的onTouchMoved、onTouchEnded和onTouchCancelled会接着响应,其他事件监听器则不会再去进行监听本次触摸事件。
return true;
}
return false;
};
listener1->onTouchMoved = [](Touch* touch, Event* event) {
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// 移动触摸的精灵
target->setPosition(target->getPosition() + touch->getDelta());
};
listener1->onTouchEnded = [=](Touch* touch, Event* event) {
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// 设置透明度
target->setOpacity(255);
std::string name;
if (target == sprite2)
{
name = "MagentaSquare.png";
sprite1->setZOrder(100);
subtitle->setString("响应事件的是酒红色滑块,青色滑块的ZOrder值修改为100");
}
else if (target == sprite1)
{
name = "CyanSquare.png";
sprite1->setZOrder(0);
subtitle->setString("响应事件的是青色滑块,青色滑块的ZOrder值修改为0");
}
else {
name = "YellowSquare.png";
}
log("onTouchEnded.. 您触摸的是%s", name.c_str());
};
// 添加场景优先事件监听器。
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
// ④注意:在使用addEventListenerWithSceneGraphPriority或者addEventListenerWithFixedPriority函数时, 会对当前使用的事件监听器添加一个已注册的标记,这使得它不能够被添加多次。所以当我们再次使用listener1的时候,需要使用clone()函数创建一个新的克隆。
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
通过示例,可以总结出实现事件处理机制的基本步骤;
1、创建一个触摸事件监听器
2、实现触摸事件的响应方法
3、添加事件监听器
4、当用户触摸时,事件分发器就会将事件分发给监听器去响应
2、演示滑动屏幕选择菜单示例:
Size visibleSize = Director::getInstance()->getVisibleSize();
// ③创建菜单
_itemMenu = Menu::create();
// 循环添加菜单项
for (int i = 0; i < itemCount; ++i)
{
// 创建Label
auto label = Label::createWithSystemFont(itemNames[i].itemName, "", 48);
// 创建menuItemLabel,触碰时调用menuCallback函数
auto menuItem = MenuItemLabel::create(label, CC_CALLBACK_1(ContentLayer::menuCallback, this));
// 设置tag,用于menuCallback中判断触碰的菜单在itemNames中的下标
menuItem->setTag(i);
// 将菜单项添加到菜单
_itemMenu->addChild(menuItem);
// 控制台打印每一个菜单项的坐标位置,读者可以进行观察调试
log("x:%f,y:%f", visibleSize.width / 2, (visibleSize.height - (i + 1) * LINE_SPACE));
// 设置菜单项位置
menuItem->setPosition(Vec2(visibleSize.width / 2, (visibleSize.height - (i + 1) * LINE_SPACE)));
}
_itemMenu->setPosition(Vec2::ZERO);
// 将菜单添加为当前层的子节点
this->addChild(_itemMenu, 1);
// ④注册触碰监听器
auto listener = EventListenerTouchOneByOne::create();
// 设置是否向下传递触摸
listener->setSwallowTouches(true);
// 设置触碰开始时调用onTouchBegan函数
listener->onTouchBegan = CC_CALLBACK_2(ContentLayer::onTouchBegan, this);
// 设置触碰移动时调用onTouchMoved函数
listener->onTouchMoved = CC_CALLBACK_2(ContentLayer::onTouchMoved, this);
// 添加场景优先事件监听器。
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
屏幕向上滑动时,可以显示更多的菜单项,向下滑动屏幕,则会显示之前的菜单选项,单击任何一个菜单项,将会进入HelloWorld场景
3、演示多点触摸示例:
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
origin.y + closeItem->getContentSize().height / 2));
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
auto title = Label::createWithSystemFont("多点触摸(缩放功能)测试", "", 64);
title->setPosition(visibleSize.width / 2, visibleSize.height * 0.9);
this->addChild(title);
auto subtitle = Label::createWithSystemFont("请用手指(iOS模拟器可使用鼠标+option键)缩放屏幕", "", 32);
subtitle->setPosition(visibleSize.width / 2, visibleSize.height * 0.8);
this->addChild(subtitle);
_bgSprite = Sprite::create("HelloWorld.png");
_bgSprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
this->addChild(_bgSprite, 0);
_mscale = 1.0;
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
listener->onTouchesCancelled = CC_CALLBACK_2(HelloWorld::onTouchesCancelled, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
实现缩放功能的步骤如下:
1、在OnTouchsBegin中检测,若触摸点个数大于两个,取前两个触摸点
2、计算两个触摸点的距离,计算方式为横纵坐标差的平方和开根号
3、在OnTouchsMoved函数中做同样的检测,如果触摸点的个数大于两个,取前两个触摸点
4、再次计算这两个点的距离,通过距离比计算得到缩放比例,并保存新触摸点两点之间的距离,
5、调用精灵类的setScale函数设置新的缩放比例