上一篇我們介紹了如何給你自定義的CCSprite添加Touch監聽,但是你會發現無論你點擊屏幕的哪里,我們的精靈都會收到Touch事件,為什么會這樣呢,主要是CCTouchDispatcher只是實現觸摸事件分發,所以每一個添加到CCTouchDispatcher上的CCTouchDelegate,都是一層,屏幕大小,這也是為什么有時候我們點擊到層的外面也能接受到Touch監聽的原因。不管怎么說,這是我們不想看到的。其實這里cocos2dx的源代碼中已經給出了解決辦法,那就是CCMenu,看看它的源代碼你會發現它是做了判斷Touch區域的操作。我們這里也這么做。代碼如下
bool TestSprite::isInSprite(CCTouch *theTouch){
// 返回當前觸摸位置在OpenGL坐標
CCPoint touchPoint=theTouch->getLocation();
// 將世界坐標轉換為當前父View的本地坐標系
CCPoint reallyPoint=this->getParent()->convertToNodeSpace(touchPoint);
// 獲取當前基於父view的坐標系
CCRect rect=this->boundingBox();
// CCnode->convertToNodeSpace 或者 convertToWorldSpace 是基於當前Node的 與當前Node相關
if(rect.containsPoint(reallyPoint)){
return true;
}
returnfalse;
}
這樣子我們就能知道我們點擊是不是我們的精靈了。下面我們來判斷雙擊。代碼如下
// 獲取當前時間 精確到毫秒數
static inline long millisecondNow()
{
struct cc_timeval now;
CCTime::gettimeofdayCocos2d(&now, NULL);
return (now.tv_sec * 1000 + now.tv_usec / 1000);
}
// 判斷是不是 雙擊
static inline bool isDoubleTouch(){
static long lastTouchTime=0;
long thisTouchTime=millisecondNow();
if(abs(thisTouchTime-lastTouchTime)<250){
lastTouchTime=0;
return true;
}
else{
lastTouchTime=millisecondNow();
return false;
}
}
就是簡單的做一下兩次點擊的時間間隔,如果小於250毫米,就算做雙擊。單機我們給解決了,那么現在就是長按了,長安其實也是很簡單就是,如果你touch的時間長於兩秒,那么我們算做它長按。或不多說,上代碼
void TestSprite::checkLongPress(){
this->unschedule(schedule_selector(TestSprite::checkLongPress));
if (isInTouch&&!isInMove) {
CCLog("LONGLONG");
this->setScale(2);
this->setOpacity(200);
afterLongPress=true;
}
}
bool TestSprite::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent){
if (this->isInSprite(pTouch)) {
isInTouch=true;
if (isDoubleTouch()) {
this->doubleClickSprite();
this->touchBeginTime=millisecondNow();
}else{
this->singleClickSprite();
this->touchBeginTime=millisecondNow();
this->schedule(schedule_selector(TestSprite::checkLongPress), 2);
}
return true;
}
returnfalse;
}
void TestSprite::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {
CCPoint deltaPoint=pTouch->getDelta();
CCLog("x=%f,y=%f",deltaPoint.x,deltaPoint.y);
if(fabs(deltaPoint.x)>1||fabs(deltaPoint.y)>1){
isInMove=true;
}
}
void TestSprite::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
isInTouch=false;
isInMove=false;
afterLongPress=false;
// 恢復 精靈
this->setScale(1);
this->setPosition(orignalPoint);
this->setOpacity(255);
}
void TestSprite::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent){
isInTouch=false;
isInMove=false;
afterLongPress=false;
// 恢復 精靈
this->setScale(1);
this->setPosition(orignalPoint);
this->setOpacity(255);
}
當然我們這里也是做了一個簡單的判斷,如果touch了一直沒有move超過兩秒我們才算做長按的。