cocos2dx3.0的触摸响应机制

2015年01月31日 13:31 0 点赞 0 评论 更新于 2025-11-21 15:51

Cocos2d-x 3.0提供了三种触摸响应机制,下面将逐一详细介绍。

一、函数回调(主要用于MenuItem)

函数回调是一种常见的触摸响应方式,主要应用于 MenuItem。在Cocos2d-x 3.0中,有一些明显的改变,例如使用 CC_CALLBACK_x 代替了按钮的 menu_selector()updateschedule_selector 回调接口。这里的 x 代表回调函数的参数个数,0 表示无参数,1 表示有一个参数,2 表示有两个参数。以下是具体的代码示例:

// 声明回调函数
void menuCloseCallback(Object* pSender);

// 创建菜单项
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

// 实现回调函数
void HelloWorld::menuCloseCallback(Object* pSender)
{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

二、TouchEvent响应

这是Cocos2d-x 3.0新加入的响应方式,主要应用于 UIWidget,可以看作是函数回调的扩展,为更多的响应处理提供了可能性。使用方法如下:

// 声明触摸事件处理函数
void touchButton(Object* object, TouchEventType type);

// 将处理函数挂接到控件上
uiButton->addTouchEventListener(this, toucheventselector(HelloWorld::touchButton));

// 实现触摸事件处理函数
void HelloWorld::touchButton(Object* object, TouchEventType type)
{
LabelTTF* label;
switch (type)
{
case TouchEventType::TOUCH_EVENT_BEGAN:
label = static_cast<LabelTTF*>(getChildByTag(11));
label->setString("按下按钮");
break;
case TouchEventType::TOUCH_EVENT_MOVED:
label = static_cast<LabelTTF*>(getChildByTag(11));
label->setString("按下按钮移动");
break;
case TouchEventType::TOUCH_EVENT_ENDED:
label = static_cast<LabelTTF*>(getChildByTag(11));
label->setString("放开按钮");
break;
case TouchEventType::TOUCH_EVENT_CANCELED:
label = static_cast<LabelTTF*>(getChildByTag(11));
label->setString("取消点击");
break;
default:
break;
}
}

由于所有的 UIWidget 都要添加到 UILayer 上,而 UILayer 通常位于最上层,所以基本上可以认为这种使用方式会优先于其他方式处理点击消息。不过,UILayer 也会有层级的改变,例如它和 MenuItem 之间的关系,因此这里说“基本上”。

三、触摸监听绑定

这种方法非常方便,不仅可以绑定在精灵上,还可以绑定在层上,并且触摸函数可以使用lambda表达式来编写。以下是具体的实现步骤和代码示例:

// 创建一个触摸监听
auto listener1 = EventListenerTouchOneByOne::create();

// 设置是否向下传递触摸事件
listener1->setSwallowTouches(true);

// 定义一个矩形区域
Rect rect = Rect(qipanPoint.x, qipanPoint.y, qipanSize.width, qipanSize.height);

// 3.0 后可以直接在touchBegan后添加它的实现代码,而不用特意去写一个touchBegan的函数
listener1->onTouchBegan = [rect, this](Touch* touch, Event* event) {
// 获取当前触摸的目标
auto target = static_cast<Node*>(event->getCurrentTarget());

// 将触摸点转换到目标节点的坐标系中
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();

// 判断触摸点是否在目标的范围内
if (rect.containsPoint(locationInNode))
{
// 创建锁定精灵
auto lockSprite = Sprite::create("lock.png");
lockSprite->setPosition(GetQiziPoint(locationInNode, rect));
lockSprite->setTag(99);
this->addChild(lockSprite);
return true;
}
else
{
return false;
}
};

// 拖动精灵移动
listener1->onTouchMoved = [rect, this](Touch* touch, Event* event) {
auto target = static_cast<Node*>(event->getCurrentTarget());
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
if (rect.containsPoint(locationInNode))
{
// 锁定精灵移动
Sprite *lockSprite = (Sprite*)this->getChildByTag(99);
lockSprite->setPosition(GetQiziPoint(locationInNode, rect));
}
};

// 触摸结束处理
listener1->onTouchEnded = [=](Touch* touch, Event* event) {
// 移除锁定精灵
this->removeChildByTag(99);
};

// 将触摸监听添加到eventDispacher中去
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, layer);

通过以上三种触摸响应机制,开发者可以根据不同的需求选择合适的方式来处理触摸事件,从而实现丰富的交互效果。

作者信息

feifeila

feifeila

共发布了 3994 篇文章