紧接上一篇,现在我们去掉单点触摸的注册,仅使用多点触摸来实现Sprite的拖拽和缩放

删除单点触摸对应的方法声明和定义,onEnter中取消单点触摸事件的注册

修改ccTouchesBegan方法,我们把在图片范围内的触摸视为有效触摸。当有一个指头在图片内,另一个在图片外,我们就将其视为单点触摸。

void MySprite::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){
    CCLog("ccTouchesBegan touches point count:%i",pTouches->count());
    CCDictionary* touchesDic = CCDictionary::create();
    CCSetIterator iter = pTouches->begin();
    CCRect rect = this->boundingBox();
    
    for (; iter != pTouches->end(); iter++){
        CCTouch* pTouch = (CCTouch*)(*iter);
        if(rect.containsPoint(pTouch->getLocation())){
            touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString());
        }
    }
    CCArray* keys = touchesDic->allKeys();
    //两个手指
    if (touchesDic->count() >= 2){//多于2点,只取前两点为有效点
        
        CCTouch *touch1 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString());
        CCTouch *touch2 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(1))->getCString());
        
        CCPoint pt = touch1->getLocation();
        CCPoint pt2 = touch2->getLocation();
        if(pt.x==pt2.x&&pt.y==pt2.y){
            CCLog("两点一样");
            return;
        }
        _beganDistance = ccpDistance(pt,pt2);
        CCLog("****ccTouchesBegan,distance:%f",_beganDistance);
    }
}
void MySprite::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){
    //CCLog("ccTouchesMoved touches point count:%i",pTouches->count());
    CCDictionary* touchesDic = CCDictionary::create();
    CCSetIterator iter = pTouches->begin();
    CCRect rect = this->boundingBox();
    for (; iter != pTouches->end(); iter++){
        CCTouch* pTouch = (CCTouch*)(*iter);
        if(rect.containsPoint(pTouch->getLocation())){
            touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString());
        }
    }
    CCArray* keys = touchesDic->allKeys();
    //两个手指
    if (touchesDic->count() == 2){
        //CCLog("****ccTouchesMoved*");
        CCArray* keys = touchesDic->allKeys();
        CCTouch *touch1 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString());
        CCTouch *touch2 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(1))->getCString());
        
        CCPoint pt = touch1->getLocation();
        CCPoint pt2 = touch2->getLocation();
        
        float moveDistance = ccpDistance(pt,pt2);
        CCLog("_beganDistance:%f,moveDistance:%f",_beganDistance,moveDistance);
        if(_beganDistance!=0){
            CCLog("curScale:%f,change:%f",this->getScale(),moveDistance/_beganDistance);
            this->setScale(this->getScale()*(moveDistance/_beganDistance));
            _beganDistance = moveDistance;
        }else{
            CCLog("开始距离为0");
        }
    }else if(touchesDic->count() ==1){//单点
        CCTouch *pTouch = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString());
        CCPoint start = pTouch->getPreviousLocation();
        CCPoint end = pTouch->getLocation();
        //计算位移,直接使用point充当position的话,会有偏差,比如点住图片的一角进行拖动,setPosition的时候是依据AnchorPoint进行设置的
        CCPoint sub = ccpSub(end, start);
        CCPoint newPosition = ccpAdd(this->getPosition(),sub);
        this->setPosition(newPosition);
    }
}

开模拟器试一下单点,拖动没啥问题

在真机上试一下缩放,和上一篇的效果基本无异,注意触点得在图片内。

 

下面我们尝试改善一下缩放效果,上一篇的有点问题,就是程序初始化的时候_beganDistance是零,而这时二指不同时触摸的话,调用了两次ccTouchesBegan,都是一个点的参数,_beganDistance还是零。而后面的情况,_beganDistance会保留上一次缩放的值,导致如果第二次二指间距离和上一次差距过大的话,图片会被骤然缩放。

我们是否可以按照单点的方式来做呢?压根就不要在ccTouchesBegan中设置这个值了。试试吧

ccTouchesBegan方法中程序直接注释掉,修改ccTouchesMoved方法,如下:

void MySprite::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){
    CCLog("ccTouchesBegan touches point count:%i",pTouches->count());
}
void MySprite::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){
    CCLog("ccTouchesMoved touches point count:%i",pTouches->count());
    CCDictionary* touchesDic = CCDictionary::create();
    CCSetIterator iter = pTouches->begin();
    CCRect rect = this->boundingBox();
    for (; iter != pTouches->end(); iter++){
        CCTouch* pTouch = (CCTouch*)(*iter);
        if(rect.containsPoint(pTouch->getLocation())){
            touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString());
        }
    }
    CCArray* keys = touchesDic->allKeys();
    //两个手指
    if (touchesDic->count() == 2){
        //CCLog("****ccTouchesMoved*");
        CCArray* keys = touchesDic->allKeys();
        CCTouch *touch1 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString());
        CCTouch *touch2 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(1))->getCString());
        
        CCPoint p1End = touch1->getLocation();
        CCPoint p2End = touch2->getLocation();
        CCPoint p1Start = touch1->getPreviousLocation();
        CCPoint p2Start = touch2->getPreviousLocation();
        
        float startDistance = ccpDistance(p1Start,p2Start);
        float endDistance = ccpDistance(p1End,p2End);
        
        CCLog("startDistance:%f,endDistance:%f",startDistance,endDistance);
        this->setScale(this->getScale()*(endDistance/startDistance));
    }else if(touchesDic->count() ==1){//单点
        CCTouch *pTouch = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString());
        CCPoint start = pTouch->getPreviousLocation();
        CCPoint end = pTouch->getLocation();
        //计算位移,直接使用point充当position的话,会有偏差,比如点住图片的一角进行拖动,setPosition的时候是依据AnchorPoint进行设置的
        CCPoint sub = ccpSub(end, start);
        CCPoint newPosition = ccpAdd(this->getPosition(),sub);
        this->setPosition(newPosition);
    }
}

OK,去真机上试一下。                    

:目      尚未发现其他问题。

再限制一下缩放比例。如最小0.5,最大3。

最终代码如下:

MySprite.h

 1 //
 2 //  MySprite.h
 3 //  TouchesTest
 4 //
 5 //  Created by HanHongmin on 13-12-28.
 6 //
 7 //
 8 
 9 #ifndef __TouchesTest__MySprite__
10 #define __TouchesTest__MySprite__
11 
12 #include "cocos2d.h"
13 using namespace cocos2d;
14 
15 class MySprite:public CCSprite,public CCTouchDelegate{
16 public:
17     static MySprite* create(const char *pszFileName);
18     
19     virtual void onEnter();
20     virtual void onExit();
21     
22     // optional
23     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
24     virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
25     virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
26     virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);
27 protected:
28     //float _beganDistance;
29 };
30 
31 #endif /* defined(__TouchesTest__MySprite__) */
View Code

相关文章: