***************************************轉載請註明出處: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
- auto sprite_2 = Sprite::create("player.png");
- sprite_2->setPosition(Point(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));
- // 圖片略大,縮小一下
- sprite_2->setScale(0.4f);
- 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_:由哪個對象觸發?——就是當前的場景
所以,最後應該是:
- // 定義監聽對象的回調方法
- listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
- listener->onTouchMoved=CC_CALLBACK_2(HelloWorld::onTouchMoved,this);
- listener->onTouchEnded=CC_CALLBACK_2(HelloWorld::onTouchEnded,this);
(PS:爲蝦米用CC_CALLBACK_2?
點擊進入它的定義,可以看到:
- // new callbacks based on C++11
- #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
- #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
- #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
- #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
註冊一個偵聽事件,主要有下面幾種:
我們用的是最後一種,基於場景圖的優先級的。
- // 在事件分發器中註冊
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
兩個參數,第一個表示偵聽對象,第二個表示在哪個節點進行。
說了這麼多了,我們來試一試,到目前爲止,是否正確,
也就是檢測一下,我們的點擊動作能否被獲取並分發。
在,HelloWorld::onTouchBegan中,設置在控制檯輸出所點擊的座標:
- bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
- {
- log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
- return true;
- }
log就是打印功能,
%lf,輸出的座標爲 double型,
getLocation是得到OpenGL座標系(左下角爲0,0點)
getLocationInView是得到當前屏幕座標系(左上角爲0,0點)
OK,搞定,運行!
有錯誤!
將Layer裏onTouchBegan複製過來,沒有給他們加命名空間,
可以直接在HelloWorldScene.h中加一句:
using namespace cocos2d;
或者 USING_NS_CC;
再或者,不嫌麻煩,就在相應Touch和Event前加cocos2d::
- bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);
好了,現在運行一下吧~
恩,點擊鼠標,輸出相應的位置座標。
我們可以繼續做下去了!
我們的目標是,點擊屏幕,然後讓我們指定的精靈移動到該位置。
現在,我們可以獲取到點擊屏幕的位置了,如何讓指定的精靈移動到該位置呢?
要想指定精靈,那就要用到Tag,給精靈做一個標記,setTag
sprite_2->setTag(33);
我給它定義了一個編號33(當然,按照心情,隨便設置的。)
編號設置了,現在,讓用戶觸摸這個點以後,得到這個精靈,便於後面進行相應操作。
- bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
- {
- log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
- // 新建一個精靈,通過編號得到這個精靈
- auto sprite=this->getChildByTag(33);
- sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
- return true;
- }
現在,我們可以通過點擊某個點,我們的精靈的中心就會在該點了,
接下來,可以做一些動作了,不要馬上出現,讓它移動過去。
這個,可以通過之前學習的 runAction中的MoveTo來解決:
- bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
- {
- log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
- // 新建一個精靈,通過編號得到這個精靈
- auto sprite=this->getChildByTag(33);
- // sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
- sprite->runAction(MoveTo::create(0.5,Point(touch->getLocation().x,touch->getLocation().y)));
- return true;
- }
完成了,~(*^__^*) ~
現在,來個更加難一點的,如何進行拖動?
其實,也不難的,就是在onTouchMoved中,獲取這個精靈,並setPosition,當然之前onTouchBegan的相應都要刪除。
- void HelloWorld::onTouchMoved(Touch *touch, Event *unused_event)
- {
- auto sprite=this->getChildByTag(33);
- sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
- }
OK,運行一下,耍一耍吧!
恩,這次就到這裏了。
這次做的是,通過點擊屏幕讓 角色 移動到該位置,可以直接出現,也可以移動過去,還可以拖動。
步驟如下:
1.創建一個所需要操作的精靈於場景中
2.創建監聽事件的偵聽對象
3.定義對象的回調函數
4.在事件分發器中進行註冊
5.更改onTouchBegan,onTouchMoved內相應內容,來實現目的。
。。End。。