cocos2d-x 多点触控实现缩放及相关问题的解决方法
#ifndef __loading__MoreTouches__ #define __loading__MoreTouches__ #include <iostream> #include "cocos2d.h" USING_NS_CC; class MoreTouches :public CCLayer { public: bool init(); //virtual void registerWithTouchDispather(void); //由于是继承自CCLayer,这个方法就不用重写了,但下面几个方法还是要重写滴 virtual void ccTouchesCancellnd(CCSet *pTouches,CCEvent *pEvent); virtual void ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent);//注意这个方法和单点触控方法的返回类型不同 virtual void ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent); virtual void ccTouchesMoved(CCSet *pTouches,CCEvent *pEvent); static CCScene *scene(); virtual void onEnter(); virtual void onExit(); CREATE_FUNC(MoreTouches); public: double distance; //两个触摸点之间的距离 double deltax; //目标x轴的改变值 double deltay; //目标y轴的改变值 CCSprite *bg; //目标精灵 double mscale; //初始地图缩放比例 }; #endif /* defined(__loading__MoreTouches__) */
#include "MoreTouches.h" bool MoreTouches::init() { if(!CCLayer::init()) { return false; } bg=CCSprite::create("fullbg.png"); //初始化目标图片 this->addChild(bg); mscale=1.0; //初始化图片的缩放比例 return true; } //void MoreTouches::registerWithTouchDispather() //{ // CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0); //} void MoreTouches::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) { if(pTouches->count()>=2) //如果触摸点不少于两个 { CCSetIterator iter=pTouches->begin(); CCPoint mPoint1=((CCTouch *)(*iter))->getLocationInView(); mPoint1 = CCDirector::sharedDirector()->convertToGL(mPoint1); iter++; CCPoint mPoint2=((CCTouch *)(*iter))->getLocationInView(); mPoint2 = CCDirector::sharedDirector()->convertToGL(mPoint2); distance=sqrt((mPoint2.x-mPoint1.x)*(mPoint2.x-mPoint1.x)+(mPoint2.y-mPoint1.y)*(mPoint2.y-mPoint1.y));//计算两个触摸点距离 deltax = (mPoint1.x + mPoint2.x)/2 - bg->getPositionX(); //得到两个触摸点中点和精灵锚点的差值 deltay = (mPoint1.y + mPoint2.y)/2 - bg->getPositionY(); CCLog("ccTouchesBegan ..."); } } void MoreTouches::ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) { if(pTouches->count()>=2) //如果移动时触摸点的个数不少于两个 { CCSetIterator iter = pTouches->begin(); CCPoint mPoint1 = ((CCTouch*)(*iter))->getLocationInView(); mPoint1 = CCDirector::sharedDirector()->convertToGL(mPoint1); iter++; CCPoint mPoint2 = ((CCTouch*)(*iter))->getLocationInView(); mPoint2 = CCDirector::sharedDirector()->convertToGL(mPoint2); //获得新触摸点两点之间的距离 double mdistance = sqrt((mPoint1.x-mPoint2.x)*(mPoint1.x-mPoint2.x)+(mPoint1.y-mPoint2.y)*(mPoint1.y-mPoint2.y)); mscale = mdistance/distance * mscale; // 新的距离 / 老的距离 * 原来的缩放比例,即为新的缩放比例 distance = mdistance; bg->setScale(mscale); double x = (mPoint2.x+mPoint1.x)/2 - deltax; //计算两触点中点与精灵锚点的差值 double y = (mPoint2.y+mPoint1.y)/2 - deltay; bg->setPosition(ccp(x,y)); //保持两触点中点与精灵锚点的差值不变 deltax = (mPoint1.x+ mPoint2.x)/2 - bg->getPositionX(); //计算新的偏移量 deltay = (mPoint2.y + mPoint1.y)/2 - bg->getPositionY(); CCLog("ccTouchMoved ...."); } if(pTouches->count()==1) //如果触摸点为一个 { CCSetIterator iter = pTouches->begin(); CCPoint mPoint=((CCTouch*)(*iter))->getLocationInView(); mPoint=CCDirector::sharedDirector()->convertToGL(mPoint); //坐标转换 bg->setPosition(mPoint); //直接移动精灵 } } void MoreTouches::ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) { } void MoreTouches::ccTouchesCancellnd(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) { } CCScene *MoreTouches::scene() { CCScene *scene=CCScene::create(); MoreTouches *layer=MoreTouches::create(); scene->addChild(layer); return scene; } void MoreTouches::onEnter() { CCLayer::onEnter(); setTouchEnabled(true);CCLog("onenter"); } void MoreTouches::onExit() { CCLayer::onExit(); CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); //移除触摸代理 }
首先要实现缩放这个逻辑,在ccTouchesBegan中检测,如果触摸点的个数大于两个,那么取前两个点,使用两点距离公式计算两点距离,在ccTouchesMoved中检测,如果触摸点的个数大于两个,那么继续计算这两个点的距离,然后通过距离,计算得到缩放比例,调用setScale设置缩放比例即可。
另外,除了缩放处理外,还需要处理位置问题,在ccTouchesBegan中计算两个触点的中点位置和精灵锚点的差,在ccTouchesMoved中,随着缩放,保持两触点中点和精灵锚点的差不变即可,ccTouchesEnded和ccTouchesCancelled中不需要修改。
接下来,就重点说下在实现时遇到的问题吧,主要就一个,就是当在ios模拟器中操作时,我按着option键,可以出现两个点,但程序中始终只能得到一个点,即count=1,
移动时也根本不能实现缩放。后来,终于谷歌出结果了,原来需要修改ios目录下的 AppController.mm文件
static AppDelegate s_sharedApplication; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. // Add the view controller's view to the window and display. window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; EAGLView *__glView = [EAGLView viewWithFrame: [window bounds] pixelFormat: kEAGLColorFormatRGBA8 depthFormat: GL_DEPTH_COMPONENT16 preserveBackbuffer: NO sharegroup: nil multiSampling: NO numberOfSamples:0 ]; // Use RootViewController manage EAGLView viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil]; viewController.wantsFullScreenLayout = YES; viewController.view = __glView; // Set RootViewController to window if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0) { // warning: addSubView doesn't work on iOS6 [window addSubview: viewController.view]; } else { // use this method on ios6 [window setRootViewController:viewController]; } [window makeKeyAndVisible]; [[UIApplication sharedApplication] setStatusBarHidden: YES]; cocos2d::CCApplication::sharedApplication()->run(); [__glView setMultipleTouchEnabled:YES]; //主要就是这句了 return YES; }
补充:移动开发 , 其他 ,