cocos2d-x 3.0事件機制及用戶輸入

在3.0版本alpha及其之後,原有的layer類的registerWithTouchDispatcher被棄置,採用全新的 node

EventDispatcher Mechanism express

簡單來講,主要包括三個部分: ide

1.Event Listener 封裝事件監聽的回調函數 函數

2.Event Dispatcher 事件發生的時候通知Listener this

3.Event Objects 攜帶一些相關的事件信息 spa

就是簡單的觀察者模式,根據訂閱狀況,發出事件通知給全部的監聽對象 code


一共有五種Event Listner 對象

  • EventListenerTouch - responds to touch events 事件

  • EventListenerKeyboard - responds to keyboard events 圖片

  • EventListenerAcceleration - reponds to accelerometer events

  • EventListenMouse - responds to mouse events

  • EventListenerCustom - responds to custom events

每一種對應於不一樣的事件。


使用方法:

1.綁定監聽事件處理函數到監聽對象

2.註冊監聽對象給事件分派機構Event Dispatcher

3.事件發生的時候,發送Event Object給全部的監聽者

在新版本的API當中,能夠使用C++ 11的lamda表達式的方法進行相關設置

在官方的API文檔裏面,有很是詳細的闡釋,基於的例子就是以前編譯的cpp-tests

基本代碼以下

	using namespace cocos2d::extension;
	bool bRet = false;
	do 
	{
		CC_BREAK_IF(!CCLayer::init());
		auto listener1 = EventListenerTouchOneByOne::create();
		listener1->setSwallowTouches(true);
		listener1->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegan, this);
		listener1->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this);
		listener1->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnded, this);
		_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
	//	_eventDispatcher->addEventListener(listener1);
		this->setTouchEnabled(true);#endif
		Size size = Director::sharedDirector()->getVisibleSize();
		auto sprite1 = Sprite::create("CyanSquare.png");
		sprite1->setPosition(Point(size.width / 2, size.height / 2) + Point(-80, 80));
		addChild(sprite1, 10);

		auto sprite2 = Sprite::create("MagentaSquare.png");
		sprite2->setPosition(Point(size.width/2, size.height/2));
		addChild(sprite2, 20);

		auto sprite3 = Sprite::create("YellowSquare.png");
		sprite3->setPosition(Point(0, 0));
		sprite2->addChild(sprite3, 1);   

		//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
			//更改先後順序,註釋掉的話嚴格按照Z軸的先後順序
			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);

	} while (0);    
	

	return true;

就是載入三個sprite圖片,藍色,紅色,***,默認的順序是,藍色最低層,而***結點是紅色結點的子結點


給三個sprite增長Touch Listner,設置swallow的flag爲true

效果就是,

若是按照上述運行,不註釋掉切換的那一部分code

那麼

Z order的值更大的若是sprite在範圍之內被點擊,會吞噬掉touch事件,不會再往下一層傳輸


若是不採用lamda表達式方式註冊事件,能夠採用以往版本的

auto listener1 = EventListenerTouchOneByOne::create();
		listener1->setSwallowTouches(true);
		listener1->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegan, this);
		listener1->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this);
		listener1->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnded, this);
		_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
相關文章
相關標籤/搜索