Cocos2d-x 3.0 屏幕觸摸及消息分發機制

***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************



題外話:

唉。開學了!    好煩,

這就已經大三了,

兩年前的這時候,我還是懵懂的大一小學弟,

兩年後,就要奔上社會就業了。

光陰似箭,日月如梭呀~



正文:

好久沒做cocos2d-x了,這次練習一下,屏幕觸摸及消息分發機制。

這裏,我用的是cocos2d-x 3.0版本來進行練習的,環境是 VS2012+WIN7


首先,新建一個項目,並向場景加入一個精靈。

新建項目: cocos  new -p xxx(包名)  -l xxx(語言)  -d xxx(保存路徑)

選擇一個精靈,放到resource目錄下,並在VS2012中加入資源項。



然後,建立一個新的精靈,添加到當前場景Hello World

  1. auto sprite_2 = Sprite::create("player.png");  
  2. sprite_2->setPosition(Point(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));  
  3. // 圖片略大,縮小一下  
  4. sprite_2->setScale(0.4f);  
  5. this->addChild(sprite_2);  

這樣,已經加入了一個精靈,接下來要做的就是觸摸事件的處理。


我們要實現觸摸一個位置,讓精靈跟着移動到該位置,步驟爲:

——定義監聽事件的偵聽對象

——定義偵聽對象的回調方法

——在事件分發器上註冊


因爲點擊一個位置,用OneByOne這個單點觸摸即可。

首先,定義監聽事件的偵聽對象:

auto listener=EventListenerTouchOneByOne::create();


然後,定義回調方法,

我們精靈所在的scene類繼承自Layer類,Layer類中,有觸摸的虛函數,

因此,我們只需要複製過來,進行覆蓋就可以定製回調函數了。

先到Layer類中,找到onTouchBegan,onTouchMoved,onTouchEnded



然後,複製到HelloWorldScene.h中聲明,並在.cpp中定義



先進行一些簡單的定義,然後在文件中,要制定回調方法,從下圖可知:


CC_CALLBACK_2有兩個參數,_selector_ and _target_

_selector_:選擇哪個函數進行回調?   ——顯然是當前類中的相應函數啦

_target_:由哪個對象觸發?——就是當前的場景

所以,最後應該是:

  1. // 定義監聽對象的回調方法  
  2. listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,this);  
  3. listener->onTouchMoved=CC_CALLBACK_2(HelloWorld::onTouchMoved,this);  
  4. listener->onTouchEnded=CC_CALLBACK_2(HelloWorld::onTouchEnded,this);  

(PS:爲蝦米用CC_CALLBACK_2?

點擊進入它的定義,可以看到:

  1. // new callbacks based on C++11  
  2. #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)  
  3. #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)  
  4. #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)  
  5. #define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)  

CC_CALLBACK_..  這個其實都是在用std::bind來進行的操作。

白話來說,就是實現了一個對象和一個方法的綁定運行。

要注意的是,後面的_幾,並不是代表有幾個參數,而是有幾個佔位符。

更加詳細內容,可以看這個→  std::bind與CC_CALLBACK不得不說的故事  )


*****這裏也體現出了cocos2d-x 2.x和3.x的小區別:

在2.x中,需要註冊一個事件偵聽。

而在3.x中,則需要定義一個偵聽器的對象,然後定義回調方法,最後還要將偵聽和事件分發器綁定。


現在來向事件分發器添加:

_eventDispatcher

註冊一個偵聽事件,主要有下面幾種:









我們用的是最後一種,基於場景圖的優先級的。

  1. // 在事件分發器中註冊  
  2. _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);  

兩個參數,第一個表示偵聽對象,第二個表示在哪個節點進行。


說了這麼多了,我們來試一試,到目前爲止,是否正確,

也就是檢測一下,我們的點擊動作能否被獲取並分發。


在,HelloWorld::onTouchBegan中,設置在控制檯輸出所點擊的座標:

  1. bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)  
  2. {  
  3.     log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);  
  4.     return true;  
  5. }  

log就是打印功能,

%lf,輸出的座標爲 double型,

getLocation是得到OpenGL座標系(左下角爲0,0點)

getLocationInView是得到當前屏幕座標系(左上角爲0,0點)


OK,搞定,運行!

有錯誤!



將Layer裏onTouchBegan複製過來,沒有給他們加命名空間,

可以直接在HelloWorldScene.h中加一句:

using namespace cocos2d;    

或者 USING_NS_CC;

再或者,不嫌麻煩,就在相應Touch和Event前加cocos2d::

  1. bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);   
  2. void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);   
  3. void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);   

好了,現在運行一下吧~



恩,點擊鼠標,輸出相應的位置座標。


我們可以繼續做下去了!

我們的目標是,點擊屏幕,然後讓我們指定的精靈移動到該位置。

現在,我們可以獲取到點擊屏幕的位置了,如何讓指定的精靈移動到該位置呢?

要想指定精靈,那就要用到Tag,給精靈做一個標記,setTag

sprite_2->setTag(33);

我給它定義了一個編號33(當然,按照心情,隨便設置的。)


編號設置了,現在,讓用戶觸摸這個點以後,得到這個精靈,便於後面進行相應操作。

  1. bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)  
  2. {  
  3.     log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);  
  4.     // 新建一個精靈,通過編號得到這個精靈  
  5.     auto sprite=this->getChildByTag(33);  
  6.     sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));  
  7.     return true;  
  8. }  

現在,我們可以通過點擊某個點,我們的精靈的中心就會在該點了,

接下來,可以做一些動作了,不要馬上出現,讓它移動過去。


這個,可以通過之前學習的  runAction中的MoveTo來解決:

  1. bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)  
  2. {  
  3.     log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);  
  4.     // 新建一個精靈,通過編號得到這個精靈  
  5.     auto sprite=this->getChildByTag(33);  
  6. //  sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));  
  7.     sprite->runAction(MoveTo::create(0.5,Point(touch->getLocation().x,touch->getLocation().y)));  
  8.     return true;  
  9. }  

完成了,~(*^__^*) ~


現在,來個更加難一點的,如何進行拖動?

其實,也不難的,就是在onTouchMoved中,獲取這個精靈,並setPosition,當然之前onTouchBegan的相應都要刪除。

  1. void HelloWorld::onTouchMoved(Touch *touch, Event *unused_event)  
  2. {  
  3.     auto sprite=this->getChildByTag(33);  
  4.     sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));  
  5. }  

OK,運行一下,耍一耍吧!



恩,這次就到這裏了。

這次做的是,通過點擊屏幕讓 角色 移動到該位置,可以直接出現,也可以移動過去,還可以拖動。

步驟如下:

1.創建一個所需要操作的精靈於場景中

2.創建監聽事件的偵聽對象

3.定義對象的回調函數

4.在事件分發器中進行註冊

5.更改onTouchBegan,onTouchMoved內相應內容,來實現目的。


。End。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章