Layer类的一个重要作用就是接受输入事件,它封装了触摸输入的处理接口。一般情况下,我们可以通过setTouchEnabled方法来开启或关闭接收触摸输入。事实上并不是只有Layer才支持接收触摸事件,任何一个游戏元素都可以接收事件,只不过Layer提供了现成的支持。
我们只需通过创建一个事件监听器用来实现各种触发后的逻辑,然后添加到事件分发器_eventDispatcher中,所有事件监听器由这个分发器统一管理,即可完成事件响应。
为一个精灵添加触摸事件的四个步骤
1.创建一个精灵
2.创建一个事件监听器(单点触摸或多点触摸)
3.实现各种触发后的逻辑(onTouchBegan,onTouchMoved,onTouchEnded等)
4.将事件监听器添加到事件分发器中
// 1.首先添加一个精灵元素
bool GameScene::init()
{
sprite = Sprite::create();
sprite->setPosition(100, 100);
this->addChild(sprite);
}
void GameScene::addTouchEvent()
{
// 2.创建一个单点触摸监听器
auto touchListener = EventListenerTouchOneByOne::create();
// 3.实现触摸后的逻辑处理,使用lambda表达式实现触摸事件处理的回调函数
// 触摸开始
touchListener->onTouchBegan = [](Touch *touch, Event *event)
{
// 获取点击的openGL坐标
auto touchPos = touch->getLocation();
// 获取触摸事件的相关目标,即玩家飞机
auto target = static_cast<Sprite *>(event->getCurrentTarget());
// 获取飞机所在区域
auto playerPos = target->getPosition();
auto playerSize = target->getContentSize();
auto rect = Rect(playerPos.x - playerSize.width/2, playerPos.y - playerSize.height/2,
playerSize.width, playerSize.height);
if(rect.containsPoint(touchPos))
{
return true;
}
// 返回false会导致后面的onTouchMoved和onTouchEnded不会执行
return false;
};
// 滑动
touchListener->onTouchMoved = [](Touch *touch, Event *event)
{
auto touchPos = touch->getLocation();
auto target = static_cast<Sprite *>(event->getCurrentTarget());
target->setPosition(touchPos);
};
// 触摸结束
touchListener->onTouchEnded = [](Touch *touch, Event *event)
{
log("touch end");
};
/*
4.最后将事件监听器添加到事件分发器_eventDispatcher中 _eventDispatcher是Node的属性,通过它管理当前节点(场景、层、精灵等)的所有事件的分发。但它本身是一个单例模式值的引用,在Node的构造函数中,通过Director::getInstance()->getEventDispatcher(); 获取,有了这个属性,就能方便的处理事件。
*/
// _eventDispatcher = Director::getInstance()->getEventDispatcher();
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, sprite);
// 为第二个精灵添加触摸监听_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener->clone(), sprite2);
}
当再次使用touchListener 的时候,需要使用clone()方法创建一个新的克隆,因为在使用addEventListenerWithSceneGraphPriority或者addEventListenerWithFixedPriority方法时,会对当前使用的事件监听器添加一个已注册的标记,这使得它不能够被添加多次。另外,有一点非常重要,FixedPriority listener添加完之后需要手动remove,而SceneGraphPriority listener是跟Node绑定的,在Node的析构函数中会被移除。具体的示例用法可以参考引擎自带的tests。
原文:http://blog.csdn.net/ixiaochouyu/article/details/43803241