1. 程式人生 > >Cocos2dx-3.x觸控事件之實現人機互動(三)

Cocos2dx-3.x觸控事件之實現人機互動(三)

今天講自定義事件和加速計事件

先在標頭檔案完成以下宣告

	virtual void onExit(); // 為了移除ListenerCustom中的監聽器_listener
	EventListenerCustom* _listener;  // 為了能夠最後在onExit中呼叫移除函式,所以在標頭檔案宣告
接著就是在cpp檔案中的實現,
	/********************************自定義事件**************************************/
	auto statusLabel = Label::createWithSystemFont("No custom event 1 received!", "", 20);
	statusLabel->setPosition(Point(240, 230));
	addChild(statusLabel);

        /*
        引數一要求給自定義事件命名,為了能夠在後面通過事件名字呼叫自定義事件
	引數二是一個事件的回撥函式,這裡用Lambda函式實現,實現具體作用
	*/
	_listener = EventListenerCustom::create("game_custom_event1", [=](EventCustom* event){ 
		std::string str("Custom event 1 received, ");
		// 因自定義事件中的"getUserData()"函式返回的是一個void*,為了能轉換為char*,這裡用了static_cast<char*>強制型別轉換
		char* buf = static_cast<char*>(event->getUserData()); 
		str += buf;
		str += " times";
		statusLabel->setString(str.c_str());
	});
	/*
	"SceneGraphPriority"和"FixedPriority"兩種分發事件區別是
	前者跟Node繫結的,在Node的解構函式中會被移除,
	後者新增完之後需要手動remove.
	*/
	// 因為這裡不能確定是誰呼叫自定義事件,並且自定義事件可以利用名字呼叫,所以就用第二個方法來分發事件和設定優先順序
	_eventDispatcher->addEventListenerWithFixedPriority(_listener, 1); 

	// 這裡通過MenuItemFont的第二個引數設定了一個Lambda函式呼叫了自定義事件
	auto sendItem = MenuItemFont::create("Send Custom Event 1", [=](Ref* sender){ 
		static int count = 0;
		++count;
		char* buf = new char[10];
		sprintf(buf, "%d", count);
		EventCustom event("game_custom_event1"); // 先通過自定義事件名字初始化事件
		event.setUserData(buf);                  // 利用自定義事件中的"setUserData()"設定使用者資料
		_eventDispatcher->dispatchEvent(&event); // 最後事件分發 還移除在事件分發列表中所有標記為刪除的事件偵聽器
		CC_SAFE_DELETE_ARRAY(buf);
	});
	sendItem->setPosition(Point(240, 160));

	auto menu = Menu::create(sendItem, nullptr);
	menu->setPosition(Vec2(0, 0));
	menu->setAnchorPoint(Vec2(0, 0));
	addChild(menu, -1);
	/*******************************************************************************/
最後在onExit函式中remove
void onExit(){
         Layer::onExit();
	_eventDispatcher->removeEventListener(_listener);
}
接著是加速計事件,其實就是重力感應,這裡沒有用手機測試,大家參考一下,有條件的可以測試一下,到時告訴我是否正確
	/********************************加速計事件*******************************************/
	Device::setAccelerometerEnabled(true);   // 開啟硬體裝置

	auto sprite = Sprite::create("Images/ball.png");
	sprite->setPosition(Point(240, 160));
	addChild(sprite);
	// 引數是一個函式,這裡用Lambda函式實現,裡面引數第一個是加速度,第二個點選事件
	auto listener = EventListenerAcceleration::create([=](Acceleration* acc, Event* event){ 
		auto ballSize = sprite->getContentSize(); // 精靈面積
		auto ptNow = sprite->getPosition();      // 精靈位置
		ptNow.x += acc->x * 9.81f; // x軸加速度,設定x軸座標
		ptNow.y += acc->y * 9.81f; // y軸加速度,設定y軸座標
		sprite->setPosition(ptNow);
	});

	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, sprite);
	/**************************************************************************************/
最後退出的時候不要忘了關掉硬體裝置,同自定義事件一樣下面的函式要在標頭檔案宣告
void onExit(){
        Layer::onExit();
	Device::setAccelerometerEnabled(false);
}

到此,所有的觸控事件就講完了,希望大家能有所收穫。