紧接上一篇,现在我们去掉单点触摸的注册,仅使用多点触摸来实现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__) */
MySprite.cpp
1 // 2 // MySprite.cpp 3 // TouchesTest 4 // 5 // Created by HanHongmin on 13-12-28. 6 // 7 // 8 9 #include "MySprite.h" 10 11 MySprite* MySprite::create(const char* pszFileName){ 12 MySprite *pobSprite = new MySprite(); 13 if (pobSprite && pobSprite->initWithFile(pszFileName)) 14 { 15 pobSprite->autorelease(); 16 return pobSprite; 17 } 18 CC_SAFE_DELETE(pobSprite); 19 return NULL; 20 } 21 22 void MySprite::onEnter(){ 23 CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);//多点触控 24 //CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);//单点触控 25 CCSprite::onEnter(); 26 } 27 void MySprite::onExit(){ 28 CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); 29 CCSprite::onExit(); 30 } 31 32 33 // optional 34 void MySprite::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){ 35 //CCLog("ccTouchesBegan touches point count:%i",pTouches->count()); 36 } 37 void MySprite::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){ 38 CCLog("ccTouchesMoved touches point count:%i",pTouches->count()); 39 CCDictionary* touchesDic = CCDictionary::create(); 40 CCSetIterator iter = pTouches->begin(); 41 CCRect rect = this->boundingBox(); 42 for (; iter != pTouches->end(); iter++){ 43 CCTouch* pTouch = (CCTouch*)(*iter); 44 if(rect.containsPoint(pTouch->getLocation())){ 45 touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); 46 } 47 } 48 CCArray* keys = touchesDic->allKeys(); 49 //两个手指 50 if (touchesDic->count() == 2){ 51 //CCLog("****ccTouchesMoved*"); 52 CCArray* keys = touchesDic->allKeys(); 53 CCTouch *touch1 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString()); 54 CCTouch *touch2 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(1))->getCString()); 55 56 CCPoint p1End = touch1->getLocation(); 57 CCPoint p2End = touch2->getLocation(); 58 CCPoint p1Start = touch1->getPreviousLocation(); 59 CCPoint p2Start = touch2->getPreviousLocation(); 60 61 float startDistance = ccpDistance(p1Start,p2Start); 62 float endDistance = ccpDistance(p1End,p2End); 63 64 //CCLog("startDistance:%f,endDistance:%f",startDistance,endDistance); 65 float scale = this->getScale()*(endDistance/startDistance); 66 if(scale<0.5f){ 67 scale = 0.5f; 68 }else if(scale>3.0f){ 69 scale = 3.0f; 70 } 71 this->setScale(scale); 72 }else if(touchesDic->count() ==1){//单点 73 CCTouch *pTouch = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString()); 74 CCPoint start = pTouch->getPreviousLocation(); 75 CCPoint end = pTouch->getLocation(); 76 //计算位移,直接使用point充当position的话,会有偏差,比如点住图片的一角进行拖动,setPosition的时候是依据AnchorPoint进行设置的 77 CCPoint sub = ccpSub(end, start); 78 CCPoint newPosition = ccpAdd(this->getPosition(),sub); 79 this->setPosition(newPosition); 80 } 81 } 82 void MySprite::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent){ 83 //CCLog("****ccTouchesEnded*"); 84 } 85 void MySprite::ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent){ 86 //CCLog("****ccTouchesCancelled*"); 87 }