cocos2dx 触摸测试一 单点和多点
2013-12-28 20:59
316 查看
打开刚创建的项目TouchesTest,等待xcode完成索引。
点击左上角向右箭头编译运行[快捷键CMD+R],注意运行的scheme是当前项目》模拟器,见下图。(默认的可能是cocos2dx》iOS Device,修改一下)
View Code
CMD+左键点击 CCSprite去看看父类的这个方法都干了什么。
点进去后是CCSprite.h文件,找到static CCSprite* create(const char *pszFileName)这个方法,光标移动到create上,右键Jump to Definition转到定义,CCSprite.cpp。
我们拷贝CCSprite的这个方法的定义,照葫芦画瓢去MySprite定义我们的create方法
这回HelloWorldScene.cpp不报错了,运行一下。可以看到图片出来了,但是触摸没反应,控制台也没有log。
因为我们的触摸事件压根就没有注册。
MySprite.h中声明方法:
virtual void onEnter();
virtual void onExit();
这两个方法从何而来呢,我们去查查CCSprite的API。http://www.cocos2d-x.org/reference/native-cpp/V2.2.1/d4/de7/classcocos2d_1_1_c_c_sprite.html
CMD+F输入onEnter找到方法,我们可以看到这个方法是CCSprite从CCNode继承而来的。具体这两个方法干什么用,大家google一下吧。
去MySprite.cpp中定义这两个方法
运行一下,我们可以在控制台看到打印了onEnter。
修改这两个方法:
在此运行,点图片并拖拽,发现控制台多了一些打印信息。
将ccTouchBegan方法return true再试试。另外,分别注释掉多点和单点的事件注册,再各种试。
需要注意的一点是,ccTouchBegan方法返回结果会导致的不同情况。
可以这样,我们在触摸图片内部的时候,使用单点系列事件,触摸图片以外的区域使用多点系列事件。(其实多点是包含单点的,刚才各种试的时候你应该能发现,因为我想,你应该和我一样只用了一个鼠标....那么,单点拖动多点缩放时都可以在图片内部区域实现的,我们下一篇再说吧)
那么怎么判断触点在图片内外呢?
修改ccToucheBegan方法
在此运行,看看图片内外的触摸是否和我们想的一样。
我们现在来实现,图片的拖动。
修改ccToucheMoved方法
我们现在来实现,多点图片的缩放。
思路:我们就实现两指吧,在began的时候记录两指的距离并记录下来,比如名字为beganDistance,move的时候在实时计算距离,比如名字叫moveDistance。
moveDistance/beganDistance就是缩放比啦。
在MySprite.h的文件后面声明一个float变量
修改cpp的ccTouchesBegan方法
修改cpp的ccTouchesMoved方法
运行试一下,这要用真机了呀~
两指测试发现没啥反应,那应该是两指判断这里出现了问题。
两个方法的刚开始位置加上打印看看
再试,发现参数中只有一个点。想,这不应该啊,一定是哪里有设置没有开启多点。
搜一下,找到原因。
在左侧导航树ios/AppController.mm文件,方法
中开启,加入一行代码
再试。先不管图片缩放效果行不行,先看控制台日志输出,1,2,3,4,5个手指都有日志。
OK,缩放有问题,那就是写的不对呗。来一起看看
改了改,缩放效果凑合实现了,但是不够达标
最后这点算法和效果都不好,就不在继续修改了,
主要是两个手指不同时触摸,即一前一后先后到屏幕上,这时候touchesBegan执行了2次单点并未算出新的_beganDistance,而执行touchesMove的时候用的还是上一次move最后的_beganDistance,导致突然放大或者缩小。
下一篇换个办法。
点击左上角向右箭头编译运行[快捷键CMD+R],注意运行的scheme是当前项目》模拟器,见下图。(默认的可能是cocos2dx》iOS Device,修改一下)
// // MySprite.h // TouchesTest // // Created by HanHongmin on 13-12-28. // // #ifndef __TouchesTest__MySprite__ #define __TouchesTest__MySprite__ #include "cocos2d.h" using namespace cocos2d; class MySprite:public CCSprite,public CCTouchDelegate{ public: static MySprite* create(const char *pszFileName); virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); // optional virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); // optional virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent); }; #endif /* defined(__TouchesTest__MySprite__) */
View Code
CMD+左键点击 CCSprite去看看父类的这个方法都干了什么。
点进去后是CCSprite.h文件,找到static CCSprite* create(const char *pszFileName)这个方法,光标移动到create上,右键Jump to Definition转到定义,CCSprite.cpp。
我们拷贝CCSprite的这个方法的定义,照葫芦画瓢去MySprite定义我们的create方法
MySprite* MySprite::create(const char* pszFileName){ MySprite *pobSprite = new MySprite(); if (pobSprite && pobSprite->initWithFile(pszFileName)) { pobSprite->autorelease(); return pobSprite; } CC_SAFE_DELETE(pobSprite); return NULL; }
这回HelloWorldScene.cpp不报错了,运行一下。可以看到图片出来了,但是触摸没反应,控制台也没有log。
因为我们的触摸事件压根就没有注册。
MySprite.h中声明方法:
virtual void onEnter();
virtual void onExit();
这两个方法从何而来呢,我们去查查CCSprite的API。http://www.cocos2d-x.org/reference/native-cpp/V2.2.1/d4/de7/classcocos2d_1_1_c_c_sprite.html
CMD+F输入onEnter找到方法,我们可以看到这个方法是CCSprite从CCNode继承而来的。具体这两个方法干什么用,大家google一下吧。
去MySprite.cpp中定义这两个方法
void MySprite::onEnter(){ CCLog("onEnter"); } void MySprite::onExit(){ CCLog("onExit"); }
运行一下,我们可以在控制台看到打印了onEnter。
修改这两个方法:
void MySprite::onEnter(){ CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);//多点触控 CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);//单点触控 CCSprite::onEnter(); } void MySprite::onExit(){ CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); CCSprite::onExit(); }
在此运行,点图片并拖拽,发现控制台多了一些打印信息。
将ccTouchBegan方法return true再试试。另外,分别注释掉多点和单点的事件注册,再各种试。
需要注意的一点是,ccTouchBegan方法返回结果会导致的不同情况。
可以这样,我们在触摸图片内部的时候,使用单点系列事件,触摸图片以外的区域使用多点系列事件。(其实多点是包含单点的,刚才各种试的时候你应该能发现,因为我想,你应该和我一样只用了一个鼠标....那么,单点拖动多点缩放时都可以在图片内部区域实现的,我们下一篇再说吧)
那么怎么判断触点在图片内外呢?
修改ccToucheBegan方法
bool MySprite::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){ CCLog("ccTouchBegan"); CCRect rect = this->boundingBox(); if(rect.containsPoint(pTouch->getLocation())){ CCLog("ccTouchBegan in Img"); return true; }else{ CCLog("ccTouchBegan out of Img"); return false; } }
在此运行,看看图片内外的触摸是否和我们想的一样。
我们现在来实现,图片的拖动。
修改ccToucheMoved方法
void MySprite::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent){ CCLog("ccTouchMoved"); 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); }
我们现在来实现,多点图片的缩放。
思路:我们就实现两指吧,在began的时候记录两指的距离并记录下来,比如名字为beganDistance,move的时候在实时计算距离,比如名字叫moveDistance。
moveDistance/beganDistance就是缩放比啦。
在MySprite.h的文件后面声明一个float变量
protected: float _beganDistance;
修改cpp的ccTouchesBegan方法
void MySprite::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){ CCDictionary* touchesDic = CCDictionary::create(); CCSetIterator iter = pTouches->begin(); for (; iter != pTouches->end(); iter++){ CCTouch* pTouch = (CCTouch*)(*iter); touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); } //两个手指 if (touchesDic->count() == 2){ CCLog("****ccTouchesBegan*"); 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(); _beganDistance = ccpDistance(pt,pt2); } }
修改cpp的ccTouchesMoved方法
void MySprite::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){ CCDictionary* touchesDic = CCDictionary::create(); CCSetIterator iter = pTouches->begin(); for (; iter != pTouches->end(); iter++){ CCTouch* pTouch = (CCTouch*)(*iter); touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); } //两个手指 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); this->setScale(this->getScale()*(moveDistance/_beganDistance)); } }
运行试一下,这要用真机了呀~
两指测试发现没啥反应,那应该是两指判断这里出现了问题。
两个方法的刚开始位置加上打印看看
CCLog("ccTouchesMoved touches point count:%i",pTouches->count());
再试,发现参数中只有一个点。想,这不应该啊,一定是哪里有设置没有开启多点。
搜一下,找到原因。
在左侧导航树ios/AppController.mm文件,方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中开启,加入一行代码
[__glView setMultipleTouchEnabled:YES];
再试。先不管图片缩放效果行不行,先看控制台日志输出,1,2,3,4,5个手指都有日志。
OK,缩放有问题,那就是写的不对呗。来一起看看
改了改,缩放效果凑合实现了,但是不够达标
void MySprite::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){ CCLog("ccTouchesBegan touches point count:%i",pTouches->count()); CCDictionary* touchesDic = CCDictionary::create(); CCSetIterator iter = pTouches->begin(); for (; iter != pTouches->end(); iter++){ CCTouch* pTouch = (CCTouch*)(*iter); touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); } //两个手指 if (touchesDic->count() == 2){ 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(); 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(); for (; iter != pTouches->end(); iter++){ CCTouch* pTouch = (CCTouch*)(*iter); touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); } //两个手指 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"); } } }
最后这点算法和效果都不好,就不在继续修改了,
主要是两个手指不同时触摸,即一前一后先后到屏幕上,这时候touchesBegan执行了2次单点并未算出新的_beganDistance,而执行touchesMove的时候用的还是上一次move最后的_beganDistance,导致突然放大或者缩小。
下一篇换个办法。
相关文章推荐
- cocos2dx 触摸测试三 优先级及阻止传递
- cocos2dx ScrollView 测试一 触摸事件优先级和自动调整
- cocos2dx 触摸测试二 多点包含单点
- cocos2dx 触摸测试四 Armature
- cocos2dx 3.x 自学笔记 <二> cocos2dx 中注册触摸事件touchEvent 2.x 与 3.x
- cocos2dx、cocostudio的一些技术讨论一:触摸吞噬
- 【Cocos2dx】触摸事件
- Cocos2dx 3.0 过渡篇(三) 触摸机制
- cocos2d-Lua05体验引擎测试用例+定时任务+触摸事件
- cocos2dx 3.2 触摸
- Cocos2dx-3.x触摸事件之实现人机交互(二)
- COCOS2DX3.0的3种触摸响应机制
- cocos2dx3.0的触摸优先级和触摸屏蔽问题
- quick-cocos2dx lua语言讲解 (动作,定时器,触摸事件,工程的类的讲解)
- cocos2dx 屏幕滑动(ScrollViewDelegate、TableViewDelegate)和屏幕触摸响应
- Cocos2dx 3.0 过渡篇(三) 触摸机制
- android view触摸事件传递机制测试
- cocos2dx 3.x 屏幕触摸事件的认识
- Cocos2dx 3.6.1运行html5的测试例子
- cocos2dx 接受触摸事件