您好,登錄后才能下訂單哦!
【嘮叨】
cocos2dx游戲引擎的重點是在于移動設備的跨平臺開發,而移動設備上的游戲大部分都是通過屏幕觸碰來進行的。比如主菜單的按鈕觸碰,打飛機中飛機的觸碰移動,都需要用到觸碰操作。想一想之前講的菜單按鈕CCMenu,菜單項的點擊響應事件,其實就是觸碰。
cocos2dx引擎中實現觸碰的類CCTouchDelegate。而CCLayer類默認繼承了CCTouchDelegate接口,所以CCLayer的子類無須再重新使用這些接口,這樣就很方便地為我們提供了觸摸操作相關的操作。
觸碰事件主要分為兩類:單點觸碰 和 多點觸碰。
本節組織結構如下:
一、單點觸碰TargetedDelegate、以及參數CCTouch類。
二、多點觸碰StandardDelegate、以及參數CCSet類。
三、兩類觸碰的區別。
【Demo下載】
https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E8%A7%A6%E7%A2%B0%E4%BA%8B%E4%BB%B6Touch
【3.x】
請移步:http://shahdza.blog.51cto.com/2410787/1560222
【單點觸碰】
單點觸碰TargetedDelegate,顧名思義,就是只接受一個點的觸摸響應事件。
在使用觸碰之前,必須要先注冊觸碰委托。單點觸碰的注冊委托函數為addTargetedDelegate。
1、開啟單點觸碰事件addTargetedDelegate
寫在onEnter()中。
// /** * 開啟單點觸碰TargetedDelegate * 注冊觸碰:addTargetedDelegate("觸碰事件委托的對象","優先級","是否攔截觸屏事件"); * 優先級的值越小,就越高越早被響應。 * 當第3個參數為true時,表示對本次觸屏事件進行攔截,也就是說當觸屏事件響應了本次觸屏委托后,將不會再繼續響應其他觸碰委托。 */ void HelloWorld::onEnter() { //注冊觸碰響應事件 CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false); CCLayer::onEnter();//一定不要忘了調用父類的onEnter } //
2、關閉單點觸碰事件removeDelegate
寫在onExit()中。
// /** * 關閉單點觸碰TargetedDelegate * 注銷觸碰:removeDelegate("注銷觸碰事件委托的對象"); */ void HelloWorld::onExit() { //注銷觸屏響應事件 CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit();//一定不要忘了調用父類的onExit } //
3、單點觸碰響應函數
ccTouchBegan、ccTouchMoved、ccTouchEnded、ccTouchCancelled。
其中ccTouchBegan的返回值為bool類型:
當返回true時 ,表示繼續響應ccTouchMoved、ccTouchEnded事件;
當返回false時,則不再繼續響應這兩個事件。
// virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event); //手指碰到屏幕時調用 virtual void ccTouchMoved(CCTouch* touch,CCEvent* event); //手指在屏幕上滑動時調用 virtual void ccTouchEnded(CCTouch* touch,CCEvent* event); //手指離開屏幕是調用 virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); //取消觸碰 //
4、關于CCTouch類
CCTouch類是用來存儲用戶觸摸屏幕的過程中,其觸摸點的相關信息。也就是保存了觸碰的整個過程中,手指所在的位置坐標。
需要在.h中添加引用命名空間:using namespace cocos2d; 才可以使用。
常用操作如下:
// class CCTouch : public CCObject { CCPoint getLocation(); //返回當前觸點的坐標 CCPoint getPreviousLocation(); //返回前一個觸點的坐標 CCPoint getStartLocation(); //返回開始觸碰時的坐標 CCPoint getDelta(); //返回最近兩個觸點的偏移量坐標 }; //
5、代碼實戰
接下來將舉個例子:使用單點觸碰實現精靈的移動。
5.1、聲明單點觸碰響應函數
先在HelloWorld.h中,聲明觸碰響應函數,以及類的生命周期。
// //觸屏事件 virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event); virtual void ccTouchMoved(CCTouch* touch,CCEvent* event); virtual void ccTouchEnded(CCTouch* touch,CCEvent* event); //生命周期 virtual void onEnter(); virtual void onExit(); //
5.2、開啟、關閉單點觸碰事件
在HelloWorld.cpp中編寫開啟和關閉觸碰事件。
// //開啟觸屏監聽 void HelloWorld::onEnter() { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false); CCLayer::onEnter(); //一定不要忘了 } //關閉觸屏監聽 void HelloWorld::onExit() { CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit(); //一定不要忘了 } //
5.3、創建測試精靈
在HelloWorld::init()中創建一個CCSprite精靈,用于測試觸碰。
// //添加一個CCSprite精靈 CCSprite* sp = CCSprite::create("Icon.png"); sp->setPosition( midPos ); this->addChild(sp, 0, 1); //tag標記為1 //
5.4、實現觸碰響應函數
ccTouchBegan:將精靈的位置設置到觸碰開始的位置。關鍵函數:touch->getLocation()
ccTouchMoved:對精靈的位置進行移動。 關鍵函數:touch->getDelta()
ccTouchEnded:將精靈的位置還原到觸碰開始的位置。關鍵函數:touch->getStartLocation()
// //觸屏開始ccTouchBegan bool HelloWorld::ccTouchBegan(CCTouch* touch,CCEvent * event) { CCLOG("ccTouchBegan"); //獲取CCSprite精靈 CCSprite* sp = (CCSprite*)this->getChildByTag(1); //設置精靈的坐標為: 當前觸點位置 CCPoint pTouch = touch->getLocation(); sp->setPosition( pTouch ); return true; } //觸屏移動ccTouchMoved void HelloWorld::ccTouchMoved(CCTouch* touch,CCEvent* event) { CCLOG("ccTouchMoved"); //獲取可視區域尺寸大小 CCSize mysize = CCDirector::sharedDirector()->getVisibleSize(); //獲取CCSprite精靈 CCSprite* sp = (CCSprite*)this->getChildByTag(1); //實現精靈的觸屏移動 CCPoint pos = touch->getDelta(); //獲得觸屏滑動的偏移量 CCPoint currentPos = sp->getPosition(); //獲得精靈的當前坐標 currentPos = ccpAdd(currentPos, pos); //精靈+偏移量 后的坐標 sp->setPosition(currentPos); //設置觸屏移動后的坐標 } //觸屏結束ccTouchEnded void HelloWorld::ccTouchEnded(CCTouch* touch,CCEvent* event) { CCLOG("ccTouchEnded"); //獲取CCSprite精靈 CCSprite* sp = (CCSprite*)this->getChildByTag(1); //設置精靈的坐標為: 觸屏開始時的觸點位置 CCPoint touchStartPos = touch->getStartLocation(); sp->setPosition( touchStartPos ); } //
6、運行結果
【多點觸碰】
多點觸碰StandardDelegate,可以支持多個點的同時觸摸響應事件。
1、開啟多點觸碰
多點觸碰的委托注冊放在onEnter的生命函數中會造成程序異常退出。
所以注冊多點觸碰都需要重寫如下函數:registerWithTouchDispatcher。
開啟多點觸碰,除了注冊觸碰委托外,還需要調用setTouchEnabled(true)來啟用觸碰。
// /** * 注冊多點觸碰,重寫registerWithTouchDispatcher。 * addStandardDelegate("觸碰事件委托的對象","優先級") */ void HelloWorld::registerWithTouchDispatcher() { CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0); } //在HelloWorld::init()中啟用多點觸碰 this->setTouchEnabled(true); //
2、關閉多點觸碰
與單點觸碰的關閉類似,寫在onExit()。
// void HelloWorld::onExit() { //關閉觸碰 CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit(); //一定不要忘了 } //
3、多點觸碰響應函數
ccTouchesBegan、ccTouchesMoved、ccTouchesEnded、ccTouchesCancelled。
其中ccTouchesBegan和單點觸碰不同,返回值為void。
// virtual void ccTouchesBegan(CCSet* touches, CCEvent* event); //觸碰開始 virtual void ccTouchesMoved(CCSet* touches, CCEvent* event); //觸碰移動 virtual void ccTouchesEnded(CCSet* touches, CCEvent* event); //觸碰結束 virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent); //取消多點觸屏 //
4、關于CCSet類
CCSet類是一個集合類,和C++中的Set是類似的。
在這里CCSet的數據元素類型為CCTouch,其主要存儲的是多點觸碰的觸摸點CCTouch集合。
使用迭代器CCSetIterator進行CCSet集合中多個觸點CCTouch的遍歷。
// for (CCSetIterator iter = touches->begin() ;iter != touches->end(); iter++) { //獲取觸點后,就和單點一樣的處理了 CCTouch* touch = (CCTouch*)(*iter); //...... } //
5、代碼實戰
在電腦中無法看到多點觸碰的效果,因為……電腦操作只有一個鼠標。
下面就講解一個多點觸碰的例子吧,至于效果,自己將代碼移植到手機上看吧。。。
5.1、聲明多點觸碰響應函數
先在HelloWorld.h中,聲明多點觸碰響應函數,以及類的生命周期。
// //觸屏事件 virtual void registerWithTouchDispatcher(void); virtual void ccTouchesBegan(CCSet* touches,CCEvent* event); virtual void ccTouchesMoved(CCSet* touches,CCEvent* event); virtual void ccTouchesEnded(CCSet* touches,CCEvent* event); //生命周期 virtual void onExit(); //
5.2、開啟、關閉多點觸碰事件
在HelloWorld.cpp中編寫開啟和關閉多點觸碰事件。
// //在init中開啟多點觸碰 bool HelloWorld::init() { //..... //開啟多點觸屏。注意這句話必須要寫,否則無法多點觸屏 this->setTouchEnabled(true); //..... } //注冊多點觸屏 void HelloWorld::registerWithTouchDispatcher() { CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0); } //注銷多點觸屏 void HelloWorld::onExit() { CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit(); //不要忘了寫! } //
5.3、創建測試精靈
在HelloWorld::init()中創建兩個CCSprite精靈,用于測試觸碰。
// //添加兩個CCSprite精靈,用于多點觸屏 CCSprite* sp1 = CCSprite::create("Icon.png"); sp1->setPosition( ccp( 100, 160 ) ); this->addChild(sp1, 0, 1); CCSprite* sp2 = CCSprite::create("Icon_gray.png"); sp2->setPosition( ccp( 200, 160) ); this->addChild(sp2, 0, 2); //
5.4、實現多點觸碰響應函數
ccTouchesMoved中:將精靈的位置設置到觸點位置,sp1精靈設置到第0個觸點位置;sp2精靈設置到第1個觸點位置。
關鍵函數:
(1)CCTouch* touch = (CCTouch*)(*iter)
(2)touch->getID()
// //觸屏開始,返回值是void void HelloWorld::ccTouchesBegan(CCSet* touches,CCEvent* event) { CCLOG("ccTouchesBegan"); } //觸屏移動 void HelloWorld::ccTouchesMoved(CCSet* touches,CCEvent* event) { CCLOG("ccTouchesMoved"); //創建CCSet的迭代器CCSetIterator CCSetIterator iter = touches->begin(); //遍歷多點觸點集合touches for( ;iter != touches->end(); iter++) { //獲取觸點后,就和單點一樣的處理了 CCTouch* touch = (CCTouch*)(*iter); if( touch->getID() == 0) //控制精靈sp1 { CCSprite* sp1 = (CCSprite*)this->getChildByTag(1); sp1->setPosition( touch->getLocation() ); } else if( touch->getID() == 1) //控制精靈sp2 { CCSprite* sp2 = (CCSprite*)this->getChildByTag(2); sp2->setPosition( touch->getLocation() ); } } } //觸屏結束 void HelloWorld::ccTouchesEnded(CCSet* touches,CCEvent* event) { CCLOG("ccTouchesEnded"); } //
6、運行結果
7、分析與總結
灰的那張精靈sp2為啥不動啊啊啊!因為電腦中只有一個鼠標……所以只能觸碰一個點。
想要看到多點觸碰的效果,就把程序移植到手機上吧。
【兩類觸碰的區別】
(1)單點使用的監聽類是CCtargetedTouchDelegate,而多點使用CCtangardTouchDelegate。
(2)多點觸控還需要多一個步驟,就是單獨寫個函數來注冊多點觸控:registerWithTouchDispatcher。
(3)多點觸控要有開啟才能用。 this->setTouchEnabled(true)。
(4)多點觸控中的ccTouchesBegan不是布爾型。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。