• cocos2dx 触摸测试二 多点包含单点


    紧接上一篇,现在我们去掉单点触摸的注册,仅使用多点触摸来实现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

    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 }
    View Code
    我是cocos2dx初学者,Java5年,一点C++,OC经验都没有,各位见笑了 文章中如有错误或者不全面或者有更好的解决办法,请指出,不胜感激
  • 相关阅读:
    网络数据处理
    进程间通信和网络
    附加的操作系统服务
    通用操作系统服务
    UIScrollView 子控件的自动布局经验
    UIImage 添加水印
    数据类型
    ios 获取手机的IP地址
    UILAbel 设置了attributedText 后省略号不显示
    swift
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3496011.html
Copyright © 2020-2023  润新知