Cocos2D-X2.2.3學習筆記8(處理精靈單擊、雙擊和三連擊事件)
我們依據上一次介紹的觸屏事件和事件隊列等知識來實現觸屏的單擊,雙擊,三連擊事件。
下圖為我們實現的效果圖:
單擊精靈跳躍一個高度,
雙擊精靈跳躍的高度比單擊的高
三連擊精靈跳躍的跟高
好了。開始動手吧。
新建項目。刪除多余的代碼
接著在Classes文件夾下建立兩個文件,這裏我就命名為Human了
(在Classes上右鍵加入新建項,選擇頭文件,名稱Human.h,位置瀏覽到Classes文件夾下)
由於要實現精靈能接受觸屏事件,所以我們不能用CCSprite ,須要自己寫個類繼承CCSprite和CCTouchDelegate
還記得CCTouchDelegate類嗎??
OK 我們先實現頭文件
#ifndef _Human_H_ #include "cocos2d.h" USING_NS_CC; class Human:public CCSprite,public CCTouchDelegate { public: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void onEnter(); virtual void onExit(); //創建靜態方法,用於創建Human精靈 static Human* create(const char *pszFileName); private: }; #endif // !_Human_H_
重寫的這5個方法應該不用解釋了,上一節介紹過的
(教大家一個小技巧。比方我不記得觸屏事件的名稱或參數怎麽寫來著。沒事,不用死機硬背的。鼠標放在CCTouchDelegate上F12,就能夠看到它們都在,多點。單點等等,你復制一份就哦了。
)
接著我們來實現CPP文件
#include "Human.h" bool Human::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { CCLOG("ccTouchBegan"); return true; } void Human::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) { CCLOG("ccTouchMoved"); } void Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { CCLOG("ccTouchEnded"); } void Human::onEnter() { //繼承,重載方法的步驟我們實現了,接下來就是註冊 //第一步:將我們須要處理觸屏事件的類加入到事件隊列中dispatcher CCSprite::onEnter(); CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher(); dispatcher->addTargetedDelegate(this,0,true); } void Human::onExit() { //第二步:卸載 CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher(); dispatcher->removeDelegate(this); } Human* Human::create(const char *pszFileName) { Human *pobSprite = new Human(); if (pobSprite && pobSprite->initWithFile(pszFileName)) { pobSprite->autorelease(); return pobSprite; } CC_SAFE_DELETE(pobSprite); return NULL; }
這裏凝視非常具體了,或許大家寫不出create方法裏面的代碼吧?寫不出沒關系,看得懂即可了。以後熟練了就能夠寫出來了。我們找到CCSprite中的create方法的實現代碼。照著寫即可了,主要將
CCSprite *pobSprite = new CCSprite();改為
Human *pobSprite = new Human();
成功了?那接著
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } Human *humanSprite=Human::create("Icon.png"); humanSprite->setPosition(ccp(240,30)); this->addChild(humanSprite); return true; }
這裏不是CCSprite了,是我們自己定義的精靈。它能夠接受觸屏事件的響應
OK 執行。點擊屏幕。看輸出窗體
有個小問題。不一定點擊精靈才觸發事件,點擊屏幕的不論什麽地方都會觸發事件。這不是我們想要的結果。
我們須要的是僅僅有觸摸點在精靈圖片的範圍內才觸發事件
OK,我們在新增一個方法 containsTouchLocation
//推斷觸摸點是否在精靈範圍內 bool containsTouchLocation(CCTouch *pTouch);實現
#ifndef _Human_H_ #include "cocos2d.h" USING_NS_CC; class Human:public CCSprite,public CCTouchDelegate { public: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void onEnter(); virtual void onExit(); //創建靜態方法,用於創建Human精靈 static Human* create(const char *pszFileName); //推斷觸摸點是否在精靈範圍內 bool containsTouchLocation(CCTouch *pTouch); private: }; #endif // !_Human_H_
CPP
#include "Human.h" bool Human::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { return true; } void Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { if (containsTouchLocation(pTouch)) { CCLOG("ccTouchEnded"); } } bool Human::containsTouchLocation(CCTouch *pTouch) { //首先須要獲得精靈的大小,將它轉換為一個CCRect(矩形) CCSize spriteSize= this->getContentSize(); CCRect rect=CCRectMake(-spriteSize.width/2,-spriteSize.height/2,spriteSize.width,spriteSize.height); //通過CCRect中的containsPoint。來推斷這個矩形是否包括這個點 //這個點為我們的觸摸點 if(!rect.containsPoint(this->convertTouchToNodeSpaceAR(pTouch))) { return false; } return true; } void Human::onEnter() { //繼承,重載方法的步驟我們實現了,接下來就是註冊 //第一步:將我們須要處理觸屏事件的類加入到事件隊列中dispatcher CCSprite::onEnter(); CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher(); dispatcher->addTargetedDelegate(this,0,true); } void Human::onExit() { //第二步:卸載 CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher(); dispatcher->removeDelegate(this); } Human* Human::create(const char *pszFileName) { Human *pobSprite = new Human(); if (pobSprite && pobSprite->initWithFile(pszFileName)) { pobSprite->autorelease(); return pobSprite; } CC_SAFE_DELETE(pobSprite); return NULL; }
這裏都有凝視了。
第一。先獲得精靈的大小(ContentSize)將其轉換為CCRect(矩形)
第二,利用CCRect中的containsPoint方法來推斷這個矩形是否包括這個點。包括返回true否則反之
(這裏須要把觸摸點的位置轉換為相對當前精靈節點的相對位置
我們介紹坐標系統的時候貌似僅僅提到過UIKIT坐標,OPGL坐標,事實上還有個相對坐標和世界坐標
我們在講完這個實列之後再介紹。如今先這樣寫著)
這裏另一句
CCRect rect=CCRectMake(-spriteSize.width/2,-spriteSize.height/2,spriteSize.width,spriteSize.height);
非常納悶為什麽是 -spriteSize.width/2
剛開始我也非常郁悶,根本看不懂。後來直接盯著這段代碼不眨眼盯了半小時,瞬間懂了,
我們學習坐標系統都知道默認錨點是在中心點吧?精靈也是
我們得求出左下角點的x和y坐標,然後後面兩個參數都懂的
如果精靈是40X40的圖片,錨點在中心,所以中心點為0,0坐標 然後四個角的坐標如上圖。
如今我們要的出左下角的坐標,瞬間懂了嗎??
如今我們幾乎相同完畢一半了。事實上我們在CCTouchEnded方法中完畢我們的跳躍效果,可是這僅僅是單擊跳躍。多連擊還是得我們自己實現
#ifndef _Human_H_ #include "cocos2d.h" USING_NS_CC; class Human:public CCSprite,public CCTouchDelegate { public: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void onEnter(); virtual void onExit(); //創建靜態方法,用於創建Human精靈 static Human* create(const char *pszFileName); //推斷觸摸點是否在精靈範圍內 bool containsTouchLocation(CCTouch *pTouch); //構造方法,初始化變量 Human(); //單擊調用 void SignleClicked(float dt); //雙擊 void DoubleClicked(float dt); //三連擊 void ThreeClicked(); private: //記錄點擊的次數 int clickedCount; }; #endif // !_Human_H_
這裏添加了些方法
//構造方法,初始化變量 Human::Human():clickedCount(0) {} //單擊調用 void Human::SignleClicked(float dt){ if (clickedCount==1) { clickedCount=0; CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,50,1); this->runAction(jumpto); } } //雙擊 void Human::DoubleClicked(float dt){ if (clickedCount==2) { clickedCount=0; CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,120,1); this->runAction(jumpto); } } //三連擊 void Human::ThreeClicked(){ clickedCount=0; CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,220,1); this->runAction(jumpto); }
方法的實現大致是這樣,推斷變量的值,假設是1則運行單擊跳躍高度為50。後面的不說了
接著我們在ccTouchEnded函數中用延遲的一個方法來實現各種點擊
void Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { if (!containsTouchLocation(pTouch)) { return; } //假設點擊在精靈上,則運行 if (clickedCount==2) { ThreeClicked(); } else if (clickedCount==1) { //延遲0.25秒運行雙擊 scheduleOnce(schedule_selector(Human::DoubleClicked),0.25f); clickedCount++; } else { //延遲0.25秒運行單擊 scheduleOnce(schedule_selector(Human::SignleClicked),0.25f); clickedCount++; } }
這裏邏輯有點轉只是來,
如果。我們點擊一次,它將會運行最後的else 。而單擊的方法要在0.25秒後才運行可是此時變量的值已經為1了
然後我們在0.25秒的時間內在繼續點擊,它將運行第二個IF中的語句。同理,雙擊的方法也要在0.25秒後運行,可是此時變量的值已經是2了
這個大家多斷點。自己多想想,說不清楚
OK,截止我們的多連擊已經搞定了
總結一下:
首先。我們學會了怎樣制定自己的精靈
怎樣使自己的精靈能處理觸屏事件
理解怎樣完畢處理觸屏事件的幾個步驟
怎樣推斷觸摸點是否是點擊在指定的矩形區域中,這個非常重要哦
利用計時器延遲巧妙實現處理多連擊事件
(還有哪些不懂的代碼。自己能夠先baidu一下)
附源代碼
Cocos2D-X2.2.3學習筆記8(處理精靈單擊、雙擊和三連擊事件)