cocos2d-x3.0事件處理機制
事件回調
3.0 後的事件回調函數接口都不一樣了,例如按鈕的menu_selector(),update的 schedule_selector等,都已成明日黃花。而新的回調接口,則由四個CC_CALLBACK取代。
其實CC_CALLBACK的差別就在於後面的數字啦,0就代表回調的是沒有參數的函數,1就是有一個參數,2 就是有兩個參數。
3.0裏Callfunc的新的用法
auto action1 = CallFunc::create(
[&](){
auto s =Director::sharedDirector()->getWinSize();
auto label =LabelTTF::create("called:lambda callback", "Marker Felt", 16);
label->setPosition(ccp(s.width/4*1,s.height/2-40));
this->addChild(label);
} );
以前動作回調都是要新寫一個回調函數,這樣子雖然問題不大,但如果用到回調的地方多了,而且回調的代碼也就幾行而已,那之前的做法就有點受不了,現在好了,可以直接把動作執行完要回調的函數代碼直接寫到創建裏來,是不是方便多了。
觸摸機制
一、單點觸摸:
方法1
聲明:
bool onTouchBegan(Touch* touch, Event *event);
void onTouchMoved(Touch* touch, Event *event);
void onTouchEnded(Touch* touch, Event *event);
實現:
寫在init方法中
auto listener1 = EventListenerTouchOneByOne::create();
listener1->setSwallowTouches(false);
listener->onTouchBegan = CC_CALLBACK_2(MainLayer::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(MainLayer::onTouchMoved,this);
listener->onTouchEnded = CC_CALLBACK_2(MainLayer::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
bool MainLayer::onTouchBegan(Touch* touch, Event *event)
{
}
void MainLayer::onTouchMoved(Touch* touch, Event *event)
{
}
void MainLayer::onTouchEnded(Touch* touch, Event *event)
{
}
方法2
實現:
寫在init方法中
auto listener1 = EventListenerTouchOneByOne::create();
listener1->setSwallowTouches(false);
listener1->onTouchBegan = [ ](Touch* touch, Event* event){
};
listener1->onTouchMoved = [ ](Touch* touch, Event* event){
};
listener1->onTouchEnded = [=](Touch* touch, Event* event){
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
二、多點觸摸:
聲明:
void onTouchesBegan(const std::vector<Touch*>& touches, Event *event);
void onTouchesMoved(const std::vector<Touch*>& touches, Event *event);
void onTouchesEnded(const std::vector<Touch*>& touches, Event *event);
實現:
寫在init方法裏
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(OptionLayer::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(OptionLayer::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(OptionLayer::onTouchesEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
void OptionLayer::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)
{
}
void OptionLayer::onTouchesMoved(const std::vector<Touch*>& touches, Event *event)
{
}
void OptionLayer::onTouchesEnded(const std::vector<Touch*>& touches, Event *event)
{
}
觸摸機制還有個不同的地方,只要是放在最上面的那個精靈,那它的觸摸優先級就最高。我們用的按鈕Menu 就是用這種方式設置觸摸優先級的。
將listener1添加到事件調度中,這裏用的是:
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1 sprite);
我們進入addEventListenerWithSceneGraphPriority的定義中看一下,有下面這一行代碼:
listener->setFixedPriority(0);
它將精靈的觸摸優先級設置成0,從這裏我們可以引申出兩個問題,一個就是當我們要給精靈設置觸摸優先級時,
listener->setFixedPriority(0);
,因爲0已經被“官府”徵用了,另一個問題就是:如果自己想設置精靈的觸摸優先級,那應該怎麼做呢?下面是提供的另外一種添加listener的方法:
_eventDispatcher->addEventListenerWithFixedPriority(listener1 ,fixedPriority);
在第二個參數裏設置觸摸優先級,這樣就可以了。
如果你有多個精靈sprite,且這些精靈都想實現拖動的功能,那麼這些精靈都可以使用listener1這一個觸摸監聽,例如我們有三個精靈,sprite,sprite2,sprite3,他們調用listener1的方式:
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
其中sprite2和sprite3都是克隆了listener1的,進入clone()的定義,我們看到以下代碼:
EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
{
auto ret = new EventListenerTouchOneByOne();
if (ret && ret->init())
{
ret->autorelease();
ret->onTouchBegan = onTouchBegan;
ret->onTouchMoved = onTouchMoved;
ret->onTouchEnded = onTouchEnded;
ret->onTouchCancelled = onTouchCancelled;
ret->_claimedTouches = _claimedTouches;
ret->_needSwallow = _needSwallow;
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}
以上代碼主要的目的也就是實現克隆touchbegan,touchmoved,touchended。
刪除觸摸監聽
_eventDispatcher->removeEventListeners(EventListener::Type::TOUCH_ONE_BY_ONE);
這樣就OK了。